Skip to content

Commit

Permalink
#22: feat: add methods to repository and service to get paginated rev…
Browse files Browse the repository at this point in the history
…iews
  • Loading branch information
ReznikovRoman committed Jul 10, 2022
1 parent 28df02b commit 0936374
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/ugc/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from ugc.domain import bookmarks, processors, progress, reviews
from ugc.domain.bookmarks.models import FilmBookmark
from ugc.domain.progress.models import UserFilmProgress
from ugc.domain.reviews.constants import REVIEWS_COLLECTION_NAME
from ugc.helpers import sentinel
from ugc.infrastructure.db import mongo, redis, repositories
from ugc.infrastructure.queue import consumers, producers
Expand Down Expand Up @@ -172,7 +173,9 @@ class Container(containers.DeclarativeContainer):

review_repository = providers.Singleton(
reviews.ReviewRepository,
mongo_repository=mongo_repository_factory(factory=review_factory, collection_name=REVIEWS_COLLECTION_NAME),
db=mongo_client,
review_factory=review_factory,
)

review_service = providers.Factory(
Expand Down
3 changes: 3 additions & 0 deletions src/ugc/domain/reviews/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from typing import Final

REVIEWS_COLLECTION_NAME: Final[str] = "reviews"
33 changes: 32 additions & 1 deletion src/ugc/domain/reviews/repositories.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,36 @@
from typing import ClassVar

from bson import ObjectId
from pymongo import DESCENDING
from pymongo.errors import DuplicateKeyError

from ugc.common.exceptions import ConflictError
from ugc.infrastructure.db.clients import MongoDatabaseClient
from ugc.infrastructure.db.repositories import MongoRepository
from ugc.infrastructure.db.types import PaginationCursor

from .constants import REVIEWS_COLLECTION_NAME
from .factories import FilmReviewFactory
from .types import FilmReview


class ReviewRepository:
"""Репозиторий для работы с данными рецензий."""

def __init__(self, db: MongoDatabaseClient) -> None:
collection: ClassVar[str] = REVIEWS_COLLECTION_NAME

def __init__(
self, mongo_repository: MongoRepository[FilmReview], db: MongoDatabaseClient, review_factory: FilmReviewFactory,
) -> None:
assert isinstance(mongo_repository, MongoRepository)
self._mongo_repository = mongo_repository

assert isinstance(db, MongoDatabaseClient)
self._db = db

assert isinstance(review_factory, FilmReviewFactory)
self._factory = review_factory

async def create(self, /, review: FilmReview) -> FilmReview:
"""Создание рецензии."""
try:
Expand All @@ -21,3 +39,16 @@ async def create(self, /, review: FilmReview) -> FilmReview:
raise ConflictError(message=f"User has already written a review for film {review.film_id}.")
review.id = str(review_db.inserted_id)
return review

async def get_paginated(
self, film_id: str, *, limit: int, cursor: PaginationCursor = None,
) -> tuple[list[FilmReview], PaginationCursor]:
"""Получение пагинированного списка рецензий на фильм."""
ordering = ("_id", DESCENDING)
filter_query = {"film_id": film_id}
pagination_query = {"_id": {"$lt": ObjectId(cursor)}}
results, new_cursor = await self._mongo_repository.get_paginated_results(
limit=limit, cursor=cursor, cursor_field="id",
ordering=ordering, filter_query=filter_query, pagination_query=pagination_query,
)
return results, new_cursor
14 changes: 14 additions & 0 deletions src/ugc/domain/reviews/services.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from typing import ClassVar
from uuid import UUID

from ugc.infrastructure.db.types import PaginationCursor

from .factories import FilmReviewFactory
from .repositories import ReviewRepository
from .types import FilmReview
Expand All @@ -8,6 +11,8 @@
class ReviewService:
"""Сервис для работы с рецензиями."""

DEFAULT_REVIEWS_PAGE_SIZE: ClassVar[int] = 3

def __init__(self, review_factory: FilmReviewFactory, review_repository: ReviewRepository) -> None:
assert isinstance(review_factory, FilmReviewFactory)
self._factory = review_factory
Expand All @@ -20,3 +25,12 @@ async def create_review(self, *, user_id: UUID, film_id: UUID, title: str, revie
review_dto = self._factory.create_new(user_id=user_id, film_id=film_id, title=title, review=review_text)
review = await self._repository.create(review_dto)
return review

async def get_film_reviews(
self, film_id: UUID, *, limit: int | None = None, cursor: PaginationCursor = None,
) -> tuple[list[FilmReview], PaginationCursor]:
"""Получение списка рецензий на фильм."""
if limit is None:
limit = self.DEFAULT_REVIEWS_PAGE_SIZE
reviews = await self._repository.get_paginated(str(film_id), limit=limit, cursor=cursor)
return reviews

0 comments on commit 0936374

Please sign in to comment.