Skip to content

Commit

Permalink
Update websocket consumer
Browse files Browse the repository at this point in the history
  • Loading branch information
h-yaqub committed Feb 27, 2023
1 parent fabb995 commit 9f41daf
Show file tree
Hide file tree
Showing 13 changed files with 69 additions and 65 deletions.
28 changes: 5 additions & 23 deletions app/consumers.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,15 @@
import json

from channels.db import database_sync_to_async
from channels.exceptions import StopConsumer
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.generic.websocket import AsyncJsonWebsocketConsumer

from app import models

class NotificationsConsumer(AsyncJsonWebsocketConsumer):
groups = ["notification"]

class MyAsyncWebSocketConsumer(AsyncWebsocketConsumer):
async def connect(self):
print("Web socket connected")
print("Channel layer ", self.channel_layer)
print("Channel name", self.channel_name)
await self.accept()
user = await database_sync_to_async(models.User.objects.get)(
email=self.scope["user"].username
)
self.group_name = user.first_name
print(self.group_name)
await self.channel_layer.group_add(self.group_name, self.channel_name)

async def receive(self, text_data=None, bytes_data=None):
print("Message recieved from client...", text_data)

async def notification_send(self, event):
print(event)
await self.send(text_data=json.dumps({"msg": event["message"]}))

async def disconnect(self, close_code):
print("Web socket disconnect")
await self.channel_layer.group_discard(self.group_name, self.channel_name)
raise StopConsumer()
async def push(self, event):
await self.send_json(content={"notifications": event["message"]})
14 changes: 14 additions & 0 deletions app/management/commands/test_notify.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from django.core.management.base import BaseCommand

from app.utils import push_notification


class Command(BaseCommand):
help = "Send Test Alert to Websocket"

def handle(self, *args, **options):
msg = "Sending test notifications"

push_notification(msg)

self.stdout.write(self.style.SUCCESS("Done"))
4 changes: 2 additions & 2 deletions app/routing.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.urls import path
from django.urls import re_path

from . import consumers

