Repository: Saurabh254/PinSphere
Pull request #45: feat: Added cache manager boilerplace code
Author: login: Saurabh254
Created: 2025-04-28T09:18:21Z | Merged: 2025-04-28T09:24:37Z

summary: 


Added boilerplate code for cache manager



Diff:
diff --git a/server/core/baseErrors.py b/server/core/baseErrors.py
new file mode 100644
index 0000000..f84993f
--- /dev/null
+++ b/server/core/baseErrors.py
@@ -0,0 +1,23 @@
+import logging
+from typing import Optional
+
+from pydantic import BaseModel
+
+from pin_sphere.base_exception import ServerError
+
+
+class CacheInitilizationError(ServerError):
+    def __init__(
+        self, namespace: Optional[str] = None, entity: Optional[BaseModel] = None
+    ) -> None:
+        logging.critical(
+            f"Failed to initilize the CacheManager class with the namespace [{namespace}] and entity [{entity}]"
+        )
+        super().__init__()
+
+
+class InvalidEntity(CacheInitilizationError):
+    def __init__(
+        self, namespace: str | None = None, entity: BaseModel | None = None
+    ) -> None:
+        super().__init__(namespace, entity)
diff --git a/server/core/caching.py b/server/core/caching.py
new file mode 100644
index 0000000..3c0143b
--- /dev/null
+++ b/server/core/caching.py
@@ -0,0 +1,62 @@
+import json
+from typing import List, Literal, Self, Union
+
+from core.baseErrors import CacheInitilizationError, InvalidEntity
+from core.models.content import Content
+from core.models.user import User
+from core.redis_utils import get_redis_client
+
+ENTITY_TYPE = User | Content | List[User | Content]
+
+
+def retrieve_namespace(namespace: str, entity_id: str) -> str:
+    return f"{namespace}_{entity_id}"
+
+
+class CachingManager:
+    _namespace: str | None = None
+
+    def namespace(self, namespace: Literal["User", "Content"]) -> Self:
+        self._namespace = namespace
+        return self
+
+    async def save(self, entity: ENTITY_TYPE) -> None:
+        if self._namespace is None:
+            raise CacheInitilizationError(self._namespace, entity)
+
+        if not isinstance(entity, (User, Content, list)):
+            raise InvalidEntity(self._namespace, entity)
+
+        redis_conn = await anext(get_redis_client())
+
+        if isinstance(entity, list):
+            for item in entity:  # type: ignore
+                if not isinstance(item, (User, Content)):
+                    raise InvalidEntity(self._namespace, item)  # type: ignore
+                if not isinstance(item, (User, Content)):
+                    raise InvalidEntity(self._namespace, item)
+                key = retrieve_namespace(self._namespace, str(item.id))
+                await redis_conn.set(key, json.dumps(item.as_dict()))
+        else:
+            key = retrieve_namespace(self._namespace, str(entity.id))
+            await redis_conn.set(key, json.dumps(entity.as_dict()))
+
+    async def retrieve(
+        self, namespace: Literal["User", "Content"], entity_id: str
+    ) -> Union[User, Content, None]:
+        key = retrieve_namespace(namespace, entity_id)
+        redis_conn = await anext(get_redis_client())
+
+        data = await redis_conn.get(key)
+        if data is None:
+            return None
+
+        obj_data = json.loads(data)
+
+        if namespace == "User":
+            return User(**obj_data)
+        elif namespace == "Content":
+            return Content(**obj_data)
+
+        # This should not happen if Literal["User", "Content"] is correct
+        raise InvalidEntity(namespace, obj_data)


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR adds boilerplate code for a cache manager to handle caching operations for User and Content entities.  
- Introduced a new CachingManager class with asynchronous save and retrieve methods in server/core/caching.py.  
- Added custom error classes (CacheInitilizationError and InvalidEntity) in server/core/baseErrors.py.

### Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

