mirror of
https://github.com/MarcZierle/photo-log-backend.git
synced 2025-04-04 11:54:38 +00:00
add websockets and connect celery worker to consumer
This commit is contained in:
parent
8ae78c5b91
commit
68df020da0
@ -20,9 +20,6 @@ from .serializers import (
|
||||
PhotoLogTemplateSerializer,
|
||||
)
|
||||
|
||||
from .photolog_generator import generate_photolog_from_latex
|
||||
from .autocrop.autocrop import autocrop
|
||||
|
||||
from photo_log import tasks
|
||||
|
||||
from django.db.models import FileField
|
||||
|
@ -9,13 +9,21 @@ https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
|
||||
|
||||
import os
|
||||
|
||||
from channels.routing import ProtocolTypeRouter
|
||||
from channels.auth import AuthMiddlewareStack
|
||||
from channels.routing import ProtocolTypeRouter, URLRouter
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
import websocket.routing
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
||||
django_asgi_app = get_asgi_application()
|
||||
|
||||
#application = get_asgi_application()
|
||||
application = ProtocolTypeRouter({
|
||||
"http": django_asgi_app,
|
||||
"websocket": AuthMiddlewareStack(
|
||||
URLRouter(
|
||||
websocket.routing.websocket_urlpatterns
|
||||
)
|
||||
),
|
||||
})
|
||||
|
@ -51,6 +51,7 @@ INSTALLED_APPS = [
|
||||
'django_celery_results',
|
||||
|
||||
# local
|
||||
'websocket',
|
||||
'accounts',
|
||||
'photo_log',
|
||||
'api',
|
||||
@ -226,3 +227,19 @@ CACHES = {
|
||||
"KEY_PREFIX": "zierletraining",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Django Channels - Channel Layers Backend
|
||||
# See https://channels.readthedocs.io/en/stable/topics/channel_layers.html
|
||||
# See https://pypi.org/project/channels-redis/ for settings configuration
|
||||
|
||||
CHANNEL_LAYERS = {
|
||||
"default": {
|
||||
"BACKEND": "channels_redis.core.RedisChannelLayer",
|
||||
"CONFIG": {
|
||||
"hosts": [("127.0.0.1", 6378)],
|
||||
"prefix": "asgi_zierle_training_staging:",
|
||||
"group_expiry": 7200,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
26
config/supervisor/daphne_supervisor.conf
Normal file
26
config/supervisor/daphne_supervisor.conf
Normal file
@ -0,0 +1,26 @@
|
||||
[fcgi-program:ws_zierle_training_staging]
|
||||
# TCP socket used by Nginx backend upstream
|
||||
socket=tcp://localhost:8001
|
||||
|
||||
user=www-data
|
||||
|
||||
# Directory where your site's project files are located
|
||||
directory=/home/marc/www-staging/backend
|
||||
|
||||
# Each process needs to have a separate socket file, so we use process_num
|
||||
# Make sure to update "mysite.asgi" to match your project name
|
||||
command=/home/marc/www-staging/backend/env/bin/python3 -m daphne -u /run/daphne/daphne%(process_num)d.sock --fd 0 --access-log - --proxy-headers config.asgi:application
|
||||
|
||||
# Number of processes to startup, roughly the number of CPUs you have
|
||||
numprocs=2
|
||||
|
||||
# Give each process a unique name so they can be told apart
|
||||
process_name=ws_zierle_training_staging%(process_num)d
|
||||
|
||||
# Automatically start and recover processes
|
||||
autostart=true
|
||||
autorestart=true
|
||||
|
||||
# Choose where you want your log to go
|
||||
stdout_logfile=/home/marc/www-staging/logs/daphne.log
|
||||
redirect_stderr=true
|
@ -10,6 +10,9 @@ from django.conf import settings
|
||||
from django.core.files import File
|
||||
from django.apps import apps
|
||||
|
||||
from channels.layers import get_channel_layer
|
||||
from asgiref.sync import async_to_sync
|
||||
|
||||
from django_tex.shortcuts import compile_template_to_pdf
|
||||
|
||||
from .photolog_layout import generate_tex
|
||||
@ -25,6 +28,16 @@ def chordfinisher(*args, **kwargs):
|
||||
return 'OK'
|
||||
|
||||
|
||||
@shared_task
|
||||
def notify_client(description, content):
|
||||
channel_layer = get_channel_layer()
|
||||
async_to_sync(channel_layer.group_send)("notifications", {
|
||||
"type": "task.finished",
|
||||
"description": description,
|
||||
"content": content
|
||||
})
|
||||
|
||||
|
||||
@shared_task
|
||||
def download_s3_file(folder_path, s3_file_path, bucket):
|
||||
"""
|
||||
@ -383,6 +396,13 @@ def generate_photo_log_chain(photo_log_id, work_folder_name=uuid4()):
|
||||
'photo_log', 'PhotoLog', photo_log.id,
|
||||
'pdf', pdf_s3_path
|
||||
),
|
||||
notify_client.si(
|
||||
description='update_photolog_pdf',
|
||||
content={
|
||||
'pdf': pdf_s3_path,
|
||||
'id': photo_log.id
|
||||
}
|
||||
),
|
||||
delete_folder.si(
|
||||
folder
|
||||
)
|
||||
|
0
websocket/__init__.py
Normal file
0
websocket/__init__.py
Normal file
3
websocket/admin.py
Normal file
3
websocket/admin.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
6
websocket/apps.py
Normal file
6
websocket/apps.py
Normal file
@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class WebsocketConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'websocket'
|
23
websocket/consumers.py
Normal file
23
websocket/consumers.py
Normal file
@ -0,0 +1,23 @@
|
||||
from channels.generic.websocket import JsonWebsocketConsumer
|
||||
|
||||
|
||||
class NotificationsConsumer(JsonWebsocketConsumer):
|
||||
groups = ['notifications']
|
||||
|
||||
def connect(self):
|
||||
self.accept()
|
||||
|
||||
|
||||
def disconnect(self, close_code):
|
||||
pass
|
||||
|
||||
|
||||
def receive_json(self, content):
|
||||
pass
|
||||
|
||||
|
||||
def task_finished(self, event):
|
||||
self.send_json({
|
||||
'type': event['description'],
|
||||
'content': event['content']
|
||||
})
|
8
websocket/routing.py
Normal file
8
websocket/routing.py
Normal file
@ -0,0 +1,8 @@
|
||||
from django.urls import re_path
|
||||
|
||||
from . import consumers
|
||||
|
||||
websocket_urlpatterns = [
|
||||
# change this for handling multiple users
|
||||
re_path(r'ws/notifications/', consumers.NotificationsConsumer.as_asgi()),
|
||||
]
|
Loading…
Reference in New Issue
Block a user