Skip to content

Commit 7be5ac6

Browse files
feat: Add DatabaseSessionService with JDBC and Flyway support
Summary Implements a production-ready database-backed session service that provides persistent storage for ADK sessions, events, and state using JDBC. Key Features - JDBC with HikariCP connection pooling for optimal performance - Flyway migrations for schema versioning and zero-downtime deployments - Multi-database support: PostgreSQL, MySQL, H2, Cloud Spanner, and other RDBMS - Thread-safe operations with pessimistic locking for concurrent updates - Comprehensive test coverage with H2 in-memory database and Integration tests for PostgreSQL , MySQL and Spanner ( using emulator ) - Dialect-aware JSON storage (JSONB for PostgreSQL, CLOB for others) - Event filtering and pagination for efficient data retrieval Architecture - Located in contrib/database-session-service module - Minimal core dependencies footprint - Users explicitly opt-in via dependency - Follows existing contrib pattern
1 parent b66e4a5 commit 7be5ac6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+9687
-1
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Database Session Service
2+
3+
JDBC-based session service implementation for ADK Java.
4+
5+
## Features
6+
7+
- **No ORM Dependencies**: Uses JDBC with HikariCP for connection pooling
8+
- **Multi-Database Support**: PostgreSQL, MySQL, H2 (SQLite not supported)
9+
- **Automatic Schema Management**: Flyway migrations handle table creation/updates
10+
- **3-Tier State Storage**: Separate tables for app-level, user-level, and session-level state
11+
- **Reactive API**: RxJava 3 Single/Maybe/Completable return types
12+
13+
## Dependencies
14+
15+
- **HikariCP**: High-performance JDBC connection pool
16+
- **Flyway**: Database schema versioning and migration
17+
- **Jackson**: JSON serialization for events and state
18+
- **RxJava 3**: Reactive programming support
19+
20+
## Database Schema
21+
22+
The service creates and manages these tables:
23+
24+
- `app_states`: Application-level state (shared across all users)
25+
- `user_states`: User-level state (shared across user's sessions)
26+
- `sessions`: Individual session data
27+
- `events`: Event history for each session
28+
29+
## Usage
30+
31+
```java
32+
// Create service with database URL
33+
String dbUrl = "jdbc:postgresql://localhost:5432/adk?user=postgres&password=secret";
34+
try (DatabaseSessionService sessionService = new DatabaseSessionService(dbUrl)) {
35+
36+
// Create a session
37+
Session session = sessionService.createSession(
38+
"myApp",
39+
"user123",
40+
new ConcurrentHashMap<>(),
41+
null
42+
).blockingGet();
43+
44+
// Append an event
45+
Event event = Event.builder()
46+
.id(UUID.randomUUID().toString())
47+
.invocationId("inv-1")
48+
.timestamp(System.currentTimeMillis())
49+
.build();
50+
51+
Event appendedEvent = sessionService.appendEvent(session, event).blockingGet();
52+
}
53+
```
54+
55+
## Supported Databases
56+
57+
- **PostgreSQL**: Full support with JSONB
58+
- URL: `jdbc:postgresql://host:port/database?user=...&password=...`
59+
- **MySQL**: Full support with JSON
60+
- URL: `jdbc:mysql://host:port/database?user=...&password=...`
61+
- **H2**: For testing and development
62+
- URL: `jdbc:h2:mem:testdb` or `jdbc:h2:file:./data/mydb`
63+
- **Cloud Spanner**: Full support
64+
- URL: `jdbc:cloudspanner:/projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID`
65+
- **SQLite**: NOT supported (no UPSERT support)
66+
67+
## State Management
68+
69+
State is stored across three tables with merge priority:
70+
71+
1. **App State** (lowest priority): `app:key` prefix
72+
2. **User State** (medium priority): `user:key` prefix
73+
3. **Session State** (highest priority): No prefix
74+
75+
When retrieving a session, states are merged: app → user → session (higher priority overwrites).
76+
77+
## Configuration
78+
79+
Optional properties can be passed to the constructor:
80+
81+
```java
82+
Map<String, Object> props = new HashMap<>();
83+
props.put("connectionTimeout", 30000);
84+
props.put("maximumPoolSize", 10);
85+
86+
DatabaseSessionService service = new DatabaseSessionService(dbUrl, props);
87+
```
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Copyright 2025 Google LLC
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<project xmlns="http://maven.apache.org/POM/4.0.0"
18+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20+
<modelVersion>4.0.0</modelVersion>
21+
22+
<parent>
23+
<groupId>com.google.adk</groupId>
24+
<artifactId>google-adk-parent</artifactId>
25+
<version>0.5.1-SNAPSHOT</version>
26+
<relativePath>../../pom.xml</relativePath>
27+
</parent>
28+
29+
<artifactId>google-adk-database-session-service</artifactId>
30+
<name>Agent Development Kit - Database Session Service</name>
31+
<description>Database integration with Agent Development Kit for User Session Management</description>
32+
33+
<dependencies>
34+
<!-- ADK Core (required) -->
35+
<dependency>
36+
<groupId>com.google.adk</groupId>
37+
<artifactId>google-adk</artifactId>
38+
<version>${project.version}</version>
39+
</dependency>
40+
41+
<!-- JDBC-based persistence with minimal dependencies -->
42+
43+
<!-- HikariCP - High-performance JDBC connection pool -->
44+
<dependency>
45+
<groupId>com.zaxxer</groupId>
46+
<artifactId>HikariCP</artifactId>
47+
</dependency>
48+
49+
<!-- Jackson for JSON serialization (minimal, standard library) -->
50+
<dependency>
51+
<groupId>com.fasterxml.jackson.core</groupId>
52+
<artifactId>jackson-databind</artifactId>
53+
</dependency>
54+
55+
<!-- RxJava for reactive API (required by BaseSessionService) -->
56+
<dependency>
57+
<groupId>io.reactivex.rxjava3</groupId>
58+
<artifactId>rxjava</artifactId>
59+
</dependency>
60+
61+
<!-- SLF4J API for logging -->
62+
<dependency>
63+
<groupId>org.slf4j</groupId>
64+
<artifactId>slf4j-api</artifactId>
65+
</dependency>
66+
67+
<!-- Database Migration -->
68+
69+
<!-- Flyway Core - Database schema migration and versioning tool -->
70+
<dependency>
71+
<groupId>org.flywaydb</groupId>
72+
<artifactId>flyway-core</artifactId>
73+
</dependency>
74+
75+
<!-- Flyway PostgreSQL Support -->
76+
<dependency>
77+
<groupId>org.flywaydb</groupId>
78+
<artifactId>flyway-database-postgresql</artifactId>
79+
<scope>runtime</scope>
80+
</dependency>
81+
82+
<!-- Flyway MySQL Support -->
83+
<dependency>
84+
<groupId>org.flywaydb</groupId>
85+
<artifactId>flyway-mysql</artifactId>
86+
<scope>runtime</scope>
87+
</dependency>
88+
89+
<!-- Flyway Spanner Support -->
90+
<dependency>
91+
<groupId>org.flywaydb</groupId>
92+
<artifactId>flyway-gcp-spanner</artifactId>
93+
<scope>runtime</scope>
94+
</dependency>
95+
96+
<!-- Database Drivers (optional - users choose their own) -->
97+
98+
<!-- PostgreSQL Driver -->
99+
<dependency>
100+
<groupId>org.postgresql</groupId>
101+
<artifactId>postgresql</artifactId>
102+
<optional>true</optional>
103+
</dependency>
104+
105+
<!-- MySQL Driver -->
106+
<dependency>
107+
<groupId>com.mysql</groupId>
108+
<artifactId>mysql-connector-j</artifactId>
109+
<optional>true</optional>
110+
</dependency>
111+
112+
<!-- Spanner JDBC Driver -->
113+
<dependency>
114+
<groupId>com.google.cloud</groupId>
115+
<artifactId>google-cloud-spanner-jdbc</artifactId>
116+
<optional>true</optional>
117+
</dependency>
118+
119+
<!-- Test Dependencies -->
120+
121+
<!-- H2 Database - In-memory database for testing -->
122+
<dependency>
123+
<groupId>com.h2database</groupId>
124+
<artifactId>h2</artifactId>
125+
<scope>test</scope>
126+
</dependency>
127+
128+
<dependency>
129+
<groupId>org.junit.jupiter</groupId>
130+
<artifactId>junit-jupiter-api</artifactId>
131+
<scope>test</scope>
132+
</dependency>
133+
134+
<dependency>
135+
<groupId>org.junit.jupiter</groupId>
136+
<artifactId>junit-jupiter-params</artifactId>
137+
<scope>test</scope>
138+
</dependency>
139+
140+
<dependency>
141+
<groupId>org.junit.jupiter</groupId>
142+
<artifactId>junit-jupiter-engine</artifactId>
143+
<scope>test</scope>
144+
</dependency>
145+
146+
<dependency>
147+
<groupId>org.slf4j</groupId>
148+
<artifactId>slf4j-simple</artifactId>
149+
<scope>test</scope>
150+
</dependency>
151+
152+
<dependency>
153+
<groupId>com.google.truth</groupId>
154+
<artifactId>truth</artifactId>
155+
<scope>test</scope>
156+
</dependency>
157+
158+
<dependency>
159+
<groupId>org.mockito</groupId>
160+
<artifactId>mockito-core</artifactId>
161+
<scope>test</scope>
162+
</dependency>
163+
</dependencies>
164+
165+
<build>
166+
<resources>
167+
<resource>
168+
<directory>src/main/resources</directory>
169+
<filtering>true</filtering>
170+
</resource>
171+
</resources>
172+
<plugins>
173+
<plugin>
174+
<artifactId>maven-compiler-plugin</artifactId>
175+
</plugin>
176+
<plugin>
177+
<groupId>org.jacoco</groupId>
178+
<artifactId>jacoco-maven-plugin</artifactId>
179+
</plugin>
180+
<plugin>
181+
<groupId>org.apache.maven.plugins</groupId>
182+
<artifactId>maven-surefire-plugin</artifactId>
183+
</plugin>
184+
</plugins>
185+
</build>
186+
</project>

0 commit comments

Comments
 (0)