I am writing a web-application using websockets from django-channels. In which:
- Customer users can make orders from store users.
- When a user requests an order via their communicator, I create a channel group using the order's id.
- The store related to this order should be added to this channel group as well. This is what I'm struggling to achieve.
This logic can be seen in my pytest below:
async def test_store_is_added_to_order_group_on_create(self, settings):
customer = await create_customer()
store = await create_store()
product = await create_product(store=store)
store_communicator = await auth_connect(store)
# Log in as customer and create order
customer_communicator = await auth_connect(user)
await communicator.send_json_to({
'type': 'create.order',
'data': {
'product': str(product.id),
'customer': user.id
}
})
response = await communicator.receive_json_from()
data = response.get('data')
await communicator.disconnect()
# Send JSON message to new order's group.
order_id = data['id']
message = {
'type': 'echo.message',
'data': 'This is a test message.'
}
channel_layer = get_channel_layer()
await channel_layer.group_send(order_id, message=message)
# Store should receive JSON message from server.
response = await store_communicator.receive_json_from()
assert_equal(message, response)
await communicator.disconnect()
The communicator function create_order should create a new channel_layer group to which both the customer and store should be added.
async def create_order(self, event):
order = await self._create_order(event.get('data'))
order_id = f'{order.id}'
# Add the customer to a group identified by order's key value.
await self.channel_layer.group_add(
group=order_id,
channel=self.channel_name
)
# Confirm creation to customer.
await self.send_json({
'type': 'MESSAGE',
'data': order_data
})
Ideally, I want to call group_add with channel set to the store communicator's channel here but I do not know the store's channel name. Is there a way to know the store's channel name from the user's communicator instance?
I have made a workaround in which I send a message to the store's communicator BEFORE the above send_json as follows:
# HACK: Send notification to store
await self.channel_layer.group_send(group=store_group, message={
'type': 'notify.store',
'data': order_data
})
This calls a second simple communicator function for the store:
async def notify_store(self, event):
data = event.get('data')
await self.channel_layer.group_add(
group=data['id'],
channel=self.channel_name
)
This workaround does not work. The store is added to the group after the second echo.message is sent. The await self.channel_layer.group_send... does not wait until notify_store has been executed for the second communicator. Is there a way to guarantee this behaviour?
Or is there a completely different way to approach adding to different user's to a channel_layer group from one user's communicator?
Thank you for your time.