-
Notifications
You must be signed in to change notification settings - Fork 120
feat: Implement a RDMS backed PushNotificationConfigStore #301
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Summary of ChangesHello @kabir, 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 enhancement by introducing a new module that enables the persistence of push notification configurations using a relational database via JPA. This change moves away from an in-memory storage solution, providing greater durability and scalability for managing push notification settings. The implementation is designed for ease of adoption, acting as a direct replacement for existing in-memory stores, and is thoroughly tested to ensure robust operation. Highlights
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this 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 new module for a JPA-backed PushNotificationConfigStore, which is a great addition for persistent storage. The implementation is solid and well-tested with both unit and integration tests. My review includes a few suggestions for improvement, mainly around code cleanup (removing unused imports), consistency (adding newlines at end of files), a small fix in the documentation, and a performance optimization in the setInfo method to make it more efficient.
.../extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java
Outdated
Show resolved
Hide resolved
.../extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java
Outdated
Show resolved
Hide resolved
...n/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java
Outdated
Show resolved
Hide resolved
...e-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/TaskConfigId.java
Outdated
Show resolved
Hide resolved
...ificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java
Show resolved
Hide resolved
.../test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/TestAgentCardProducer.java
Outdated
Show resolved
Hide resolved
.../src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/TestAgentExecutor.java
Outdated
Show resolved
Hide resolved
Interaction with the RDBMS happens with JPA
| ```xml | ||
| <dependency> | ||
| <groupId>io.github.a2asdk</groupId> | ||
| <artifactId>a2a-java-extras-pushnotificationconfigstore-database-jpa</artifactId> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very minor, wondering if we should add some hyphens in pushnotificationconfigstore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fjuma I'm not sure :-) I originally had some, but then noticed that the taskstore one did not. But I agree it is a bit long.
How about push-notification-config-store, and renaming the other one to task-store?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds good to me.
|
/gemini review |
There was a problem hiding this 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 valuable feature: a JPA-backed implementation of PushNotificationConfigStore, allowing push notification configurations to be persisted in a relational database. This is a great enhancement for production deployments. The implementation is well-structured, using standard JPA practices with entities and an embedded ID. The addition of comprehensive unit and integration tests ensures the new component is robust and works as expected. The refactoring to rename test utility classes for better clarity is also a welcome improvement. My review includes a few suggestions to refine the JPA usage and improve code clarity.
| // Create new entity | ||
| JpaPushNotificationConfig jpaConfig = JpaPushNotificationConfig.createFromConfig(taskId, notificationConfig); | ||
| em.merge(jpaConfig); | ||
| LOGGER.debug("Persisted new PushNotificationConfig for Task '{}' with ID: {}", | ||
| taskId, notificationConfig.id()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For persisting a new entity instance, em.persist() is generally preferred over em.merge(). While merge works, it's designed to handle detached entities by copying their state to a managed instance. Since you've confirmed the entity is new with em.find(), using persist is more idiomatic and can be slightly more efficient as it doesn't need to perform a check to see if the entity is already managed.
// Create new entity
JpaPushNotificationConfig jpaConfig = JpaPushNotificationConfig.createFromConfig(taskId, notificationConfig);
em.persist(jpaConfig);
LOGGER.debug("Persisted new PushNotificationConfig for Task '{}' with ID: {}",
taskId, notificationConfig.id());
| } catch (Exception e) { | ||
| LOGGER.error("Failed to retrieve PushNotificationConfigs for Task '{}'", taskId, e); | ||
| throw e; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The catch (Exception e) block is too broad. It's better to catch more specific exceptions. In this context, the operations within the try block (JPA queries and stream processing of deserialized objects) are expected to throw RuntimeException subclasses (like PersistenceException or the one we throw for JSON errors). Catching Exception could unintentionally catch checked exceptions that are not declared in the method signature, or other unexpected exceptions. To make the code safer and more explicit, you should catch RuntimeException.
} catch (RuntimeException e) {
LOGGER.error("Failed to retrieve PushNotificationConfigs for Task '{}'", taskId, e);
throw e;
}| public void setConfig(String taskId, PushNotificationConfig config) throws JsonProcessingException { | ||
| configJson = Utils.OBJECT_MAPPER.writeValueAsString(config); | ||
| if (this.id == null) { | ||
| this.id = new TaskConfigId(taskId, config.id()); | ||
| } | ||
| this.config = config; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The setConfig method's responsibility is a bit unclear because it contains logic to set the entity's ID. An entity's primary key should be immutable after it's been persisted. While the logic is guarded by a null check, it's better to separate the concerns of creation and updating. The createFromConfig factory method already handles ID assignment during creation. This method should focus solely on updating the configuration data of an existing entity.
I suggest simplifying setConfig to only update the configJson and config fields, and removing the taskId parameter. The call in JpaDatabasePushNotificationConfigStore would then be simplified to existingJpaConfig.setConfig(notificationConfig);.
public void setConfig(PushNotificationConfig config) throws JsonProcessingException {
configJson = Utils.OBJECT_MAPPER.writeValueAsString(config);
this.config = config;
}…#301) Interaction with the RDBMS happens with JPA. Also renamed the JPA TaskStore AgentCard and AgentExecutor test producers since I am not a fan of having lots of classes with the same name
Interaction with the RDBMS happens with JPA.
Also renamed the JPA TaskStore AgentCard and AgentExecutor test producers since I am not a fan of having lots of classes with the same name