websocket_urlpatterns = [
path("ws/awc/", consumers.MyAsyncWebSocketConsumer.as_asgi()),
re_path(r"ws/notifications/$", consumers.NotificationsConsumer.as_asgi()),
]
23 changes: 13 additions & 10 deletions app/templates/app/api/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,25 @@
{% block js_includes %}{% endblock %}
{% render_bundle 'main' 'js' %}
<script>
var ws = new WebSocket('ws://127.0.0.1:8000/ws/awc/')
ws.addEventListener('open',()=>{
console.log("WebSocket connection open..")
var ws = new WebSocket(
'ws://'
+ window.location.host
+ '/ws/notifications/'
);
ws.addEventListener('open', () => {
console.log("WebSocket connection open..");
})

ws.addEventListener('message',(event)=>{
console.log("Message recieved from server..", event.data)
//console.log(event.data)
ws.addEventListener('message', (event) => {
console.log("Message recieved from server..", JSON.parse(event.data));
})

ws.addEventListener('error',(event)=>{
console.log("Websocket error occured..", event)
ws.addEventListener('error', (event) => {
console.log("Websocket error occured..", event);
})

ws.addEventListener('close',(event)=>{
console.log("Websocket connection closed..", event)
ws.addEventListener('close', (event) => {
console.log("Websocket connection closed..", event);
})
</script>
</body>
Expand Down
9 changes: 9 additions & 0 deletions app/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import boto3
from asgiref.sync import async_to_sync
from botocore.exceptions import ClientError
from channels.layers import get_channel_layer
from django.conf import settings
from django.core.mail import send_mail
from django.template.loader import render_to_string
Expand Down Expand Up @@ -82,3 +84,10 @@ def create_presigned_url(bucket_name, key, expiration=3600):

# The response contains the presigned URL
return response


def push_notification(message):
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
"notification", {"type": "push", "message": message}
)
15 changes: 7 additions & 8 deletions app/views/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

import requests
import slack
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from django.conf import settings
from django.contrib.auth import authenticate, login, update_session_auth_hash
from django.contrib.auth.tokens import PasswordResetTokenGenerator
Expand All @@ -30,7 +28,12 @@
from waffle import get_waffle_switch_model

from app import models, serializers
from app.utils import create_presigned_url, send_email_forget_password, send_leave_email
from app.utils import (
create_presigned_url,
push_notification,
send_email_forget_password,
send_leave_email,
)
from app.views import mixins
from project.settings import SLACK_ATTENDACE_CHANNEL, SLACK_SIGNING_SECRET, SLACK_TOKEN

Expand Down Expand Up @@ -764,11 +767,7 @@ def update(self, request, *args, **kwargs):
user = employee.user.first_name
status = request.data["status"]
message = user + ", Your leave has been " + status
print(message)
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
user, {"type": "notification.send", "message": message}
)
push_notification(message)
notification = models.Notification(user=employee.user, message=message)
notification.save()
return response
Expand Down
5 changes: 5 additions & 0 deletions docker-compose.staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ services:
- ./env.db
volumes:
- db_data:/var/lib/postgresql/data

redis:
image: redis:7.0-alpine
expose:
- 6379

app:
build:
Expand Down
4 changes: 4 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ services:
volumes:
- db_data:/var/lib/postgresql/data

redis:
image: redis:7.0-alpine

app:
build:
context: .
Expand All @@ -23,6 +26,7 @@ services:
- .:/opt/code
depends_on:
- db
- redis

availability:
build:
Expand Down
2 changes: 2 additions & 0 deletions env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=
AWS_STORAGE_BUCKET_NAME=
REDIS_HOST="redis"
REDIS_PORT=6379
20 changes: 2 additions & 18 deletions frontend/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -4843,14 +4843,10 @@
},
"max_hours_per_week": {
"type": "integer",
"maximum": 32767,
"minimum": -32768,
"nullable": true
},
"expected_hours_per_week": {
"type": "integer",
"maximum": 32767,
"minimum": -32768,
"nullable": true
},
"updated_at": {
Expand Down Expand Up @@ -5152,14 +5148,10 @@
},
"salary": {
"type": "integer",
"maximum": 2147483647,
"minimum": 0,
"nullable": true
},
"leave_count": {
"type": "integer",
"maximum": 2147483647,
"minimum": -2147483648
"type": "integer"
},
"user_allowed": {
"type": "boolean"
Expand All @@ -5176,14 +5168,10 @@
},
"weekly_available_hours": {
"type": "integer",
"maximum": 2147483647,
"minimum": -2147483648,
"nullable": true
},
"monthly_available_hours": {
"type": "integer",
"maximum": 2147483647,
"minimum": -2147483648,
"nullable": true
},
"availability_last_msg": {
Expand Down Expand Up @@ -5340,14 +5328,10 @@
},
"salary": {
"type": "integer",
"maximum": 2147483647,
"minimum": 0,
"nullable": true
},
"leave_count": {
"type": "integer",
"maximum": 2147483647,
"minimum": -2147483648
"type": "integer"
},
"user_allowed": {
"type": "boolean"
Expand Down
5 changes: 4 additions & 1 deletion project/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from django.core.asgi import get_asgi_application

import app.routing
Expand All @@ -21,6 +22,8 @@
application = ProtocolTypeRouter(
{
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(URLRouter(app.routing.websocket_urlpatterns)),
"websocket": AllowedHostsOriginValidator(
AuthMiddlewareStack(URLRouter(app.routing.websocket_urlpatterns))
),
}
)
4 changes: 2 additions & 2 deletions project/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@
# Application definition

INSTALLED_APPS = [
"daphne",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"daphne",
"django.contrib.staticfiles",
"django.contrib.sites",
# Internal Apps
Expand Down Expand Up @@ -126,7 +126,7 @@
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("localhost", 6379)],
"hosts": [(env("REDIS_HOST"), env("REDIS_PORT"))],
},
},
}
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ factory-boy==3.2.1
gunicorn==20.1.0
Pillow==9.4.0
psycopg2==2.9.5
redis==4.5.1
requests==2.28.2
schedule==1.1.0
slackclient==2.9.4

0 comments on commit 9f41daf

Please sign in to comment.