Closed k4ml closed 7 years ago
I'm wondering if there's an event we can listen to know ring_ready is done ...
Hey @k4ml. Glad you (somewhat) figured it out. So answering in order:
time.sleep(5.5)
is fine but will block the event loop. So if you plan on processing concurrent calls there will be a backup as new calls will be stalled until previous ones which are still sleeping are completed.asyncio
(as in #54) and I've been slow to the draw with getting that in. I've thought about trying to implement it myself for py2 (much like twisted's inlineCallbacks) but I'd frankly rather just jump to py3's proper coroutines. Do you need py2?ring_ready
and I believe the handler here show's how to do it.Another approach is to simply delay your answer by scheduling it to happen in the future using FreeSWITCH's internal scheduler. The caveat with this is that you'll probably want to write a separate answer handler:
class Phone(object):
@event_callback('CHANNEL_PARK')
def on_park(self, sess):
print(sess)
logger.info(sess)
if not sess.is_inbound():
sess.hangup()
sess.broadcast('ring_ready::', 'aleg')
sess.broadcast("answer::", delay=5.5)
@event_callback('CHANNEL_ANSWER')
def on_answer(self, sess):
if sess.is_inbound():
sess.playback('http://a.clyp.it/b3byghjf.mp3')
I realize having all these handlers doesn't scale well and makes the code hard to read and understand (which is the motivation for using asyncio
and coroutines and which I really want to get done soon). Unfortunately (or fortunately?), switchy
was originally built for stress testing and it was easier to just delegate to FreeSWITCH's internal scheduler instead of trying to get performance out of python at the inset; so the callback system was good enough. If you'd like this feature soon I can do my best to hack out something for next week.
Let me know about the py3 vs. 2 thing and we can move forward from there!
@tgoodlet Fortunately, we already on Python 3 right now. I've been looking at asyncio too lately so it would be great if we can put it into practice.
@tgoodlet If we can't run blocking operations in the event handler, how do we run blocking function like accessing external HTTP endpoint from the event handler ? Spawn a thread ?
I've also figured out today we can't run execute()
from inside thread when handling channel_park
. This is using python-ESL lib directly, not switchy.
@k4ml to do blocking stuff in the event loop we for sure need to add and use asyncio
.
For our purposes we've been using the non-blocking mod_commands
which has worked well enough but of course more generally we need a Python side solution for handling blocking code.
So for right now, yes, you may have to spawn a thread or write your own future mechanism unfortunately.
With regard to execute()
, do you need it?
You should be able to use broadcast()
to accomplish all your app running needs no?
Also as I mentioned before, feel free to make a PR to expose execute
through switchy
if you really need it :)
I'm not sure yet about execute()
. broadcast()
seem to work for now.
On the non-blocking issue, I think even spawning a thread won't help since I still need to get the return value of the function running inside thread, which mean it will block again. The whole stack, starting from switchy need to be non-blocking.
I think even spawning a thread won't help since I still need to get the return value of the function running inside thread, which mean it will block again. The whole stack, starting from switchy need to be non-blocking.
@k4ml yes agreed it does and hence asyncio
.
In the interim you can use something like requests-futures
if you want to do the request non-blocking in the event loop.
I will push hard on trying to get asyncio
support going on a development branch over the the next week or so.
@k4ml since this was a question and is I'm closing.
I've started asyncio
progress on my own fork and I'll track that using #54.
Notes: Originally wrote this thinking it's a bug but then managed to figure out myself but I decided to post it through as a notes and question on best approach.
For handling incoming calls, our practice is to ring twice and stay silent for 2 seconds before answering it. We manage to accomplish this via ring_ready and sleep command. So I try to accomplish the same thing with switchy:-
That however didn't work, it went immediately to playback. Looking at the log, the command was executed. Comparing it with our working freeswitch instance also look the same command executed inside freeswitch. Only then I realized that we're handling incoming calls through outbound socket in sync mode.
Since switchy is inbound socket and everything asynchronous, it mean
sess.answer()
was executed immediately, leaving no room for the ring_ready. So I try sleeping in python instead:-And it work ! Not sure if this is the best way so I appreciate if there's better approach to handle this.