Skip to content

Conversation

@mohan-ganesh
Copy link
Contributor

@mohan-ganesh mohan-ganesh commented Nov 10, 2025

This pull request adds FirestoreSessionService by implementing BaseSessionService interface that uses Firestore as the data store to manage user sessions.

Added the feature to contrib folder

here is the discussion request link https://github.com/google/adk-java/discussions/568

Why Firestore:

Firestore is a scalable, managed, and widely-used Google Cloud database. It would provide a clear, simple, and robust path for developers needing persistent sessions in production scale

Transactional Design Consideration

The createSession, appendEvent, and deleteSession methods in this service use blocking .get() calls on their Firestore ApiFuture objects. This is a deliberate design choice to guarantee data consistency within the ADK's sequential execution flow.

The appendEvent method is particularly critical. A fully non-blocking implementation could create a race condition where the Runner proceeds to the next step (e.g., calling the LLM) before the latest event and state changes are persisted. This would result in the model operating on stale data, leading to an incomplete chat history.

By blocking within the reactive stream, we ensure that the database transaction is complete before the Single or Completable emits, providing strong consistency for the Runner. This synchronous-within-asynchronous pattern is applied to all write operations for predictable and reliable behavior.

Dependencies:

Added new dependacy 'Firestore'

Testing:
All test passed with > 80% test coverage

image

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @mohan-ganesh, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request delivers a significant new feature to the Agent Development Kit (ADK) by providing a robust and scalable session management solution using Google Firestore. It allows ADK applications to persist user conversation sessions, manage application and user-specific state, and perform memory searches on past interactions. This enhancement provides developers with a powerful tool for building stateful and intelligent agents.

Highlights

  • Firestore Session Service: Introduced a new session service for the ADK that uses Google Firestore as the backend for storing user conversation sessions and events, enabling scalable and reliable session management.
  • Firestore Memory Service: Implemented a Firestore-backed memory service that allows searching memory entries based on keywords extracted from session events.
  • FirestoreDatabaseRunner: Added a new runner implementation, FirestoreDatabaseRunner, to easily integrate the Firestore session and memory services, along with GCS for artifact storage, into ADK applications.
  • Configuration and Utilities: Included a property loading utility (FirestoreProperties) for flexible configuration and an ApiFutureUtils class to bridge Google Cloud's ApiFuture with RxJava types.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a significant new feature: a session and memory service implementation using Google Firestore. The implementation is comprehensive, including the core services, a runner, configuration management, and a full suite of tests. The overall structure is well-designed. However, there are a few critical and high-severity issues that must be addressed. Most importantly, there's a resource leak in ApiFutureUtils due to an un-shutdown executor, which will prevent the application from terminating. Several classes also inefficiently create new executors on each method call. I've also included several medium-severity suggestions to improve code robustness, consistency, and maintainability, such as migrating to JUnit 5, improving the session deletion logic, and hardening the singleton pattern and type casting.

Comment on lines 477 to 489
// 1. Delete all events in the subcollection
CollectionReference eventsRef = sessionRef.collection(EVENTS_SUBCOLLECTION_NAME);
com.google.api.core.ApiFuture<com.google.cloud.firestore.QuerySnapshot> eventsQuery =
eventsRef.get();
List<QueryDocumentSnapshot> eventDocuments = eventsQuery.get().getDocuments();
List<ApiFuture<WriteResult>> deleteFutures = new ArrayList<>();
for (QueryDocumentSnapshot doc : eventDocuments) {
deleteFutures.add(doc.getReference().delete());
}
// Wait for all event deletions to complete
if (!deleteFutures.isEmpty()) {
ApiFutures.allAsList(deleteFutures).get();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The current implementation deletes documents in the events subcollection one by one after fetching them. This is inefficient and can be slow and costly for sessions with many events. It's also not atomic. You should use batched writes (WriteBatch) to delete documents in chunks of up to 500. This will be much more performant and cost-effective.

/** The template for the environment-specific property file name. */
private static final String ENV_PROPERTY_FILE_TEMPLATE = "adk-firestore-%s.properties";

private static volatile FirestoreProperties INSTANCE = new FirestoreProperties();
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The singleton INSTANCE is eagerly initialized here, but the getInstance() method uses a double-checked locking pattern, which is meant for lazy initialization. This is confusing and unnecessarily complex. Since the instance is already created, you can simplify the getInstance() method to just return INSTANCE;.

@mohan-ganesh mohan-ganesh force-pushed the feat/firestore-session-service branch 4 times, most recently from 46cae9b to 750a4b2 Compare November 13, 2025 00:57
Copy link
Contributor

@glaforge glaforge left a comment

Choose a reason for hiding this comment

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

This is a very solid PR!
It's a big one as well, and I'm not very familiar with the Firestore APIs, but on the surface it looks very good.
Gemini Code Assist made a few suggestions you might want to address (on executors, for example, and some volatile fields...) so it'd be good to have a look at some of them which make sense.

@mohan-ganesh
Copy link
Contributor Author

This is a very solid PR! It's a big one as well, and I'm not very familiar with the Firestore APIs, but on the surface it looks very good. Gemini Code Assist made a few suggestions you might want to address (on executors, for example, and some volatile fields...) so it'd be good to have a look at some of them which make sense.

thanks for taking a look at this PR @glaforge .. all of the identified suggetions are already updated and committed . i just resolved all of the open comments.

@mohan-ganesh mohan-ganesh force-pushed the feat/firestore-session-service branch 2 times, most recently from f4b8db8 to 59bd22f Compare November 20, 2025 19:43
…ent Kit) that uses Google Firestore as the backend for storing session data.
@mohan-ganesh mohan-ganesh force-pushed the feat/firestore-session-service branch from 59bd22f to f6f8ef2 Compare November 20, 2025 23:38
@mohan-ganesh
Copy link
Contributor Author

mohan-ganesh commented Nov 20, 2025

Hi @glaforge , the earlier build was fine but ran in to merge conflicts. I've force-pushed an update that resolves the merge conflicts and build issues. The branch should now be clean and ready for merging. Could you please take another look when you have a moment? Thanks!

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.

2 participants