Skip to content

Commit efda983

Browse files
authored
Merge pull request #1 from ozgurkara/refactoring-data-layer
Refactoring data layer
2 parents 78b6513 + 227e0f8 commit efda983

37 files changed

+605
-100
lines changed

app/data/__init__.py

Whitespace-only changes.

app/data/todo/__init__.py

Whitespace-only changes.

app/data/todo/handlers/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from pydantic import BaseModel, Field
2+
from app.pydiator.interfaces import BaseRequest, BaseResponse, BaseHandler
3+
from app.db.fake_db import fake_todo_db
4+
5+
6+
class AddTodoDataRequest(BaseModel, BaseRequest):
7+
title: str = Field("", title="The title of the item", max_length=300, min_length=1)
8+
9+
10+
class AddTodoDataResponse(BaseModel, BaseResponse):
11+
success: bool = Field(...)
12+
13+
14+
class AddTodoDataHandler(BaseHandler):
15+
16+
async def handle(self, req: AddTodoDataRequest) -> AddTodoDataResponse:
17+
fake_todo_db.append({
18+
"id": len(fake_todo_db) + 1,
19+
"title": req.title
20+
})
21+
22+
return AddTodoDataResponse(success=True)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from pydantic import BaseModel, Field
2+
from app.pydiator.interfaces import BaseRequest, BaseResponse, BaseHandler
3+
from app.db.fake_db import fake_todo_db
4+
5+
6+
class DeleteTodoByIdDataRequest(BaseModel, BaseRequest):
7+
id: int = Field(0, gt=0, title="item id")
8+
9+
10+
class DeleteTodoByIdDataResponse(BaseModel, BaseResponse):
11+
success: bool = Field(...)
12+
13+
14+
class DeleteTodoByIdDataHandler(BaseHandler):
15+
16+
async def handle(self, req: DeleteTodoByIdDataRequest) -> DeleteTodoByIdDataResponse:
17+
for it in fake_todo_db:
18+
if it["id"] == req.id:
19+
fake_todo_db.remove(it)
20+
return DeleteTodoByIdDataResponse(success=True)
21+
22+
return DeleteTodoByIdDataResponse(success=False)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from pydantic import BaseModel, Field
2+
from app.pydiator.interfaces import BaseRequest, BaseResponse, BaseHandler
3+
from app.db.fake_db import fake_todo_db
4+
from typing import List
5+
6+
7+
class GetTodoAllDataRequest(BaseModel, BaseRequest):
8+
def __init__(self):
9+
pass
10+
11+
12+
class GetTodoAllDataResponse(BaseModel, BaseResponse):
13+
id: int = Field(...)
14+
title: str = Field(...)
15+
16+
17+
class GetTodoAllDataHandler(BaseHandler):
18+
19+
async def handle(self, req: GetTodoAllDataRequest) -> List[GetTodoAllDataResponse]:
20+
response = []
21+
for it in fake_todo_db:
22+
response.append(GetTodoAllDataResponse(id=it["id"], title=it["title"]))
23+
24+
return response
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from pydantic import BaseModel, Field
2+
from app.pydiator.interfaces import BaseRequest, BaseResponse, BaseHandler, BaseCacheable, CacheType
3+
from app.db.fake_db import fake_todo_db
4+
5+
6+
class GetTodoByIdDataRequest(BaseModel, BaseRequest):
7+
id: int = Field(0, gt=0, description="The item id be greater than zero")
8+
9+
10+
class GetTodoByIdDataResponse(BaseModel, BaseResponse):
11+
id: int = Field(...)
12+
title: str = Field(...)
13+
14+
15+
class GetTodoByIdDataHandler(BaseHandler):
16+
17+
async def handle(self, req: GetTodoByIdDataRequest) -> GetTodoByIdDataResponse:
18+
for it in fake_todo_db:
19+
if it["id"] == req.id:
20+
return GetTodoByIdDataResponse(id=it["id"], title=it["title"])
21+
22+
return None
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from pydantic import BaseModel, Field, Extra
2+
from app.pydiator.interfaces import BaseRequest, BaseResponse, BaseHandler
3+
from app.db.fake_db import fake_todo_db
4+
5+
6+
class UpdateTodoDataRequest(BaseModel, BaseRequest):
7+
title: str = Field("", title="The title of the item", max_length=300, min_length=1)
8+
id: int = Field(0, title="", gt=0)
9+
10+
11+
class UpdateTodoDataResponse(BaseModel, BaseResponse):
12+
success: bool = Field(...)
13+
14+
15+
class UpdateTodoDataHandler(BaseHandler):
16+
17+
async def handle(self, req: UpdateTodoDataRequest) -> UpdateTodoDataResponse:
18+
for it in fake_todo_db:
19+
if it["id"] == req.id:
20+
it["title"] = req.title
21+
return UpdateTodoDataResponse(success=True)
22+
23+
return UpdateTodoDataResponse(success=False)

