Replay Modes
mockd supports three replay modes for stream recordings, each suited to different testing scenarios. Understanding when to use each mode helps you create more effective and reliable tests.
Overview
Section titled “Overview”| Mode | Timing | Client Input | Best For |
|---|---|---|---|
| Pure | Original delays preserved | Ignored | Demo, playback, timing verification |
| Synchronized | Waits for client messages | Required to proceed | Protocol compliance, request-response flows |
| Triggered | Manual/API control | Optional | Step debugging, integration tests |
Pure Mode
Section titled “Pure Mode”Replays server messages with original timing, ignoring any client input.
How It Works
Section titled “How It Works”- Recording starts playing immediately on connection
- Delays between frames match the original recording (scaled by
timingScale) - Client messages are ignored - playback continues regardless
- Completes when all server frames have been sent
Use Cases
Section titled “Use Cases”- Demos: Show realistic streaming behavior
- Timing verification: Ensure client handles message timing correctly
- Load testing: Generate predictable server traffic patterns
- UI development: Develop against a predictable stream
Configuration
Section titled “Configuration”# Via Admin APIcurl -X POST http://localhost:4290/stream-recordings/01HXYZ123456/replay \ -H "Content-Type: application/json" \ -d '{ "mode": "pure", "timingScale": 1.0 }'{ "mode": "pure", "timingScale": 1.0}Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
timingScale | float | 1.0 | Speed multiplier. 0.5 = 2x speed, 2.0 = half speed |
Example: 2x Speed Playback
Section titled “Example: 2x Speed Playback”curl -X POST http://localhost:4290/stream-recordings/01HXYZ123456/replay \ -d '{"mode": "pure", "timingScale": 0.5}'Pause/Resume
Section titled “Pause/Resume”Pure mode supports pause and resume:
# Pausecurl -X POST http://localhost:4290/replay/SESSION_ID/pause
# Resumecurl -X POST http://localhost:4290/replay/SESSION_ID/resumeSynchronized Mode
Section titled “Synchronized Mode”Waits for expected client messages before sending server responses. Ensures the client follows the recorded conversation flow.
How It Works
Section titled “How It Works”- Recording analyzes client-to-server and server-to-client frame order
- When a client message is expected, replay pauses and waits
- Client must send a message (optionally matching expected content)
- After receiving client message, server responses are sent
- Timeout occurs if client doesn’t respond within limit
Use Cases
Section titled “Use Cases”- Protocol compliance testing: Verify client sends correct messages
- Integration testing: Test full request-response flows
- Conversation flow testing: Ensure proper message sequencing
- State machine validation: Test stateful WebSocket protocols
Configuration
Section titled “Configuration”curl -X POST http://localhost:4290/stream-recordings/01HXYZ123456/replay \ -H "Content-Type: application/json" \ -d '{ "mode": "synchronized", "strictMatching": false, "timeout": 30000 }'{ "mode": "synchronized", "strictMatching": false, "timeout": 30000}Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
strictMatching | bool | false | Require exact message content match |
timeout | int | 30000 | Max ms to wait for client message |
Strict vs Loose Matching
Section titled “Strict vs Loose Matching”Loose matching (default): Any client message advances the replay. Useful when message content varies but sequence matters.
Strict matching: Client message must exactly match recorded content. Useful for protocol compliance verification.
# Strict matching - client must send exact messagescurl -X POST http://localhost:4290/stream-recordings/01HXYZ123456/replay \ -d '{"mode": "synchronized", "strictMatching": true}'Timeout Handling
Section titled “Timeout Handling”If the client doesn’t send a message within the timeout:
- Replay session enters error state
ErrMatchTimeouterror is returned- Session can be stopped and restarted
Example Flow
Section titled “Example Flow”Given a recording with this sequence:
1. [s2c] Welcome message2. [c2s] Client login3. [s2c] Login success4. [c2s] Client request data5. [s2c] Data responseReplay behavior:
- Server sends “Welcome message” immediately
- Replay waits for client to send any message
- Client sends login -> Server sends “Login success”
- Replay waits for client
- Client sends request -> Server sends “Data response”
- Replay completes
Triggered Mode
Section titled “Triggered Mode”Manual control over frame advancement via API. Each frame or batch of frames is sent only when explicitly triggered.
How It Works
Section titled “How It Works”- Recording loads but doesn’t start sending
- Optionally sends first frame on connect (
autoAdvanceOnConnect) - Waits for
/replay/{id}/advanceAPI calls - Each advance sends one or more frames
- Completes when all frames have been sent
Use Cases
Section titled “Use Cases”- Step debugging: Examine state after each message
- Integration test assertions: Assert between each message
- Controlled scenarios: Precise control over message timing
- Interactive demos: Manual control for presentations
Configuration
Section titled “Configuration”curl -X POST http://localhost:4290/stream-recordings/01HXYZ123456/replay \ -H "Content-Type: application/json" \ -d '{ "mode": "triggered", "autoAdvanceOnConnect": true }'{ "mode": "triggered", "autoAdvanceOnConnect": true}Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
autoAdvanceOnConnect | bool | false | Send first frame immediately on connect |
Advancing Playback
Section titled “Advancing Playback”# Advance 1 frame (default)curl -X POST http://localhost:4290/replay/SESSION_ID/advance
# Advance N framescurl -X POST http://localhost:4290/replay/SESSION_ID/advance \ -d '{"count": 5}'
# Advance until specific contentcurl -X POST http://localhost:4290/replay/SESSION_ID/advance \ -d '{"until": "{\"type\":\"complete\"}"}'Advance Response
Section titled “Advance Response”{ "framesSent": 1, "currentFrame": 5, "totalFrames": 42, "status": "waiting", "complete": false}Example: Integration Test
Section titled “Example: Integration Test”// Start triggered replayconst { replayId } = await fetch('/stream-recordings/REC_ID/replay', { method: 'POST', body: JSON.stringify({ mode: 'triggered' })}).then(r => r.json());
// Connect WebSocketconst ws = new WebSocket('ws://localhost:4280/ws/chat');
// Advance and assertawait fetch(`/replay/${replayId}/advance`, { method: 'POST' });const msg1 = await nextMessage(ws);expect(msg1.type).toBe('welcome');
await fetch(`/replay/${replayId}/advance`, { method: 'POST' });const msg2 = await nextMessage(ws);expect(msg2.type).toBe('ready');
// Clean upawait fetch(`/replay/${replayId}`, { method: 'DELETE' });Replay Status
Section titled “Replay Status”Check replay session status:
curl http://localhost:4290/replay/SESSION_ID{ "id": "01REPLAY123456", "recordingId": "01HXYZ123456", "status": "playing", "currentFrame": 15, "totalFrames": 42, "framesSent": 15, "startedAt": "2024-01-15T10:30:00Z", "elapsedMs": 5432, "config": { "mode": "pure", "timingScale": 1.0 }}Status Values
Section titled “Status Values”| Status | Description |
|---|---|
pending | Session created, not yet started |
playing | Actively sending frames |
waiting | Waiting for client input (synchronized) or trigger (triggered) |
paused | Paused (pure mode only) |
complete | All frames sent |
aborted | Session stopped early |
Managing Replay Sessions
Section titled “Managing Replay Sessions”List Active Sessions
Section titled “List Active Sessions”curl http://localhost:4290/replayStop Replay
Section titled “Stop Replay”curl -X DELETE http://localhost:4290/replay/SESSION_IDReplay API Reference
Section titled “Replay API Reference”| Method | Endpoint | Description |
|---|---|---|
| POST | /stream-recordings/{id}/replay | Start replay for recording |
| GET | /replay | List active replay sessions |
| GET | /replay/{id} | Get replay session status |
| DELETE | /replay/{id} | Stop replay session |
| POST | /replay/{id}/advance | Advance triggered replay |
| POST | /replay/{id}/pause | Pause pure mode replay |
| POST | /replay/{id}/resume | Resume paused replay |
Mode Comparison
Section titled “Mode Comparison”When to Use Each Mode
Section titled “When to Use Each Mode”Need original timing?├── Yes → Pure Mode│ └── Want to control speed? → Use timingScale└── No ├── Need to verify client messages? → Synchronized Mode │ └── Need exact content match? → strictMatching: true └── Need step-by-step control? → Triggered Mode └── Want first frame auto-sent? → autoAdvanceOnConnect: truePerformance Characteristics
Section titled “Performance Characteristics”| Mode | CPU Usage | Memory | Network |
|---|---|---|---|
| Pure | Low | Low | Steady stream |
| Synchronized | Low (waiting) | Low | Bursty |
| Triggered | Minimal | Low | On-demand |
Common Patterns
Section titled “Common Patterns”Speed Testing
Section titled “Speed Testing”Test how client handles fast message streams:
# 10x speedcurl -X POST http://localhost:4290/stream-recordings/REC_ID/replay \ -d '{"mode": "pure", "timingScale": 0.1}'Protocol Verification
Section titled “Protocol Verification”Ensure client follows correct message sequence:
curl -X POST http://localhost:4290/stream-recordings/REC_ID/replay \ -d '{"mode": "synchronized", "strictMatching": true, "timeout": 5000}'Debugging Session
Section titled “Debugging Session”Step through messages one at a time:
# Start triggered replayREPLAY_ID=$(curl -s -X POST http://localhost:4290/stream-recordings/REC_ID/replay \ -d '{"mode": "triggered"}' | jq -r '.id')
# Step throughwhile true; do result=$(curl -s -X POST "http://localhost:4290/replay/$REPLAY_ID/advance") echo "$result" | jq
if [ "$(echo $result | jq -r '.complete')" = "true" ]; then break fi
read -p "Press enter to advance..."doneNext Steps
Section titled “Next Steps”- Stream Recording - Recording WebSocket and SSE streams
- SSE Streaming - SSE mock configuration
- Admin API - Stream recording API endpoints