mirror of
https://github.com/MarcZierle/photo-log-backend.git
synced 2025-04-12 15:24: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,
|
PhotoLogTemplateSerializer,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .photolog_generator import generate_photolog_from_latex
|
|
||||||
from .autocrop.autocrop import autocrop
|
|
||||||
|
|
||||||
from photo_log import tasks
|
from photo_log import tasks
|
||||||
|
|
||||||
from django.db.models import FileField
|
from django.db.models import FileField
|
||||||
|
@ -9,13 +9,21 @@ https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
|
|||||||
|
|
||||||
import os
|
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
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
import websocket.routing
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
||||||
django_asgi_app = get_asgi_application()
|
django_asgi_app = get_asgi_application()
|
||||||
|
|
||||||
#application = get_asgi_application()
|
#application = get_asgi_application()
|
||||||
application = ProtocolTypeRouter({
|
application = ProtocolTypeRouter({
|
||||||
"http": django_asgi_app,
|
"http": django_asgi_app,
|
||||||
|
"websocket": AuthMiddlewareStack(
|
||||||
|
URLRouter(
|
||||||
|
websocket.routing.websocket_urlpatterns
|
||||||
|
)
|
||||||
|
),
|
||||||
})
|
})
|
||||||
|
@ -51,6 +51,7 @@ INSTALLED_APPS = [
|
|||||||
'django_celery_results',
|
'django_celery_results',
|
||||||
|
|
||||||
# local
|
# local
|
||||||
|
'websocket',
|
||||||
'accounts',
|
'accounts',
|
||||||
'photo_log',
|
'photo_log',
|
||||||
'api',
|
'api',
|
||||||
@ -226,3 +227,19 @@ CACHES = {
|
|||||||
"KEY_PREFIX": "zierletraining",
|
"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.core.files import File
|
||||||
from django.apps import apps
|
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 django_tex.shortcuts import compile_template_to_pdf
|
||||||
|
|
||||||
from .photolog_layout import generate_tex
|
from .photolog_layout import generate_tex
|
||||||
@ -25,6 +28,16 @@ def chordfinisher(*args, **kwargs):
|
|||||||
return 'OK'
|
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
|
@shared_task
|
||||||
def download_s3_file(folder_path, s3_file_path, bucket):
|
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,
|
'photo_log', 'PhotoLog', photo_log.id,
|
||||||
'pdf', pdf_s3_path
|
'pdf', pdf_s3_path
|
||||||
),
|
),
|
||||||
|
notify_client.si(
|
||||||
|
description='update_photolog_pdf',
|
||||||
|
content={
|
||||||
|
'pdf': pdf_s3_path,
|
||||||
|
'id': photo_log.id
|
||||||
|
}
|
||||||
|
),
|
||||||
delete_folder.si(
|
delete_folder.si(
|
||||||
folder
|
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