-
-
Notifications
You must be signed in to change notification settings - Fork 761
Durable Sessions
WebSocket sessions are ephemeral — when the server restarts, all connections are lost and clients must reconnect from scratch, losing their room memberships, broadcaster subscriptions, and application metadata. Durable Sessions solve this by persisting session state to a backing store (SQLite or Redis) so that reconnecting clients automatically resume exactly where they left off.
┌──────────────┐ X-Atmosphere-Session-Token ┌──────────────────────┐
│ atmosphere.js│ ──────────────────────────────────→ │ DurableSession │
│ client │ ←────────────────────────────────── │ Interceptor │
└──────────────┘ token assigned on first connect │ │
│ save / restore │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ SessionStore SPI │
├──────────────────────┤
│ InMemorySessionStore │ (dev/test)
│ SqliteSessionStore │ (single-node)
│ RedisSessionStore │ (clustered)
└──────────────────────┘
<dependency> <groupId>org.atmosphere</groupId> <artifactId>atmosphere-spring-boot-starter</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.atmosphere</groupId> <artifactId>atmosphere-durable-sessions</artifactId> <version>4.0.1</version> </dependency> <!-- Pick one: --> <dependency> <groupId>org.atmosphere</groupId> <artifactId>atmosphere-durable-sessions-sqlite</artifactId> <version>4.0.1</version> </dependency>
atmosphere.durable-sessions.enabled=true atmosphere.durable-sessions.session-ttl-minutes=1440 atmosphere.durable-sessions.cleanup-interval-seconds=60
@Bean public SessionStore sessionStore() { return new SqliteSessionStore(Path.of("data/sessions.db")); }
If no SessionStore bean is defined, an InMemorySessionStore is used
automatically (useful for development, but sessions won't survive restarts).
import { atmosphere } from 'atmosphere.js'; const atmosphere = new Atmosphere(); const sub = await atmosphere.subscribe({ url: '/atmosphere/chat', transport: 'websocket', sessionToken: localStorage.getItem('atmo-session-token'), });
The sessionToken is sent as X-Atmosphere-Session-Token on every request.
The SessionStore interface defines six methods:
| Method | Description |
|---|---|
save(session) |
Persist a session (upsert) |
restore(token) |
Look up a session by token |
remove(token) |
Delete a session |
touch(token) |
Update the last-seen timestamp |
removeExpired(ttl) |
Find and remove sessions older than TTL |
close() |
Release resources |
public record DurableSession( String token, // unique session token String resourceId, // AtmosphereResource UUID Set<String> rooms, // room names Set<String> broadcasters, // broadcaster IDs Map<String, String> metadata, // app-defined key-value pairs Instant createdAt, Instant lastSeen ) { }
Zero-configuration, embedded database. Perfect for single-node deployments, development, and edge/IoT scenarios.
// Default: atmosphere-sessions.db in working directory var store = new SqliteSessionStore(); // Custom path var store = new SqliteSessionStore(Path.of("/data/sessions.db")); // In-memory (for testing) var store = SqliteSessionStore.inMemory();
Maven:
<dependency> <groupId>org.atmosphere</groupId> <artifactId>atmosphere-durable-sessions-sqlite</artifactId> <version>4.0.1</version> </dependency>
Sessions shared across all nodes via Redis. Ideal for multi-node production deployments and Kubernetes environments.
// Basic connection var store = new RedisSessionStore("redis://localhost:6379"); // With custom TTL var store = new RedisSessionStore("redis://localhost:6379", Duration.ofHours(12)); // Share connection with atmosphere-redis clustering var store = new RedisSessionStore(existingLettuceConnection, Duration.ofHours(24));
Maven:
<dependency> <groupId>org.atmosphere</groupId> <artifactId>atmosphere-durable-sessions-redis</artifactId> <version>4.0.1</version> </dependency>
-
First connection —
DurableSessionInterceptor.inspect()creates a newDurableSessionwith a UUID token, saves it to the store, and sends the token back viaX-Atmosphere-Session-Tokenresponse header. -
Disconnect — A listener captures the client's current rooms and broadcaster subscriptions and saves them to the store.
-
Reconnection — The client sends its token. The interceptor restores the session, re-subscribes to all broadcasters, and re-joins all rooms.
-
Cleanup — A background virtual thread periodically removes sessions that haven't been seen within the configured TTL.
If not using Spring Boot auto-configuration:
var store = new SqliteSessionStore(); var interceptor = new DurableSessionInterceptor( store, Duration.ofHours(24), // session TTL Duration.ofMinutes(1) // cleanup interval ); framework.interceptor(interceptor);
| Property | Default | Description |
|---|---|---|
atmosphere.durable-sessions.enabled |
false |
Enable durable sessions |
atmosphere.durable-sessions.session-ttl-minutes |
1440 |
Session time-to-live in minutes (24h) |
atmosphere.durable-sessions.cleanup-interval-seconds |
60 |
Expired session cleanup interval |