You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: specs/002-session-state-machine/spec.md
+12-12Lines changed: 12 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -67,27 +67,27 @@ As a developer building a distributed application on top of Raft with the client
67
67
68
68
### Acceptance Scenarios
69
69
70
-
1.**Given** a developer has defined a simple user state machine (e.g., a counter), **When** a client submits a command with a new session ID and request ID, **Then** the client-server layer detects it's not a duplicate, forwards it to the user state machine, processes the command, caches the response, and returns the result to the client.
70
+
1.**Given** a developer has extended SessionStateMachine with their business logic, **When** a client submits a command with a new session ID and request ID, **Then** the base class template method detects it's not a duplicate, narrows state to UserSchema, calls the user's applyCommand method, merges changes, caches the response, and returns the result to the client.
71
71
72
-
2.**Given** a client submits the same command twice (same session ID and request ID), **When** the second request arrives, **Then** the client-server layer detects the duplicate, retrieves the cached response, and returns it without invoking the user state machine again.
72
+
2.**Given** a client submits the same command twice (same session ID and request ID), **When** the second request arrives, **Then** the base class template method detects the duplicate, retrieves the cached response, and returns it without calling the user's applyCommand method again.
73
73
74
-
3.**Given** a developer has defined a user state machine, **When** they wire it into their application by routing RaftAction events from the client-server library to the state machine and sending state machine responses back via ServerAction events, **Then** all commands flow through idempotency checking automatically.
74
+
3.**Given** a developer has extended SessionStateMachine, **When** they wire it into their application by converting RaftAction events from the client-server library to SessionCommand and applying to the state machine, and sending state machine responses back via ServerAction events, **Then** all commands flow through the base class template method's idempotency checking automatically.
75
75
76
-
4.**Given** a user state machine processes a command and returns an error, **When** the client retries with the same request ID, **Then** the cached error response is returned without reprocessing the command.
76
+
4.**Given** a user's applyCommand method processes a command and returns an error, **When** the client retries with the same request ID, **Then** the base class template method returns the cached error response without calling applyCommand again.
77
77
78
-
5.**Given** multiple clients submit different commands in parallel, **When** Raft applies these commands in consensus order, **Then** each command goes through idempotency checking and is processed exactly once by the user state machine.
78
+
5.**Given** multiple clients submit different commands in parallel, **When** Raft applies these commands in consensus order, **Then** each command goes through the template method's idempotency checking and is processed exactly once by the user's applyCommand method.
79
79
80
-
6.**Given** a user state machine generates server-initiated requests during command processing, **When** the state machine returns these requests, **Then** the user takes them and sends via ServerAction.SendServerRequest through the client-server library, and the session state machine tracks them as pending until acknowledged.
80
+
6.**Given** a user's applyCommand method generates server-initiated requests during command processing, **When** the method returns these in the (response, List[SR]) tuple, **Then** the base class template method adds them to pending state and returns them, and the user sends them via ServerAction.SendServerRequest through the client-server library.
81
81
82
-
7.**Given** a user state machine needs to produce side effects (e.g., send a message to a client), **When** processing a command, **Then** the state machine returns both a response and a list of server-initiated requests, which the user must send through the client-server library.
82
+
7.**Given** a user's applyCommand method needs to produce side effects (e.g., send a message to a client), **When** processing a command, **Then** the method returns both a response and a list of server-initiated requests (in the tuple), which the base class returns to the user who must send them through the client-server library.
83
83
84
84
8.**Given** a client receives a server-initiated request, **When** the client processes it, **Then** the client immediately sends an acknowledgment (ServerRequestAck) back to the server.
85
85
86
-
9.**Given** the server receives a ServerRequestAck for request ID N, **When** it is committed through Raft, **Then** the session state machine removes all pending server-initiated requests with ID ≤ N from its pending state (cumulative acknowledgment).
86
+
9.**Given** the server receives a ServerRequestAck for request ID N, **When** it is committed through Raft, **Then** the base class template method removes all pending server-initiated requests with ID ≤ N from the session state (cumulative acknowledgment).
87
87
88
88
10.**Given** an external retry process needs to resend server-initiated requests, **When** it performs a dirty read of the state machine's unacknowledged list and applies retry policy locally, **Then** if the policy indicates requests need retry, it sends a GetRequestsForRetry command and the state machine atomically identifies requests, updates their lastSentAt, and returns the authoritative list. The process discards the dirty read data and uses only the command response. (Optimization: dirty read allows skipping command when nothing needs retry)
89
89
90
-
11.**Given** a Raft cluster performs a snapshot, **When**capturing state, **Then**both the user state machine state and the client-server session state (including response cache and pending server-initiated requests) are included in the snapshot.
90
+
11.**Given** a Raft cluster performs a snapshot, **When**the user's takeSnapshot method is called, **Then** the user serializes the entire HMap[CombinedSchema[UserSchema]] which contains both session state (SessionSchema prefixes) and user business logic state (UserSchema prefixes), including response cache and pending server-initiated requests.
91
91
92
92
### Edge Cases
93
93
@@ -123,11 +123,11 @@ As a developer building a distributed application on top of Raft with the client
123
123
-**FR-015**: System MUST NOT impose size limits on cached responses (for now)
124
124
125
125
#### State Machine Interface (Library Provides)
126
-
-**FR-016**: System MUST provide a state machine interface that accepts RaftAction events (ClientRequest, ServerRequestAck, SessionCreationConfirmed, SessionExpired) and returns state transitions
126
+
-**FR-016**: System MUST provide a state machine interface that accepts SessionCommand commands (ClientRequest, ServerRequestAck, SessionCreationConfirmed, SessionExpired, GetRequestsForRetry) and returns state transitions. Note: Users convert RaftAction events from client-server library to SessionCommand at the integration layer.
127
127
-**FR-017**: System MUST return responses that the user can send via ServerAction.SendResponse through the client-server library (library does NOT send responses directly)
128
128
-**FR-018**: System MUST return server-initiated requests that the user can send via ServerAction.SendServerRequest through the client-server library (library does NOT send requests directly)
129
-
-**FR-019**: System MUST process RaftAction.ClientRequest events by performing idempotency checking, invoking user state machine, caching responses, and returning the response
130
-
-**FR-020**: System MUST process RaftAction.ServerRequestAck events to remove acknowledged server-initiated requests from the session state machine; when processing an acknowledgment for request ID N, the system MUST remove all pending requests with ID ≤ N (cumulative acknowledgment)
129
+
-**FR-019**: System MUST process SessionCommand.ClientRequest by performing idempotency checking, calling user's applyCommand method, caching responses, and returning the response
130
+
-**FR-020**: System MUST process SessionCommand.ServerRequestAck to remove acknowledged server-initiated requests from the session state; when processing an acknowledgment for request ID N, the system MUST remove all pending requests with ID ≤ N (cumulative acknowledgment)
131
131
-**FR-021**: System MUST allow user state machines to generate server-initiated requests as part of command processing, which are added to pending state and returned for the user to send
-**ZIOClock service used for all time operations**- verify Instant values come from ZIOClock, not Instant.now() or System.currentTimeMillis() (PrincipleIV)
330
+
-**No java.util.Random or UUID.randomUUID()**- only ZIORandom service if needed (PrincipleIV)
329
331
-**Success**:All constitutional requirements met
330
332
331
333
- [ ] **T043**Code review and cleanup
@@ -387,6 +389,7 @@ Different files, no dependencies:
0 commit comments