-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
1,103 additions
and
966 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import dataclasses | ||
|
||
from app.entities.category.category_codes import CategoryCode | ||
from app.entities.collections.geo_json import GeoJsonPolygon | ||
|
||
|
||
@dataclasses.dataclass | ||
class ShopCreationRequest: | ||
name: str | ||
category_codes: set[CategoryCode] | ||
delivery_areas: list[GeoJsonPolygon] |
50 changes: 50 additions & 0 deletions
50
app/entities/caches/category_point/category_point_cache_invalidator.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import asyncio | ||
from abc import ABC, abstractmethod | ||
|
||
from app.entities.collections.category_point.category_point_collection import ( | ||
CategoryPointCollection, | ||
) | ||
from app.entities.collections.category_point.category_point_document import ( | ||
CategoryPointDocument, | ||
) | ||
from app.entities.collections.shop.shop_document import ShopDocument | ||
from app.entities.redis_repositories.category_point_redis_repository import ( | ||
CategoryPointRedisRepository, | ||
) | ||
|
||
|
||
class CategoryPointCacheInvalidator(ABC): | ||
def __init__(self, shop: ShopDocument): | ||
self._shop = shop | ||
|
||
@abstractmethod | ||
async def invalidate(self) -> None: | ||
pass | ||
|
||
async def _delete_cache(self, point: CategoryPointDocument) -> None: | ||
""" | ||
반드시 redis 에서 삭제가 성공한 후에 mongodb 에서 삭제해야 합니다. | ||
mongodb 에서 삭제된 후에 redis 삭제가 실패할 경우, redis 캐시를 다시 찾아서 삭제할 방법이 없기 때문입니다. | ||
""" | ||
await CategoryPointRedisRepository.delete(point.cache_key) | ||
await CategoryPointCollection.delete_by_id(point.id) | ||
|
||
|
||
class ShopCreationCategoryPointCacheInvalidator(CategoryPointCacheInvalidator): | ||
async def invalidate(self) -> None: | ||
list_of_point_tuple = await self._get_list_of_point_tuple() | ||
deleted = set() | ||
for tp in list_of_point_tuple: | ||
for point in tp: | ||
if point.id not in deleted: | ||
await self._delete_cache(point) | ||
deleted.add(point.id) | ||
|
||
async def _get_list_of_point_tuple(self) -> list[tuple[CategoryPointDocument, ...]]: | ||
return await asyncio.gather( | ||
*( | ||
CategoryPointCollection.get_all_within_polygon_and_code_ne(area.poly, code) | ||
for area in self._shop.delivery_areas | ||
for code in self._shop.category_codes | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from app.dtos.shop.shop_creation_request import ShopCreationRequest | ||
from app.entities.caches.category_point.category_point_cache_invalidator import ( | ||
ShopCreationCategoryPointCacheInvalidator, | ||
) | ||
from app.entities.collections import ShopCollection | ||
from app.entities.collections.shop.shop_document import ( | ||
ShopDeliveryAreaSubDocument, | ||
ShopDocument, | ||
) | ||
|
||
|
||
async def create_shop(shop_creation_request: ShopCreationRequest) -> ShopDocument: | ||
shop = await ShopCollection.insert_one( | ||
shop_creation_request.name, | ||
list(shop_creation_request.category_codes), | ||
[ShopDeliveryAreaSubDocument(poly=area) for area in shop_creation_request.delivery_areas], | ||
) | ||
|
||
await ShopCreationCategoryPointCacheInvalidator(shop).invalidate() | ||
|
||
return shop |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
from app.dtos.shop.shop_creation_request import ShopCreationRequest | ||
from app.entities.category.category_codes import CategoryCode | ||
from app.entities.collections import ShopCollection | ||
from app.entities.collections.category_point.category_point_collection import ( | ||
CategoryPointCollection, | ||
) | ||
from app.entities.collections.geo_json import GeoJsonPoint, GeoJsonPolygon | ||
from app.entities.collections.shop.shop_document import ShopDeliveryAreaSubDocument | ||
from app.services.shop_service import create_shop | ||
|
||
|
||
async def test_create_shop_invalidates_point() -> None: | ||
# Given | ||
await ShopCollection.insert_one( | ||
name="sandwich_pizza_shop", | ||
category_codes=[CategoryCode.SANDWICH, CategoryCode.PIZZA], | ||
delivery_areas=[ | ||
ShopDeliveryAreaSubDocument(poly=GeoJsonPolygon(coordinates=[[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]]])) | ||
], | ||
) | ||
shop_creation_request = ShopCreationRequest( | ||
name="chicken_sandwich_shop", | ||
category_codes={CategoryCode.CHICKEN, CategoryCode.SANDWICH}, | ||
delivery_areas=[GeoJsonPolygon(coordinates=[[[8, 0], [8, 14], [14, 14], [14, 0], [8, 0]]])], | ||
) | ||
not_be_removed1 = await CategoryPointCollection.insert_or_replace( | ||
"3_3", | ||
GeoJsonPoint(coordinates=[3, 3]), | ||
( | ||
CategoryCode.SANDWICH, | ||
CategoryCode.PIZZA, | ||
), | ||
) | ||
to_be_removed = await CategoryPointCollection.insert_or_replace( | ||
"9_9", | ||
GeoJsonPoint(coordinates=[9, 9]), | ||
( | ||
CategoryCode.SANDWICH, | ||
CategoryCode.PIZZA, | ||
), | ||
) | ||
not_be_removed2 = await CategoryPointCollection.insert_or_replace( | ||
"9.2_9.2", | ||
GeoJsonPoint(coordinates=[9.2, 9.2]), | ||
( | ||
CategoryCode.SANDWICH, | ||
CategoryCode.PIZZA, | ||
CategoryCode.CHICKEN, | ||
), | ||
) | ||
|
||
# When | ||
shop = await create_shop(shop_creation_request) | ||
|
||
# Then | ||
result = await CategoryPointCollection._collection.find({}, {"_id": True}).to_list(None) | ||
|
||
assert len(result) == 2 | ||
ids = [item["_id"] for item in result] | ||
assert not_be_removed1.id in ids | ||
assert not_be_removed2.id in ids | ||
|
||
result_shop = await ShopCollection._collection.find_one({"_id": shop.id}) | ||
assert shop.name == result_shop["name"] |
Oops, something went wrong.