app/main.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
request_validation_exception_handler
88
)
99

10-
from app.resources.pydiator_config import set_up_pydiator
10+
from app.pydiator_config import set_up_pydiator
1111
from starlette.exceptions import HTTPException as StarletteHTTPException
1212

1313
app = FastAPI()
@@ -32,8 +32,8 @@ async def validation_exception_handler(request, exc):
3232

3333
app.include_router(
3434
todo_resource.router,
35-
prefix="/v1/todo",
36-
tags=["todo"]
35+
prefix="/v1/handlers",
36+
tags=["handlers"]
3737
)
3838

3939
set_up_pydiator()

app/pydiator/pipelines/cache_pipeline.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ async def handle(self, req: BaseRequest) -> object:
2727
return cached_obj
2828

2929
response = await self.next().handle(req)
30-
if response is not None or response is not "":
30+
if response is not None or response != "":
3131
self.add_to_cache(response, cache_key, cache_duration, no_cache)
3232

3333
if response is None:

app/resources/pydiator_config.py renamed to app/pydiator_config.py

+19-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
from app.data.todo.handlers.delete_todo_by_id_data_handler import DeleteTodoByIdDataHandler, DeleteTodoByIdDataRequest
12
from app.utils.environment import redis_key_prefix, cache_pipeline_is_active, distributed_cache_is_active
2-
from app.utils.client_factory import get_redis_client
3+
from app.utils.client_factory import get_distributed_cache_provider
34
from app.utils.distributed_cache_provider import DistributedCacheProvider
45

56
from app.pydiator.mediatr import pydiator
@@ -12,7 +13,13 @@
1213
from app.resources.todo.handlers.add_todo_handler import AddTodoRequest, AddTodoHandler
1314
from app.resources.todo.handlers.update_todo_handler import UpdateTodoRequest, UpdateTodoHandler
1415
from app.resources.todo.handlers.delete_todo_by_id_handler import DeleteTodoByIdRequest, DeleteTodoByIdHandler
15-
from app.resources.todo.handlers.notifications.todo_cache_remove_handler import TodoChangeNotification, TodoCacheRemoveNotificationHandler
16+
from app.resources.todo.handlers.notifications.todo_cache_remove_handler import TodoChangeNotification, \
17+
TodoCacheRemoveNotificationHandler
18+
19+
from app.data.todo.handlers.get_todo_all_data_handler import GetTodoAllDataRequest, GetTodoAllDataHandler
20+
from app.data.todo.handlers.get_todo_by_id_data_handler import GetTodoByIdDataRequest, GetTodoByIdDataHandler
21+
from app.data.todo.handlers.add_todo_data_handler import AddTodoDataHandler, AddTodoDataRequest
22+
from app.data.todo.handlers.update_todo_data_handler import UpdateTodoDataRequest, UpdateTodoDataHandler
1623

1724
DistributedCacheProvider.redis_key_prefix = redis_key_prefix
1825

@@ -21,15 +28,24 @@ def set_up_pydiator():
2128
container = MediatrContainer()
2229
container.register_pipeline(LogPipeline())
2330
if cache_pipeline_is_active is True and distributed_cache_is_active is True:
24-
cache_pipeline = CachePipeline(DistributedCacheProvider(get_redis_client()))
31+
cache_pipeline = CachePipeline(get_distributed_cache_provider())
2532
container.register_pipeline(cache_pipeline)
2633

34+
# Service handlers mapping
2735
container.register_request(GetTodoAllRequest(), GetTodoAllHandler())
2836
container.register_request(GetTodoByIdRequest(), GetTodoByIdHandler())
2937
container.register_request(AddTodoRequest(), AddTodoHandler())
3038
container.register_request(UpdateTodoRequest(), UpdateTodoHandler())
3139
container.register_request(DeleteTodoByIdRequest(), DeleteTodoByIdHandler())
3240

41+
# Data handlers mapping
42+
container.register_request(GetTodoAllDataRequest(), GetTodoAllDataHandler())
43+
container.register_request(GetTodoByIdDataRequest(), GetTodoByIdDataHandler())
44+
container.register_request(AddTodoDataRequest(), AddTodoDataHandler())
45+
container.register_request(DeleteTodoByIdDataRequest(), DeleteTodoByIdDataHandler())
46+
container.register_request(UpdateTodoDataRequest(), UpdateTodoDataHandler())
47+
48+
# Notification mapping
3349
container.register_notification(TodoChangeNotification(), [TodoCacheRemoveNotificationHandler()])
3450

