Implemented mongodb schema for messaging #48#105
Conversation
| @@ -37,7 +37,15 @@ services: | |||
| test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] | |||
There was a problem hiding this comment.
Please check if Docker is working properly.
Replacement: $$ is only escaped in bash, but here it is necessary for Docker to interpret environment variables correctly. That is, leave one $.
There was a problem hiding this comment.
Add healthcheck for MongoDB (optional)
healthcheck:
test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet
interval: 10s
retries: 5
| room.participants.append(user_pk) | ||
| room.updated_at = timezone.now() | ||
|
|
||
| room.save() |
There was a problem hiding this comment.
Missing await in room.save() and Message(...).save()
MongoEngine .save() is not an asynchronous function. In asynchronous code, this can block the event loop.
Solution: move from async def to a separate sync_to_async block:
from asgiref.sync import sync_to_async
@sync_to_async
def save_room_and_message(room, user_pk, text):
room.save()
Message(
room=room,
sender_id=user_pk,
text=text,
timestamp=timezone.now()
).save()
There was a problem hiding this comment.
And in receive():
await save_room_and_message(room, user_pk, text)
There was a problem hiding this comment.
No channel_layer check
Although rare, self.channel_layer can be None if Redis (or another backend) is not configured.
if not self.channel_layer:
await self.send(text_data="No channel layer configured.")
return
| user_pk = user.pk | ||
|
|
||
| room = Room.objects(room_id=self.room_id).first() | ||
|
|
There was a problem hiding this comment.
Repetitive code in Room logic can be moved to a helper function for cleanliness:
@sync_to_async
def get_or_update_room(room_id, user_pk):
room = Room.objects(room_id=room_id).first()
if not room:
room = Room(room_id=room_id, participants=[user_pk])
else:
if user_pk not in room.participants:
room.participants.append(user_pk)
room.updated_at = timezone.now()
room.save()
return room
| room_id = me.StringField(primary_key=True, required=True) | ||
| participants = me.ListField(me.IntField(), default=list, required=True) | ||
| created_at = me.DateTimeField(required=True, default=timezone.now) | ||
| updated_at = me.DateTimeField(required=True, default=timezone.now) |
There was a problem hiding this comment.
Adding auto_now for updated_at makes your logic store updated_at manually, but it's easy to forget. It's worth creating a "hook" to make this happen automatically.
def save(self, *args, **kwargs):
self.updated_at = timezone.now()
return super().save(*args, **kwargs)
| ] | ||
| } | ||
| room = me.ReferenceField(Room, required=True, reverse_delete_rule=me.CASCADE) | ||
| sender_id = me.IntField(required=True) |
There was a problem hiding this comment.
Use ReferenceField for sender_id if users are stored in Mongo — it's worth:
sender = me.ReferenceField(User, required=True)
| "db_alias": "chat", | ||
| "collection": "messages", | ||
| "indexes": [ | ||
| {"fields": ["room", "timestamp"]}, |
There was a problem hiding this comment.
This is good, but you can also add something "-" to quickly sort backwards in time:
{"fields": ["room", "-timestamp"]}
| sender_id = me.IntField(required=True) | ||
| text = me.StringField(required=True) | ||
| timestamp = me.DateTimeField(required=True, default=timezone.now) | ||
|
No newline at end of file |
There was a problem hiding this comment.
If there is default=timezone.now, then required=True is not required.
There was a problem hiding this comment.
AuthMiddlewareStack already tries to authenticate via session or cookie, but if you are working exclusively with JWT via query param, then AuthMiddlewareStack may be unnecessary.
If you are definitely not using cookie-based login:
"websocket": JwtAuthMiddleware(
URLRouter(websocket_urlpatterns)
)
This will speed up the authorization of WebSocket requests and reduce unnecessary load.
docker-compose.ymlandsettings.pyfor mongoDB usagerouting.pyfor better use and added path for rooms; updated requirements.txtmodels_mongo.pywith Room and Message modelsconsumers.pywith configuredChatConsumerto manage WebSocket connections and messagesmiddleware.pywithJwtAuthMiddlewareto manage if users that are connecting to rooms via WebSocket are authenticated (registered and logged in==obtained token)asgi.pywithJwtAuthMiddlewareto validate?token=on connecttested in postman:
checking history using mongoDB extension in VisualStudio: