Skip to content

feat: add TypesenseSessionService#140

Open
deniskrds wants to merge 7 commits into
google:mainfrom
deniskrds:feat/7-typesense-session-service
Open

feat: add TypesenseSessionService#140
deniskrds wants to merge 7 commits into
google:mainfrom
deniskrds:feat/7-typesense-session-service

Conversation

@deniskrds
Copy link
Copy Markdown

This change adds TypesenseSessionService, implementing all five BaseSessionService methods — create_session, get_session, list_sessions, delete_session, and append_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).

@DeanChensj
Copy link
Copy Markdown
Collaborator

@gemini-cli /review

@github-actions
Copy link
Copy Markdown

🤖 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.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. Memory management: The state locks dictionaries grow indefinitely.
  2. Scalability: list_sessions might struggle with a large number of users.
  3. 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:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
"""
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add Typesense-based session service

2 participants