3551
pydiator.set_container(container)
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from pydantic import BaseModel, Field
2+
3+
from app.data.todo.handlers.add_todo_data_handler import AddTodoDataRequest
24
from app.pydiator.interfaces import BaseRequest, BaseResponse, BaseHandler
35
from app.pydiator.mediatr import pydiator
4-
from app.db.fake_db import fake_todo_db
56
from app.resources.todo.handlers.notifications.todo_cache_remove_handler import TodoChangeNotification
67

78

@@ -16,11 +17,9 @@ class AddTodoResponse(BaseModel, BaseResponse):
1617
class AddTodoHandler(BaseHandler):
1718

1819
async def handle(self, req: AddTodoRequest) -> AddTodoResponse:
19-
fake_todo_db.append({
20-
"id": len(fake_todo_db) + 1,
21-
"title": req.title
22-
})
23-
24-
await pydiator.publish(TodoChangeNotification())
20+
data_response = await pydiator.send(AddTodoDataRequest(title=req.title))
21+
if data_response.success:
22+
await pydiator.publish(TodoChangeNotification())
23+
return AddTodoResponse(success=True)
2524

26-
return AddTodoResponse(success=True)
25+
return AddTodoResponse(success=False)
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from pydantic import BaseModel, Field
2+
3+
from app.data.todo.handlers.delete_todo_by_id_data_handler import DeleteTodoByIdDataRequest
24
from app.pydiator.mediatr import pydiator
35
from app.pydiator.interfaces import BaseRequest, BaseResponse, BaseHandler
4-
from app.db.fake_db import fake_todo_db
56
from app.resources.todo.handlers.notifications.todo_cache_remove_handler import TodoChangeNotification
67

78

@@ -16,11 +17,9 @@ class DeleteTodoByIdResponse(BaseModel, BaseResponse):
1617
class DeleteTodoByIdHandler(BaseHandler):
1718

1819
async def handle(self, req: DeleteTodoByIdRequest) -> DeleteTodoByIdResponse:
19-
for it in fake_todo_db:
20-
if it["id"] == req.id:
21-
fake_todo_db.remove(it)
22-
await pydiator.publish(TodoChangeNotification())
23-
24-
return DeleteTodoByIdResponse(success=True)
20+
data_response = await pydiator.send(DeleteTodoByIdDataRequest(id=req.id))
21+
if data_response.success:
22+
await pydiator.publish(TodoChangeNotification())
23+
return DeleteTodoByIdResponse(success=True)
2524

2625
return DeleteTodoByIdResponse(success=False)

app/resources/todo/handlers/get_todo_all_handler.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from pydantic import BaseModel, Field
22
from app.pydiator.interfaces import BaseRequest, BaseResponse, BaseHandler, BaseCacheable, CacheType
3-
from app.db.fake_db import fake_todo_db
43
from typing import List
4+
from app.pydiator.mediatr import pydiator
5+
from app.data.todo.handlers.get_todo_all_data_handler import GetTodoAllDataRequest
56

67

78
class GetTodoAllRequest(BaseModel, BaseRequest, BaseCacheable):
@@ -24,7 +25,8 @@ class GetTodoAllHandler(BaseHandler):
2425

2526
async def handle(self, req: GetTodoAllRequest) -> List[GetTodoAllResponse]:
2627
response = []
27-
for it in fake_todo_db:
28-
response.append(GetTodoAllResponse(id=it["id"], title=it["title"]))
28+
data_response = await pydiator.send(GetTodoAllDataRequest())
29+
for d in data_response:
30+
response.append(GetTodoAllResponse(id=d.id, title=d.title))
2931

3032
return response

app/resources/todo/handlers/get_todo_by_id_handler.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from pydantic import BaseModel, Field
2-
from app.pydiator.interfaces import BaseRequest, BaseResponse, BaseHandler, BaseCacheable, CacheType
3-
from app.db.fake_db import fake_todo_db
2+
from app.pydiator.interfaces import BaseRequest, BaseResponse, BaseHandler
3+
from app.pydiator.mediatr import pydiator
4+
from app.data.todo.handlers.get_todo_by_id_data_handler import GetTodoByIdDataRequest
45

56

67
class GetTodoByIdRequest(BaseModel, BaseRequest):
@@ -15,8 +16,8 @@ class GetTodoByIdResponse(BaseModel, BaseResponse):
1516
class GetTodoByIdHandler(BaseHandler):
1617

1718
async def handle(self, req: GetTodoByIdRequest) -> GetTodoByIdResponse:
18-
for it in fake_todo_db:
19-
if it["id"] == req.id:
20-
return GetTodoByIdResponse(id=it["id"], title=it["title"])
19+
todo_data = await pydiator.send(GetTodoByIdDataRequest(id=req.id))
20+
if todo_data is not None:
21+
return GetTodoByIdResponse(id=todo_data.id, title=todo_data.title)
2122

