Giter VIP home page Giter VIP logo

Comments (16)

gawel avatar gawel commented on June 3, 2024

You cant really use multiprocessing with asyncio. You'll lost the event loop. I guess that's your problem.

from panoramisk.

raj2569 avatar raj2569 commented on June 3, 2024

Is there any best practice or example I can follow to run two instances of panoramisk together (which is assuming, I need two instances, to run events and action simultaneously)

I have searched a lot, but there really isn't much out there, and not much guidance in general and wrt panoramisk specifically.

from panoramisk.

gawel avatar gawel commented on June 3, 2024

I think there is no benefits to have more than on instance per process since they will use the same event loop. Why an instance is not enough for you ? Is the event loop lagging due to high traffic ?

You can try to use two instance with two event loop (in two different thread). But this is really painfull

from panoramisk.

romkazor avatar romkazor commented on June 3, 2024

Is there any best practice or example I can follow to run two instances of panoramisk together (which is assuming, I need two instances, to run events and action simultaneously)

Yon dont need two instances of panoramisk if you use one asterisk, if asterisk more than one:

import asyncio

from panoramisk.manager import Manager


manager_local = ...
manager_remote = ...


async def ami_local_callback(mngr, msg):
    print(msg)


async def ami_remote_callback(mngr, msg):
    print(msg)


def main():
    manager_local.register_event('*', callback=ami_local_callback)
    manager_remote.register_event('*', callback=ami_remote_callback)
    manager_local.connect()
    manager_remote.connect()

    try:
        manager_local.loop.run_forever()
    except KeyboardInterrupt:
        manager_remote.close()
        manager_local.loop.close()


if __name__ == '__main__':
    main()

from panoramisk.

raj2569 avatar raj2569 commented on June 3, 2024

I think there is no benefits to have more than on instance per process since they will use the same event loop. Why an instance is not enough for you ? Is the event loop lagging due to high traffic ?

My requirement is to listen continuously to events from Asterisk, and send an action once every minute and process the result of both. I only have one Asterisk server, and action/response and events has to come from it.

I could not find a means to do both, simultaneously, in same event loop, which is why I thought of running two event loops.

From the answers I now understand that single event loop is sufficient for simultaneously listening for events and sending actions and getting its response. But so far I am unable to figure out how.

from panoramisk.

raj2569 avatar raj2569 commented on June 3, 2024

Yon dont need two instances of panoramisk if you use one asterisk

Thanks for the reply, I only have one asterisk, but want both events and actions response from it, continuously.

Going through the example, I know how to listen to events, and send actions and get response. But could not figure out how to combine both in a single program.

from panoramisk.

romkazor avatar romkazor commented on June 3, 2024

But could not figure out how to combine both in a single program.

@manager.register_event('*')
def callback(manager, message):
    if message.Event == 'FullyBooted':
        response = await manager.send_action({'Action': 'Status'})
        print(response)
    elif message.Event == 'Hangup':
        response = await manager.send_action({'Action': 'Status'})
        print(response)

from panoramisk.

raj2569 avatar raj2569 commented on June 3, 2024
@manager.register_event('*')
def callback(manager, message):
    if message.Event == 'FullyBooted':
        response = await manager.send_action({'Action': 'Status'})
        print(response)
    elif message.Event == 'Hangup':
        response = await manager.send_action({'Action': 'Status'})
        print(response)```

Thanks for this example.

One problem I see with this is that, for firing actions, I need an incoming event like FullyBooted or Hangup and will not work if I need to send action once every minute (for example).

One work around I can think of is to send a Ping action at the beginning and on receiving the reply send my action, sleep for a minute and then send ping again.

If there are no better way, I can settle for this.

from panoramisk.

romkazor avatar romkazor commented on June 3, 2024

One problem I see with this is that, for firing actions, I need an incoming event like FullyBooted or Hangup and will not work if I need to send action once every minute (for example).

you can use aiocron for this and send action every 1,30,60, etc seconds

from panoramisk.

streltsovdenis avatar streltsovdenis commented on June 3, 2024
loop_manager = asyncio.get_event_loop()

manager = Manager(
    loop=loop_manager,
    host=HOST,
    port=PORT,
    username=USERNAME,
    secret=SECRET
)


@manager.register_event('*')
def callback(manager, message):
    print(message)


async def ping():
    while True:
        await manager.connect()
        response = await manager.send_action({'Action': 'Ping'})
        print(response)
        await asyncio.sleep(5)


def main():
    manager.connect()
    try:
        loop_manager.create_task(ping())
        manager.loop.run_forever()
    except KeyboardInterrupt:
        manager.loop.close()


if __name__ == '__main__':
    main()

from panoramisk.

romkazor avatar romkazor commented on June 3, 2024

Very bad example.

from panoramisk.

raj2569 avatar raj2569 commented on June 3, 2024

I think I got this correctly. The code works fine, but not sure if there is some non obvious errors.

import asyncio
import logging
from pprint import pprint
from panoramisk import Manager

class EventsListener:
    def __init__(self, options):
        self.loop = asyncio.get_event_loop()
        self.queue = asyncio.Queue()
        self.manager = Manager(loop=self.loop, **options)
        self.manager.log.addHandler(logging.NullHandler())
        self.manager.register_event("*", self.handle_events)

    async def handle_message(self):
        while True:
            message = await self.queue.get()
            pprint (message)
            self.queue.task_done()

    async def handle_actions(self):
        while True:
            response = await self.manager.send_action({'Action': 'Status'})
            self.queue.put_nowait(response)
            await asyncio.sleep(10)

    async def handle_events(self, manager, message):
        event = message.event
        await self.queue.put(event)

    async def connect(self):
        await self.manager.connect()
        t1 = asyncio.create_task(self.handle_message())
        t2 = asyncio.create_task(self.handle_actions())
        await t1
        await t2

    def run(self):
        self.loop.run_until_complete(self.connect())
        self.loop.run_forever()

If this is correct, I will make a PR with a clean running example, so that others don't have to waste time reinventing this.

from panoramisk.

gawel avatar gawel commented on June 3, 2024

I dont really understand why you need a queue with events/responses. It's weird to mix both in the same queue. Also you should try/expept in while True loops to avoid failures.

from panoramisk.

raj2569 avatar raj2569 commented on June 3, 2024

I dont really understand why you need a queue with events/responses.

Its easy to process all the events and action responses in a single place. Having an async queue will also let the receive loop of panoramisk run with out any block, as all processing is happening at the other end of the queue. It is bit weird to have two types of messages from the queue, but I find it easier to handle both of them together.

Also you should try/expept in while True loops to avoid failures.

Yes, this was meant to be a simple example code illustrating the technique.

Shall I raise a PR for including this in examples/?

from panoramisk.

gawel avatar gawel commented on June 3, 2024

Yeah sure. Why not

from panoramisk.

ludovic-gasc avatar ludovic-gasc commented on June 3, 2024

Hi @raj2569,

I confirm that you can use the same Panoramisk instance to send actions and receive events.
The only theoretical drawback you might have is that if you have a very long blocking statement in your treatment (CPU or blocking I/O) AND you are very sensitive to execute quickly a piece of code when you receive a specific event, it might be a problem, but I never had this situation from my professional life.

In case of you are in this situation, you might use an external queue, that could be a Redis, PostgreSQL, RabbitMQ or Kafka queue, to have another processes to handle it, but, again, you will increase the complexity of your technical stack.

Based on the content of this issue, the original question seems answered, I'm closing it.
Don't hesitate to re-open in case of extra question.

Have a nice week-end !

from panoramisk.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.