| File                          | Description                                                          |
| ----------------------------- | -------------------------------------------------------------------- |
| server/core/caching.py        | New cache manager implementation and namespace-based key retrieval.  |
| server/core/baseErrors.py     | Custom error classes for caching errors with logging integration.    |




state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T09:23:27Z

Review comments:
diff_hunk: @@ -0,0 +1,23 @@
+import logging
+from typing import Optional
+
+from pydantic import BaseModel
+
+from pin_sphere.base_exception import ServerError
+
+
+class CacheInitilizationError(ServerError):
+    def __init__(
+        self, namespace: Optional[str] = None, entity: Optional[BaseModel] = None
+    ) -> None:
+        logging.critical(
+            f"Failed to initilize the CacheManager class with the namespace [{namespace}] and entity [{entity}]"
+        )
+        super().__init__()
+
+
+class InvalidEntity(CacheInitilizationError):
path: server/core/baseErrors.py
user: login: Copilot
body: The term 'CacheInitilizationError' appears to be a misspelling. Consider renaming it to 'CacheInitializationError' for clarity and consistency.
```suggestion
class CacheInitializationError(ServerError):
    def __init__(
        self, namespace: Optional[str] = None, entity: Optional[BaseModel] = None
    ) -> None:
        logging.critical(
            f"Failed to initialize the CacheManager class with the namespace [{namespace}] and entity [{entity}]"
        )
        super().__init__()


class InvalidEntity(CacheInitializationError):
```
created_at: 2025-04-28T09:23:27Z
author_association: CONTRIBUTOR

PR comments:
user: login: vercel[bot]
created_at: 2025-04-28T09:18:25Z
body: [vc]: #+OZhL0K54ygB8vR/MmP1IfVdX1ohVQNl4s8c39mT5OI=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJwaW4tc3BoZXJlIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6IiJ9LCJpbnNwZWN0b3JVcmwiOiJodHRwczovL3ZlcmNlbC5jb20vc2F1cmFiaDI1NHMtcHJvamVjdHMvcGluLXNwaGVyZS9KOHA1aXQzclNjTGlGR0I5MzhzQUtuc1A1RExWIiwicHJldmlld1VybCI6IiIsIm5leHRDb21taXRTdGF0dXMiOiJGQUlMRUQiLCJyb290RGlyZWN0b3J5Ijoic2VydmVyIn1dfQ==
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **pin-sphere** | ❌ Failed ([Inspect](https://vercel.com/saurabh254s-projects/pin-sphere/J8p5it3rScLiFGB938sAKnsP5DLV)) |  |  | Apr 28, 2025 9:19am |


author_association: NONE
user: login: cloudflare-workers-and-pages[bot]
created_at: 2025-04-28T09:18:34Z
body: ## Deploying pinsphere with &nbsp;<a href="https://pages.dev"><img alt="Cloudflare Pages" src="https://user-images.githubusercontent.com/23264/106598434-9e719e00-654f-11eb-9e59-6167043cfa01.png" width="16"></a> &nbsp;Cloudflare Pages

<table><tr><td><strong>Latest commit:</strong> </td><td>
<code>e036d18</code>
</td></tr>
<tr><td><strong>Status:</strong></td><td>&nbsp;✅&nbsp; Deploy successful!</td></tr>
<tr><td><strong>Preview URL:</strong></td><td>
<a href='https://bf853c54.pinsphere.pages.dev'>https://bf853c54.pinsphere.pages.dev</a>
</td></tr>
<tr><td><strong>Branch Preview URL:</strong></td><td>
<a href='https://feat-added-cache-manager.pinsphere.pages.dev'>https://feat-added-cache-manager.pinsphere.pages.dev</a>
</td></tr>
</table>

[View logs](https://dash.cloudflare.com/da1c65fd004c763d5ca7c62c9811dc24/pages/view/pinsphere/bf853c54-0581-48fb-9ccf-5bbbcb9aca2c)

author_association: NONE