2223
return None
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from pydantic import BaseModel
2-
from app.utils.client_factory import get_redis_client
2+
from app.utils.client_factory import get_distributed_cache_provider
33
from app.pydiator.interfaces import BaseNotification, BaseNotificationHandler
4-
from app.utils.distributed_cache_provider import DistributedCacheProvider
54
from app.resources.todo.handlers.get_todo_all_handler import GetTodoAllRequest
65

76

@@ -11,7 +10,7 @@ class TodoChangeNotification(BaseModel, BaseNotification):
1110

1211
class TodoCacheRemoveNotificationHandler(BaseNotificationHandler):
1312
def __init__(self):
14-
self.cache_provider = DistributedCacheProvider(get_redis_client())
13+
self.cache_provider = get_distributed_cache_provider()
1514

1615
async def handle(self, notification: BaseNotification):
1716
self.cache_provider.delete(GetTodoAllRequest().get_cache_key())

app/resources/todo/handlers/update_todo_handler.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from pydantic import BaseModel, Field, Extra
2+
3+
from app.data.todo.handlers.update_todo_data_handler import UpdateTodoDataRequest
24
from app.pydiator.interfaces import BaseRequest, BaseResponse, BaseHandler
35
from app.pydiator.mediatr import pydiator
4-
from app.db.fake_db import fake_todo_db
56
from app.resources.todo.handlers.notifications.todo_cache_remove_handler import TodoChangeNotification
67

78

@@ -19,10 +20,9 @@ class UpdateTodoResponse(BaseModel, BaseResponse):
1920
class UpdateTodoHandler(BaseHandler):
2021

2122
async def handle(self, req: UpdateTodoRequest) -> UpdateTodoResponse:
22-
for it in fake_todo_db:
23-
if it["id"] == req.CustomFields.id:
24-
it["title"] = req.title
25-
await pydiator.publish(TodoChangeNotification())
26-
return UpdateTodoResponse(success=True)
23+
data_response = await pydiator.send(UpdateTodoDataRequest(id=req.CustomFields.id, title=req.title))
24+
if data_response.success:
25+
await pydiator.publish(TodoChangeNotification())
26+
return UpdateTodoResponse(success=True)
2727

2828
return UpdateTodoResponse(success=False)

app/resources/todo/todo_resource.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from fastapi import APIRouter
22
from typing import List
3-
from app.resources.pydiator_config import pydiator
3+
from app.pydiator.mediatr import pydiator
44
from app.resources.todo.handlers.get_todo_all_handler import GetTodoAllRequest, GetTodoAllResponse
55
from app.resources.todo.handlers.get_todo_by_id_handler import GetTodoByIdRequest, GetTodoByIdResponse
66
from app.resources.todo.handlers.add_todo_handler import AddTodoRequest, AddTodoResponse

app/utils/client_factory.py

+9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import redis
2+
3+
from app.utils import environment
4+
from app.utils.distributed_cache_provider import DistributedCacheProvider, FakeDistributedCacheProvider
25
from app.utils.environment import redis_host, redis_port, redis_db
36

47

58
def get_redis_client():
69
return redis.Redis(host=redis_host, port=redis_port, db=redis_db)
10+
11+
12+
def get_distributed_cache_provider():
13+
if environment.distributed_cache_is_active:
14+
return DistributedCacheProvider(get_redis_client())
15+
return FakeDistributedCacheProvider()

app/utils/distributed_cache_provider.py

+19-1
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,22 @@ def __get_client(self):
6161

6262
return self.client
6363

64-
# distributed_cache_provider = RedisCacheProvider()
64+
65+
class FakeDistributedCacheProvider(BaseCacheProvider):
66+
def __init__(self):
67+
pass
68+
69+
def add(self, key: str, value, expires):
70+
pass
71+
72+
def get(self, key: str):
73+
pass
74+
75+
def exist(self, key: str):
76+
pass
77+
78+
def delete(self, key: str):
79+
pass
80+
81+
def check_connection(self):
82+
pass

app/utils/environment.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
redis_db = int(os.getenv('RedisDb', 0))
66
redis_key_prefix = os.getenv('RedisKeyPrefix', 'pydiator_api:')
77

8-
distributed_cache_is_active = bool(os.environ.get("DistributedCacheIsActive", True))
8+
distributed_cache_is_active = bool(os.environ.get("DistributedCacheIsActive", False))
99
cache_pipeline_is_active = bool(os.environ.get("CachePipelineIsActive", True))

0 commit comments

Comments
 (0)