Reputation: 1138
I'm working with django channels
and I have a problem about how to deal with sending a message using channels
Context
I have 2 containers: celery-worker
and api
, I want to send data via websockets from celery-worker
container to the browser through api
container using channels
, here a picture:
Question
Do you know how to "initialize" channels in api
container and use this channels inside celery-worker
container? to after in celery-worker
container call only to Group('pablo').send(message)
and it automatically send to the browser.
Any advice will be ok.
Note: I tried to not post code because is very extensive and maybe It would result difficult to understand the question but if you want I can post some code that you need.
Upvotes: 6
Views: 1446
Reputation: 5839
I have created the example (with simple tasks) that is using Celery and Django Channels 2 (github). Celery worker is sending to channel layer messages. Messages are broadcasted to clients that are connected to websocket.
On server side I have consumer:
class TasksConsumer(AsyncWebsocketConsumer):
async def connect(self):
# One group name for all clients: 'tasks'
self.group_name = 'tasks'
await self.channel_layer.group_add(self.group_name, self.channel_name)
await self.accept()
async def disconnect(self, close_code):
await self.channel_layer.group_discard(self.group_name, self.channel_name)
async def receive(self, text_data):
pass
async def task_update_message(self, event):
# Send message to channel
await self.send(json.dumps(event))
You can see that the group name is 'tasks'. On celery side, worker is calling:
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)("tasks", msg)
To use channels in worker code, you need to set django settings:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'server.settings')
import django
django.setup()
Hope it helps!
Upvotes: 1
Reputation: 2868
You need to let know other containers that you depend on them. Example. Here you see that PostgreSQL has dependencies from user_service and notification_service you need to add this for each container that wants to use other containers either linked or dependant. here is an example.
version: '3'
services:
db:
image: postgres
ports:
- '5434:5434'
user_service:
build: ""
environment:
- JWT_SECRET=mysecret_json_web_token_pass
command: python user/app.py
volumes:
- .:/microservices
ports:
- "9001:9001"
depends_on:
- db
notification_service:
build: ""
environment:
- JWT_SECRET=mysecret_json_web_token_pass
command: python notification/app.py
volumes:
- .:/microservices
ports:
- "9002:9002"
depends_on:
- db
for your case you might want to add depends_on: - celery - redis
You can also stablish a local network.. but Rather than doing that I created containers in the same docker-compose that way they know eachother.
Here is another example
version: '2'
services:
nginx:
image: nginx:latest
container_name: nx01
ports:
- "8001:8001"
volumes:
- ../src:/src
- ./static:/static
- ./media:/media/
- ./config/nginx:/etc/nginx/conf.d
depends_on:
- web
web:
build: .
container_name: dg01
command: gunicorn mydjango.wsgi 0.0.0.0:8000
depends_on:
- db
links:
- redis
volumes:
- ../src:/src
- ./static:/static
- ./media:/media/
expose:
- "8001"
db:
image: postgres:latest
container_name: pq01
ports:
- "5432:5432"
redis:
image: redis:latest
container_name: rd01
ports:
- '6379:6379'
celery:
build: .
container_name: cl01
command: celery worker --app=app.tasks
volumes:
- ..:/src
links:
- db
- redis
to call it on your code... use it like this.
CELERY_BROKER_URL = 'redis://redis:6379/0'
CELERY_RESULT_BACKEND = 'redis://redis:6379/0'
Upvotes: 0