I'm not sure why that would happen - the code that chooses what application instance to use is here: https://github.com/django/asgiref/blob/master/asgiref/server.py (under get_or_create_application_instance).
If you're always using a single channel name, which gets passed as scope_id (see here: https://github.com/django/channels/blob/master/channels/worker.py), it really should be returning the same instance. I recommend you poke around in there and do some debugging to figure out what's going on.
Andrew
On Fri, Jun 22, 2018 at 9:46 AM itsnate_b <nathan.bluvol@gmail.com> wrote:
I am only using one channel name and my expectation is that only one instance of the background worker class should be initiated/used. Instead, I am seeing a new class being initiated for each call routed to the background worker class. This is unexpected...--
On Thursday, June 21, 2018 at 3:55:23 PM UTC-4, Andrew Godwin wrote:The worker server tries to keep one application instance open per incoming channel name, but that's no guarantee. It will always make a new instance for different channel names. What kind of behaviour are you expecting?AndrewOn Tue, Jun 19, 2018 at 6:45 AM itsnate_b <nathan...@gmail.com> wrote:I am using Django 2.0.5, Python 3.6.2, Django Channels 2.1.1, aiohttp 3.1.3.--I have created a background worker class which is initialized on a route to the appropriate event/function. Problem is that it initializes a *new* instance of the class on every triggered call, meaning that I cannot access contextual variables (they don't persist). Is there a way to trigger the same (i.e. first) and only class repeatedly on each routed call? I can change it all to function calls with global variables stored for the relevant asyncio futures and/or booleans, but would really prefer not to do that....any suggestions?My (simplified) code:consumers.pyfrom channels.generic.websocket import AsyncWebsocketConsumerfrom channels.consumer import AsyncConsumerfrom channels.layers import get_channel_layerimport jsonimport asyncioimport aiohttpimport datetimeclass mainConsumer(AsyncWebsocketConsumer):async def connect(self):await self.channel_layer.group_add('myGroup', self.channel_name)await self.accept()async def disconnect(self, closeCode):await self.channel_layer.group_discard('myGroup', self.channel_name)async def receive(self, text_data):eventData = json.loads(text_data)print(eventData)if eventData['toggle'] == 'on':await self.channel_layer.send('myToggle',{"type": "openConnection"})elif eventData['toggle'] == 'off':await self.channel_layer.send('myToggle',{"type": "closeConnection"})async def myUpdate(self, data):updateMsg = #some data processing hereawait self.send(text_data=json.dumps(updateMsg))class backgroundConsumer(AsyncConsumer):def __init__(self, scope):self.scope = scopeself.turnOnListener = Trueself.channelLayer = get_channel_layer()self.t1 = Noneprint('inside init') # this will print init on every channel_layer.send to 'myToggle' in mainConsumerasync def listen(self):async with aiohttp.ClientSession() as session:async with session.ws_connect('...streaming url...', ssl=False) as ws:await ws.send_str('...some string...')async for msg in ws:if msg.type == aiohttp.WSMsgType.TEXT:if msg.data.startswith('2'):await ws.send_str('3')else:await self.parseListenData(msg)async def parseListenData(self, msgContent):
# process and create updateMsg dict with type: 'myUpdate' (so that it gets to the myUpdate function in main Consumer)await self.channelLayer.group_send('myGroup', updateMsg)async def openConnection(self, event):if(self.turnOnListener): # THIS IS ALWAYS TRUE BECAUSE THE ROUTE INITIALIZES A NEW INSTANCE OF THIS CLASS!!await self.channelLayer.group_add('myGroup',self.channel_name,)self.turnOnListener = False # This only changes it for the current instance (obviously)loop = asyncio.get_event_loop()self.t1 = asyncio.run_coroutine_threadsafe(self.listen(), loop=loop)else:print('already turned on listener')async def closeConnection(self, event):loop = asyncio.get_event_loop()loop.call_soon_threadsafe(self.t1.cancel) # t1 is always None because the route initialized a new instance of this class!!
routing.pyfrom channels.auth import AuthMiddlewareStackfrom channels.routing import ProtocolTypeRouter, URLRouter, ChannelNameRouterimport dashboard.routingfrom dashboard.consumers import backgroundConsumerapplication = ProtocolTypeRouter({# (http->django views is added by default)'websocket': AuthMiddlewareStack(URLRouter(dashboard.routing.websocket_urlpatterns)),'channel': ChannelNameRouter({"myToggle": backgroundConsumer,}),})
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/431ada54-74cb-4822-9b33-5dcb0326fb9c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/541378d0-6e7d-43ea-9b08-016aefd38702%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CAFwN1ur_%3DTM64aa8D8q5wMhD1ntohNDTYVvX60P-1%3Dh9TMBrVA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
No comments:
Post a Comment