feat: add TypesenseSessionService#140
Conversation
|
@gemini-cli /review |
|
🤖 Hi @DeanChensj, I've received your request, and I'm working on it now! You can track my progress in the logs for more details. |
There was a problem hiding this comment.
Thanks for the detailed contribution! The implementation of TypesenseSessionService is clean, well-tested, and follows the project's patterns.
I've left a few comments regarding:
- Memory management: The state locks dictionaries grow indefinitely.
- Scalability:
list_sessionsmight struggle with a large number of users. - Distributed concurrency: Local locks won't work in multi-instance deployments (as noted in your docstring).
Overall, this is a great addition to the community plugins. Please consider addressing the memory leak and scalability points if this is intended for high-traffic use cases.
| collection_prefix: str = 'adk', | ||
| connection_timeout_seconds: int = 5, | ||
| ): | ||
| try: |
There was a problem hiding this comment.
These dictionaries grow indefinitely as new apps or users are encountered, which could lead to a memory leak in long-running services with many unique users. Consider using an LRU cache or a similar mechanism to limit the number of active locks.
| return None | ||
|
|
||
| async def _search_all( | ||
| self, collection: str, filter_by: str, sort_by: Optional[str] = None |
There was a problem hiding this comment.
As noted in the docstring, these local locks won't synchronize state updates across multiple instances/processes. While Typesense doesn't have native transactions, using a distributed lock (e.g., via Redis) would be a more robust solution for multi-process deployments. For this community contribution, the current approach is acceptable but the limitation is worth highlighting.
| 'filter_by': filter_by, | ||
| 'sort_by': 'timestamp:desc', | ||
| 'per_page': min(remaining, 250), | ||
| 'page': page, |
There was a problem hiding this comment.
Fetching all user states for an app when user_id is None could be extremely slow and memory-intensive if the app has a large number of users. Since list_sessions already fetches session documents, perhaps user states could be fetched on-demand or only for the users returned in the session list (e.g., using a filter with multiple IDs if the number of sessions is small).
| * App and user state updates are serialized per-key within a single process. | ||
| Multi-process deployments sharing the same Typesense instance may still | ||
| lose concurrent state updates because Typesense has no native transactions. | ||
| """ |
There was a problem hiding this comment.
Nice job handling the optional typesense dependency with lazy imports and clear error messages. This keeps the core package lightweight for users who don't need this specific service.
This change adds
TypesenseSessionService, implementing all five BaseSessionService methods —create_session,get_session,list_sessions,delete_session, andappend_event— backed by Typesense collections. Four collections are managed automatically on first use({prefix}_sessions, {prefix}_events, {prefix}_app_states, {prefix}_user_states), following the same collection-per-scope pattern used by DatabaseSessionService for app, user, and session state. The typesense package is added as an optional dependency with a lazy import in init.py to avoid breaking users who don't have typesense installed.App and user state updates are serialized per-key via asyncio locks within a single process. Note that app_name, user_id, and session_id must not contain || (used as an internal document-ID separator).