A journey to fix `ValidationError` in Pocket imports turned service layer refactoring :D
116 lines
3.5 KiB
Python
116 lines
3.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import typing
|
|
import uuid
|
|
|
|
from django.core.exceptions import ValidationError
|
|
from django.db import models
|
|
|
|
from hotpocket_backend.apps.core.services import get_adapter
|
|
from hotpocket_backend.apps.saves.models import Save
|
|
from hotpocket_backend.apps.saves.types import PSaveAdapter
|
|
from hotpocket_soa.dto.saves import ImportedSaveIn, SaveIn, SavesQuery
|
|
from hotpocket_soa.exceptions.backend import (
|
|
Invalid as InvalidError,
|
|
NotFound as NotFoundError,
|
|
)
|
|
|
|
|
|
class SavesService:
|
|
class SavesServiceError(Exception):
|
|
pass
|
|
|
|
class Invalid(InvalidError, SavesServiceError):
|
|
pass
|
|
|
|
class NotFound(NotFoundError, SavesServiceError):
|
|
pass
|
|
|
|
@property
|
|
def adapter(self) -> PSaveAdapter:
|
|
if hasattr(self, '_adapter') is False:
|
|
adapter_klass = get_adapter(
|
|
'SAVES_SAVE_ADAPTER',
|
|
'hotpocket_backend.apps.saves.adapters.basic:BasicSaveAdapter',
|
|
)
|
|
self._adapter = adapter_klass()
|
|
|
|
return self._adapter
|
|
|
|
def create(self,
|
|
*,
|
|
account_uuid: uuid.UUID,
|
|
save: SaveIn | ImportedSaveIn,
|
|
) -> Save:
|
|
try:
|
|
key = hashlib.sha256(save.url.encode('utf-8')).hexdigest()
|
|
|
|
defaults = dict(
|
|
account_uuid=account_uuid,
|
|
key=key,
|
|
url=save.url,
|
|
)
|
|
|
|
save_object, created = Save.objects.get_or_create(
|
|
key=key,
|
|
deleted_at__isnull=True,
|
|
defaults=defaults,
|
|
)
|
|
|
|
if created is True:
|
|
save_object.is_netloc_banned = save.is_netloc_banned
|
|
|
|
if isinstance(save, ImportedSaveIn) is True:
|
|
save_object.title = save.title # type: ignore[union-attr]
|
|
|
|
save_object.save()
|
|
|
|
return save_object
|
|
except ValidationError as exception:
|
|
raise self.Invalid.from_django_validation_error(exception)
|
|
|
|
def get(self, *, pk: uuid.UUID) -> Save:
|
|
try:
|
|
return Save.active_objects.get(pk=pk)
|
|
except Save.DoesNotExist as exception:
|
|
raise self.NotFound(
|
|
f'Save not found: pk=`{pk}`',
|
|
) from exception
|
|
|
|
def search(self,
|
|
*,
|
|
filters: typing.Any,
|
|
offset: int = 0,
|
|
limit: int = 10,
|
|
order: str = '-created_at',
|
|
) -> models.QuerySet[Save]:
|
|
raise NotImplementedError('TODO')
|
|
|
|
def update(self, *, pk: uuid.UUID, save: SaveIn) -> Save:
|
|
raise NotImplementedError('TODO')
|
|
|
|
def delete(self, *, pk: uuid.UUID) -> bool:
|
|
raise NotImplementedError('TODO')
|
|
|
|
def search_associated_to_account(self,
|
|
*,
|
|
account_uuid: uuid.UUID,
|
|
query: SavesQuery,
|
|
offset: int = 0,
|
|
limit: int = 10,
|
|
order_by: str = '-associations__created_at',
|
|
) -> models.QuerySet[Save]:
|
|
result = Save.active_objects.\
|
|
filter(
|
|
associations__account_uuid=account_uuid,
|
|
associations__archived_at__isnull=True,
|
|
).\
|
|
order_by(order_by)
|
|
|
|
return result
|
|
|
|
def get_for_processing(self, *, pk: uuid.UUID) -> Save:
|
|
return self.adapter.get_for_processing(pk=pk)
|