Skip to content

Commit 7b0f805

Browse files
committed
fix: cached profiles when user is deleted (#78)
1 parent 637a8e7 commit 7b0f805

File tree

5 files changed

+70
-12
lines changed

5 files changed

+70
-12
lines changed

Changelog.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
### [0.0.33] -2025/5/26
1+
### [0.0.34] - unrealeased
2+
3+
**Fixed**
4+
5+
- remove cached profiles after user is deleted
6+
7+
8+
9+
10+
11+
### [0.0.33] - 2025/5/26
212

313
**Added**
414

@@ -15,7 +25,7 @@
1525

1626

1727

18-
### [0.0.32] -2025/5/14
28+
### [0.0.32] - 2025/5/14
1929

2030
**Added**
2131

src/server/api/memobase_server/controllers/profile.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from pydantic import ValidationError
22
from ..models.utils import Promise
33
from ..models.database import GeneralBlob, UserProfile
4-
from ..models.response import CODE, IdData, IdsData, UserProfilesData
4+
from ..models.response import CODE, IdData, IdsData, UserProfilesData, ProfileAttributes
55
from ..connectors import Session, get_redis_client
66
from ..utils import get_encoded_tokens
77
from ..env import LOG, CONFIG
@@ -122,6 +122,13 @@ async def add_user_profiles(
122122
assert len(profiles) == len(
123123
attributes
124124
), "Length of profiles, attributes must be equal"
125+
for attr in attributes:
126+
try:
127+
ProfileAttributes.model_validate(attr)
128+
except ValidationError as e:
129+
return Promise.reject(
130+
CODE.SERVER_PARSE_ERROR, f"Invalid profile attributes: {e}"
131+
)
125132
with Session() as session:
126133
db_profiles = [
127134
UserProfile(
@@ -132,8 +139,7 @@ async def add_user_profiles(
132139
session.add_all(db_profiles)
133140
session.commit()
134141
profile_ids = [profile.id for profile in db_profiles]
135-
async with get_redis_client() as redis_client:
136-
await redis_client.delete(f"user_profiles::{project_id}::{user_id}")
142+
await refresh_user_profile_cache(user_id, project_id)
137143
return Promise.resolve(IdsData(ids=profile_ids))
138144

139145

@@ -166,8 +172,7 @@ async def update_user_profiles(
166172
db_profile.attributes = attribute
167173
db_profiles.append(profile_id)
168174
session.commit()
169-
async with get_redis_client() as redis_client:
170-
await redis_client.delete(f"user_profiles::{project_id}::{user_id}")
175+
await refresh_user_profile_cache(user_id, project_id)
171176
return Promise.resolve(IdsData(ids=db_profiles))
172177

173178

@@ -186,8 +191,7 @@ async def delete_user_profile(
186191
)
187192
session.delete(db_profile)
188193
session.commit()
189-
async with get_redis_client() as redis_client:
190-
await redis_client.delete(f"user_profiles::{project_id}::{user_id}")
194+
await refresh_user_profile_cache(user_id, project_id)
191195
return Promise.resolve(None)
192196

193197

@@ -201,6 +205,11 @@ async def delete_user_profiles(
201205
UserProfile.project_id == project_id,
202206
).delete(synchronize_session=False)
203207
session.commit()
208+
await refresh_user_profile_cache(user_id, project_id)
209+
return Promise.resolve(IdsData(ids=profile_ids))
210+
211+
212+
async def refresh_user_profile_cache(user_id: str, project_id: str) -> Promise[None]:
204213
async with get_redis_client() as redis_client:
205214
await redis_client.delete(f"user_profiles::{project_id}::{user_id}")
206-
return Promise.resolve(IdsData(ids=profile_ids))
215+
return Promise.resolve(None)

src/server/api/memobase_server/controllers/user.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from ..models.database import User, GeneralBlob, UserProfile
33
from ..models.response import CODE, UserData, IdData, IdsData, UserProfilesData
44
from ..connectors import Session
5+
from .profile import refresh_user_profile_cache
56
from ..models.blob import BlobType
67

78

@@ -58,7 +59,8 @@ async def delete_user(user_id: str, project_id: str) -> Promise[None]:
5859
return Promise.reject(CODE.NOT_FOUND, f"User {user_id} not found")
5960
session.delete(db_user)
6061
session.commit()
61-
return Promise.resolve(None)
62+
await refresh_user_profile_cache(user_id, project_id)
63+
return Promise.resolve(None)
6264

6365

6466
async def get_user_all_blobs(

src/server/api/memobase_server/models/response.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ class ChatModalResponse(BaseModel):
6363
)
6464

6565

66+
class ProfileAttributes(BaseModel):
67+
topic: str = Field(..., description="The topic of the profile")
68+
sub_topic: str = Field(..., description="The sub-topic of the profile")
69+
70+
6671
class ProfileData(BaseModel):
6772
id: UUID = Field(..., description="The profile's unique identifier")
6873
content: str = Field(..., description="User profile content value")

src/server/api/tests/test_controller.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import pytest
2-
from memobase_server import controllers
2+
from memobase_server.controllers import full as controllers
33
from memobase_server.models import response as res
44
from memobase_server.models.blob import BlobType
55
from memobase_server.models.database import DEFAULT_PROJECT_ID
@@ -30,6 +30,38 @@ async def test_user_curd(db_env):
3030
assert not p.ok()
3131

3232

33+
@pytest.mark.asyncio
34+
async def test_user_state_clean(db_env):
35+
p = await controllers.user.create_user(
36+
res.UserData(data={"test": 1}), DEFAULT_PROJECT_ID
37+
)
38+
assert p.ok()
39+
d = p.data()
40+
u_id = d.id
41+
42+
p = await controllers.user.get_user(u_id, DEFAULT_PROJECT_ID)
43+
assert p.ok()
44+
d = p.data().data
45+
assert d["test"] == 1
46+
47+
p = await controllers.profile.add_user_profiles(
48+
u_id, DEFAULT_PROJECT_ID, ["test"], [{"topic": "test", "sub_topic": "test"}]
49+
)
50+
assert p.ok()
51+
p = await controllers.profile.get_user_profiles(u_id, DEFAULT_PROJECT_ID)
52+
assert p.ok()
53+
d = p.data()
54+
assert len(d.profiles) == 1
55+
assert d.profiles[0].attributes == {"topic": "test", "sub_topic": "test"}
56+
57+
p = await controllers.user.delete_user(u_id, DEFAULT_PROJECT_ID)
58+
assert p.ok()
59+
p = await controllers.user.get_user(u_id, DEFAULT_PROJECT_ID)
60+
assert not p.ok()
61+
p = await controllers.profile.get_user_profiles(u_id, DEFAULT_PROJECT_ID)
62+
assert p.ok() and len(p.data().profiles) == 0
63+
64+
3365
@pytest.mark.asyncio
3466
async def test_blob_curd(db_env):
3567
p = await controllers.user.create_user(res.UserData(), DEFAULT_PROJECT_ID)

0 commit comments

Comments
 (0)