mirror of
https://github.com/hexolan/panels.git
synced 2026-03-26 20:41:15 +00:00
init comment-service
This commit is contained in:
@@ -0,0 +1 @@
|
||||
DROP TABLE IF EXISTS comments CASCADE;
|
||||
@@ -0,0 +1,11 @@
|
||||
CREATE TABLE comments (
|
||||
"id" serial PRIMARY KEY,
|
||||
|
||||
"post_id" varchar(64) NOT NULL,
|
||||
"author_id" varchar(64) NOT NULL,
|
||||
|
||||
"message" varchar(512) NOT NULL,
|
||||
|
||||
"created_at" timestamp NOT NULL DEFAULT timezone('utc', now()),
|
||||
"updated_at" timestamp
|
||||
);
|
||||
@@ -0,0 +1,94 @@
|
||||
from typing import List
|
||||
|
||||
from databases import Database
|
||||
|
||||
from comment_service.events.producer import CommentEventProducer
|
||||
from comment_service.models.exceptions import ServiceException, ServiceErrorCode
|
||||
from comment_service.models.service import CommentDBRepository, Comment, CommentCreate, CommentUpdate
|
||||
|
||||
|
||||
class ServiceDBRepository(CommentDBRepository):
|
||||
"""Database repository responsible for actions
|
||||
relating to the postgres database.
|
||||
|
||||
This repository will be utilised by other upstream repositories
|
||||
or the Kafka event consumers.
|
||||
|
||||
Attributes:
|
||||
_db (Database): The postgres database connection handler.
|
||||
_event_prod (CommentEventProducer): Used to dispatch events upon execution of a CRUD action.
|
||||
|
||||
"""
|
||||
def __init__(self, db: Database, event_producer: CommentEventProducer) -> None:
|
||||
self._db = db
|
||||
self._event_prod = event_producer
|
||||
|
||||
def _result_to_comment(self, result) -> Comment:
|
||||
return Comment(
|
||||
id=result.id,
|
||||
post_id=result.post_id,
|
||||
author_id=result.author_id,
|
||||
message=result.message,
|
||||
created_at=result.created_at,
|
||||
updated_at=result._mapping.get("updated_at", None)
|
||||
)
|
||||
|
||||
async def get_post_comments(self, post_id: str) -> List[Comment]:
|
||||
query = "SELECT id, post_id, author_id, message, created_at, updated_at FROM comments WHERE post_id = :post_id"
|
||||
rows = await self._db.fetch_all(query=query, values={"post_id": post_id})
|
||||
return [self._result_to_comment(result) for result in rows]
|
||||
|
||||
async def create_comment(self, data: CommentCreate) -> Comment:
|
||||
query = "INSERT INTO comments (post_id, author_id, message) VALUES (:post_id, :author_id, :message) RETURNING id"
|
||||
result = await self._db.execute(query=query, values={"post_id": data.post_id, "author_id": data.author_id, "message": data.message})
|
||||
|
||||
comment = await self.get_comment(result)
|
||||
await self._event_prod.send_created_event(comment)
|
||||
return comment
|
||||
|
||||
async def update_comment(self, comment_id: int, data: CommentUpdate) -> Comment:
|
||||
query = "UPDATE comments SET message = :message, updated_at = now() WHERE id = :comment_id"
|
||||
await self._db.execute(query=query, values={"message": data.message, "comment_id": comment_id})
|
||||
|
||||
comment = await self.get_comment(comment_id)
|
||||
await self._event_prod.send_updated_event(comment)
|
||||
return comment
|
||||
|
||||
async def delete_comment(self, comment_id: int) -> None:
|
||||
comment = await self.get_comment(comment_id)
|
||||
|
||||
query = "DELETE FROM comments WHERE id = :comment_id"
|
||||
await self._db.execute(query=query, values={"comment_id": comment_id})
|
||||
|
||||
await self._event_prod.send_deleted_event(comment)
|
||||
|
||||
async def get_comment(self, comment_id: int) -> Comment:
|
||||
query = "SELECT id, post_id, author_id, message, created_at, updated_at FROM comments WHERE id = :comment_id"
|
||||
result = await self._db.fetch_one(query=query, values={"comment_id": comment_id})
|
||||
if result is None:
|
||||
raise ServiceException(message="no comment found", error_code=ServiceErrorCode.NOT_FOUND)
|
||||
|
||||
return self._result_to_comment(result)
|
||||
|
||||
async def delete_post_comments(self, post_id: str) -> None:
|
||||
comments = await self.get_post_comments(post_id)
|
||||
|
||||
query = "DELETE FROM comments WHERE post_id = :post_id"
|
||||
await self._db.execute(query=query, values={"post_id": post_id})
|
||||
|
||||
for comment in comments:
|
||||
await self._event_prod.send_deleted_event(comment)
|
||||
|
||||
async def delete_user_comments(self, user_id: str) -> None:
|
||||
comments = await self.get_post_comments(user_id)
|
||||
|
||||
query = "DELETE FROM comments WHERE author_id = :author_id"
|
||||
await self._db.execute(query=query, values={"author_id": user_id})
|
||||
|
||||
for comment in comments:
|
||||
await self._event_prod.send_deleted_event(comment)
|
||||
|
||||
async def _get_user_comments(self, user_id: str) -> List[Comment]:
|
||||
query = "SELECT id, post_id, author_id, message, created_at, updated_at FROM comments WHERE author_id = :user_id"
|
||||
rows = await self._db.fetch_all(query=query, values={"user_id": user_id})
|
||||
return [self._result_to_comment(result) for result in rows]
|
||||
41
services/comment-service/comment_service/postgres/service.py
Normal file
41
services/comment-service/comment_service/postgres/service.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import logging
|
||||
|
||||
from databases import Database
|
||||
|
||||
from comment_service.models.config import Config
|
||||
from comment_service.events.producer import CommentEventProducer
|
||||
from comment_service.postgres.repository import ServiceDBRepository
|
||||
|
||||
|
||||
async def connect_database(config: Config) -> Database:
|
||||
"""Opens a connection to the database.
|
||||
|
||||
Args:
|
||||
config (Config): The app configuration.
|
||||
|
||||
Returns:
|
||||
A connected databases.Database instance
|
||||
|
||||
"""
|
||||
db = Database(config.postgres_dsn)
|
||||
try:
|
||||
await db.connect()
|
||||
except Exception:
|
||||
logging.error("failed to connect to postgresql database")
|
||||
raise
|
||||
|
||||
return db
|
||||
|
||||
|
||||
async def create_db_repository(config: Config, event_producer: CommentEventProducer) -> ServiceDBRepository:
|
||||
"""Create the database repository.
|
||||
|
||||
Open a database connection and instantialise the
|
||||
database repository.
|
||||
|
||||
Returns:
|
||||
ServiceDBRepository
|
||||
|
||||
"""
|
||||
db = await connect_database(config)
|
||||
return ServiceDBRepository(db, event_producer)
|
||||
Reference in New Issue
Block a user