This commit is contained in:
Andros Fenollosa 2024-11-07 16:20:51 +01:00
parent d8ffe60909
commit bbcdbafba0
5 changed files with 63 additions and 8 deletions

View File

@ -43,11 +43,14 @@ INSTALLED_APPS = [
'channels', # Servidor de WebSockets 'channels', # Servidor de WebSockets
] ]
REDIS_HOST = "redis"
REDIS_PORT = 6379
CHANNEL_LAYERS = { CHANNEL_LAYERS = {
"default": { "default": {
"BACKEND": "channels_redis.core.RedisChannelLayer", "BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": { "CONFIG": {
"hosts": [("redis", 6379)], "hosts": [(REDIS_HOST, REDIS_PORT)],
}, },
}, },
} }
@ -61,8 +64,8 @@ HUEY = {
'utc': False, 'utc': False,
'blocking': True, 'blocking': True,
'connection': { 'connection': {
'host': 'redis', 'host': REDIS_HOST,
'port': 6379, 'port': REDIS_PORT,
'db': 0, 'db': 0,
'connection_pool': None, 'connection_pool': None,
'read_timeout': 1, 'read_timeout': 1,

View File

@ -1,14 +1,19 @@
import json import json
import redis
from django.conf import settings
from channels.generic.websocket import WebsocketConsumer from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync from asgiref.sync import async_to_sync
from waiting_room.tasks import calculate_min_distance from waiting_room.tasks import calculate_min_distance, run_tasks_from_queue, render_location_in_the_queue, notify_of_new_position
class MyConsumer(WebsocketConsumer): class MyConsumer(WebsocketConsumer):
redis_conn = redis.StrictRedis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=0)
def connect(self): def connect(self):
self.room_group_name = self.scope["url_route"]["kwargs"]["room_name"] self.room_group_name = self.scope["url_route"]["kwargs"]["room_name"]
async_to_sync(self.channel_layer.group_add)(self.room_group_name, self.channel_name) async_to_sync(self.channel_layer.group_add)(self.room_group_name, self.channel_name)
self.accept() self.accept()
notify_of_new_position()
def disconnect(self, close_code): def disconnect(self, close_code):
async_to_sync(self.channel_layer.group_discard)(self.room_group_name, self.channel_name) async_to_sync(self.channel_layer.group_discard)(self.room_group_name, self.channel_name)
@ -16,11 +21,15 @@ class MyConsumer(WebsocketConsumer):
def receive(self, text_data): def receive(self, text_data):
json_data = json.loads(text_data) json_data = json.loads(text_data)
# Echo
self.send(text_data=text_data)
# Run task # Run task
if json_data['task'] == 'calculate': if json_data['task'] == 'calculate':
calculate_min_distance(self.room_group_name) # Check if the new task is already in the queue
if self.redis_conn.lrange('enqueue', 0, -1).count(self.room_group_name.encode()) == 0:
# Add the task to the queue
self.redis_conn.rpush('enqueue', self.room_group_name)
notify_of_new_position()
# Send accurate location in the queue
run_tasks_from_queue()
def channel_message(self, event): def channel_message(self, event):
message = event['message'] message = event['message']

View File

@ -1,4 +1,6 @@
from huey.contrib.djhuey import task from django.conf import settings
import redis
from huey.contrib.djhuey import task, lock_task
import operator import operator
from django.template.loader import render_to_string from django.template.loader import render_to_string
from itertools import permutations from itertools import permutations
@ -8,6 +10,7 @@ from math import factorial
from channels.layers import get_channel_layer from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync from asgiref.sync import async_to_sync
def render_progress_bar(group_name, progress, result=None): def render_progress_bar(group_name, progress, result=None):
channel_layer = get_channel_layer() channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)( async_to_sync(channel_layer.group_send)(
@ -21,6 +24,18 @@ def render_progress_bar(group_name, progress, result=None):
} }
) )
def render_location_in_the_queue(group_name, location):
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
group_name,
{
'type': 'channel_message',
'message': render_to_string('components/tasks/location.html', {
'location': location,
}),
}
)
@task() @task()
def calculate_min_distance(group_name): def calculate_min_distance(group_name):
# Distance matrix between cities # Distance matrix between cities
@ -72,3 +87,25 @@ def calculate_min_distance(group_name):
return shortest_route return shortest_route
return calculate_shortest_route(distances) return calculate_shortest_route(distances)
@task()
@lock_task('run-queue-lock')
def run_tasks_from_queue():
notify_of_new_position()
# Get the first task from the queue
redis_conn = redis.StrictRedis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=0)
task = redis_conn.lindex('enqueue', 0)
if task:
# Run task
r = calculate_min_distance(task.decode('utf-8'))
# Wait for task to finish
r(blocking=True)
# Run the next task
redis_conn.lpop('enqueue')
run_tasks_from_queue()
@task()
def notify_of_new_position():
redis_conn = redis.StrictRedis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=0)
for index, group_name in enumerate(redis_conn.lrange('enqueue', 0, -1)):
render_location_in_the_queue(group_name.decode('utf-8'), index )

View File

@ -9,6 +9,7 @@
background: lightgray; background: lightgray;
"> ">
{% include 'components/tasks/update.html' %} {% include 'components/tasks/update.html' %}
{% include 'components/tasks/location.html' %}
</section> </section>
<script> <script>
document.querySelector('#component-notification').setAttribute('ws-connect', '/ws/' + localStorage.getItem('userId') + '/'); document.querySelector('#component-notification').setAttribute('ws-connect', '/ws/' + localStorage.getItem('userId') + '/');

View File

@ -0,0 +1,5 @@
<div id="component-notification__location">
{% if location > 0 %}
<p>You have {{ location }} persons in front of you.</p>
{% endif %}
</div>