anear-js-api 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EACH_PARTICIPANT_LIFECYCLE.md +3 -1
- package/README.md +12 -19
- package/lib/AnearService.js +3 -3
- package/lib/models/AnearEvent.js +2 -4
- package/lib/state_machines/AnearCoreServiceMachine.js +3 -5
- package/lib/state_machines/AnearEventMachine.js +195 -360
- package/lib/utils/AssetFileCollector.js +0 -2
- package/lib/utils/DisplayEventProcessor.js +21 -40
- package/package.json +1 -1
- package/tests/DisplayEventProcessor.test.js +39 -26
- package/lib/state_machines/AnearParticipantMachine.js +0 -765
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# The `eachParticipant` Display Lifecycle
|
|
2
2
|
|
|
3
|
+
> Breaking vNext note: `AnearParticipantMachine` has been removed. `AnearEventMachine` now owns participant private channel lifecycle and `DisplayEventProcessor` publishes `PRIVATE_DISPLAY` directly to participant private channels.
|
|
4
|
+
|
|
3
5
|
This document provides a detailed, step-by-by-step breakdown of how a display targeted at `eachParticipant` travels from the application's state machine (AppM) to an individual participant's browser client.
|
|
4
6
|
|
|
5
7
|
### The Goal
|
|
@@ -10,7 +12,7 @@ We want to render a specific view (`QuestionScreen.pug`) for a single user (`par
|
|
|
10
12
|
|
|
11
13
|
The core idea is to translate a declarative `meta` block in your application's state machine (AppM) into concrete HTML content that gets delivered to a specific participant's device. This process involves a chain of components:
|
|
12
14
|
|
|
13
|
-
`AppMachineTransition` -> `AnearEventMachine` -> `DisplayEventProcessor` ->
|
|
15
|
+
`AppMachineTransition` -> `AnearEventMachine` -> `DisplayEventProcessor` -> **Ably Message**
|
|
14
16
|
|
|
15
17
|
Let's break down each step.
|
|
16
18
|
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ The anear-js-api abstracts away:
|
|
|
18
18
|
- Participant presence tracking and coordination
|
|
19
19
|
- Display rendering and template compilation
|
|
20
20
|
- Asset management (CSS, images) and CDN uploads
|
|
21
|
-
- Timeout
|
|
21
|
+
- Timeout orchestration for `allParticipants` action windows
|
|
22
22
|
- Reconnection handling and error recovery
|
|
23
23
|
|
|
24
24
|
## Architecture
|
|
@@ -28,9 +28,7 @@ The anear-js-api abstracts away:
|
|
|
28
28
|
```
|
|
29
29
|
AnearCoreServiceMachine (Root)
|
|
30
30
|
├── AnearEventMachine (Per Event)
|
|
31
|
-
│ ├── AnearParticipantMachine (Per Participant)
|
|
32
31
|
│ └── AppEventMachine (Developer's App Logic)
|
|
33
|
-
└── AppParticipantMachine (Optional, Per Participant)
|
|
34
32
|
```
|
|
35
33
|
|
|
36
34
|
### Core Components
|
|
@@ -52,30 +50,26 @@ AnearCoreServiceMachine (Root)
|
|
|
52
50
|
- Route messages between participants and app logic
|
|
53
51
|
- Manage participant presence (enter/leave/exit)
|
|
54
52
|
- Coordinate display rendering for all channels
|
|
55
|
-
- Handle
|
|
53
|
+
- Handle allParticipants timeout orchestration
|
|
56
54
|
- **Key States**: `registerCreator` → `eventCreated` → `announce` → `live` → `closeEvent`
|
|
57
55
|
|
|
58
|
-
####
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
- Manage participant timeouts and reconnection logic
|
|
63
|
-
- Track participant activity and idle states
|
|
64
|
-
- Route participant-specific actions to app logic
|
|
65
|
-
- **Key States**: `setup` → `live` → `waitReconnect` → `cleanupAndExit`
|
|
56
|
+
#### Breaking vNext: APM Removed
|
|
57
|
+
- Participant-machine orchestration is removed from JSAPI.
|
|
58
|
+
- AEM now manages participant private channel lifecycle and private display publishing directly.
|
|
59
|
+
- JSAPI no longer emits `PARTICIPANT_TIMEOUT`; participant-local timeout UX is owned by browser runtime (`<anear-timeout>`).
|
|
66
60
|
|
|
67
61
|
### Separation of Concerns: JSAPI vs. AppM
|
|
68
62
|
|
|
69
63
|
A key architectural principle is the clear separation of concerns between the Anear JSAPI (the "engine") and the App Event Machine (the "application").
|
|
70
64
|
|
|
71
|
-
#### JSAPI (AEM
|
|
65
|
+
#### JSAPI (AEM): The Engine Room
|
|
72
66
|
|
|
73
67
|
The JSAPI is responsible for all the underlying infrastructure and communication mechanics. Its concerns are purely technical:
|
|
74
68
|
|
|
75
69
|
- **Event Lifecycle & State:** Manages the low-level state transitions of an event (`created` → `announce` → `live` → `closed`) and the lifecycle of participants.
|
|
76
70
|
- **Real-time Communication:** Handles all Ably channel setup, messaging, presence events, and connection state.
|
|
77
71
|
- **Orderly Operations:** Ensures smooth, reliable startup and shutdown of all services and participant connections.
|
|
78
|
-
- **Notifier:** The JSAPI acts as a notifier. It informs the AppM of important events (`PARTICIPANT_ENTER`, `PARTICIPANT_DISCONNECT`, `ACTION`, `
|
|
72
|
+
- **Notifier:** The JSAPI acts as a notifier. It informs the AppM of important events (`PARTICIPANT_ENTER`, `PARTICIPANT_DISCONNECT`, `ACTION`, `ACTIONS_TIMEOUT`) but does not decide what these events mean for the application.
|
|
79
73
|
|
|
80
74
|
#### AppM: The Application & User Experience
|
|
81
75
|
|
|
@@ -185,7 +179,6 @@ The JSAPI handles participant lifecycle through presence events:
|
|
|
185
179
|
| `PARTICIPANT_RECONNECT` | Participant rejoins after disconnect | `HOST_RECONNECT` or `PARTICIPANT_RECONNECT` |
|
|
186
180
|
| `PARTICIPANT_EXIT` | Participant permanently leaves | `HOST_EXIT` or `PARTICIPANT_EXIT` |
|
|
187
181
|
| `PARTICIPANT_DISCONNECT` | Temporary connection loss | `HOST_DISCONNECT` or `PARTICIPANT_DISCONNECT` |
|
|
188
|
-
| `PARTICIPANT_TIMEOUT` | Participant fails to respond in time | `PARTICIPANT_TIMEOUT` |
|
|
189
182
|
| `ACTION` | Participant performs an action | Custom event (e.g., `MOVE`, `ANSWER`) |
|
|
190
183
|
|
|
191
184
|
**Key Point**: The AEM uses role-specific events (`HOST_*` vs `PARTICIPANT_*`) based on whether the user is the event creator/host. Your AppM never needs to check `isHost` - it just reacts to the specific events it receives.
|
|
@@ -236,9 +229,9 @@ PUG templates receive rich context including:
|
|
|
236
229
|
|
|
237
230
|
## Timeout Management
|
|
238
231
|
|
|
239
|
-
###
|
|
232
|
+
### Participant-local Timeouts
|
|
240
233
|
|
|
241
|
-
|
|
234
|
+
Participant-local timeout UX is handled by browser runtime (`<anear-timeout>`). JSAPI does not emit `PARTICIPANT_TIMEOUT`.
|
|
242
235
|
|
|
243
236
|
```javascript
|
|
244
237
|
meta: {
|
|
@@ -251,8 +244,7 @@ meta: {
|
|
|
251
244
|
}
|
|
252
245
|
},
|
|
253
246
|
on: {
|
|
254
|
-
MOVE: 'nextTurn'
|
|
255
|
-
PARTICIPANT_TIMEOUT: 'handleTimeout'
|
|
247
|
+
MOVE: 'nextTurn'
|
|
256
248
|
}
|
|
257
249
|
```
|
|
258
250
|
|
|
@@ -287,6 +279,7 @@ The JSAPI automatically handles asset management:
|
|
|
287
279
|
1. **CSS Upload**: All CSS files in `assets/css/` are uploaded to CloudFront
|
|
288
280
|
2. **Image Upload**: All images in `assets/images/` are uploaded to CloudFront
|
|
289
281
|
3. **Template Preloading**: All PUG templates are preloaded and cached
|
|
282
|
+
4. **Hash-based dedupe**: Asset uploads are decided by SHA-256 content hash comparison against S3 metadata (not file timestamps)
|
|
290
283
|
|
|
291
284
|
### CI-Managed Assets Mode
|
|
292
285
|
|
package/lib/AnearService.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
const AnearCoreServiceMachine = require('./state_machines/AnearCoreServiceMachine')
|
|
2
2
|
|
|
3
|
-
const AnearService = (appEventMachineFactory
|
|
3
|
+
const AnearService = (appEventMachineFactory) => {
|
|
4
4
|
//
|
|
5
5
|
// developer provides appEventMachineFactory:
|
|
6
6
|
//
|
|
7
7
|
// appEventMachineFactory = anearEvent => { returns XState Machine) }
|
|
8
|
-
//
|
|
8
|
+
// participant-level machines are no longer managed by JSAPI.
|
|
9
9
|
//
|
|
10
|
-
return AnearCoreServiceMachine(appEventMachineFactory
|
|
10
|
+
return AnearCoreServiceMachine(appEventMachineFactory)
|
|
11
11
|
}
|
|
12
12
|
module.exports = AnearService
|
package/lib/models/AnearEvent.js
CHANGED
|
@@ -111,10 +111,8 @@ class AnearEvent extends JsonApiResource {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
cancelAllParticipantTimeouts() {
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
// Useful for scenarios where a game event (e.g., LIAR call) should immediately
|
|
117
|
-
// cancel all individual participant timeouts.
|
|
114
|
+
// Cancels active allParticipants timeout tracking in AEM.
|
|
115
|
+
// Participant-local timeout ownership now lives in the browser runtime.
|
|
118
116
|
this.send({ type: "CANCEL_ALL_PARTICIPANT_TIMEOUTS" })
|
|
119
117
|
}
|
|
120
118
|
|
|
@@ -82,11 +82,10 @@ function scheduleExit(code, message) {
|
|
|
82
82
|
setTimeout(() => process.exit(code), delayMs)
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
const AnearCoreServiceMachineContext = (appId, appEventMachineFactory
|
|
85
|
+
const AnearCoreServiceMachineContext = (appId, appEventMachineFactory) => ({
|
|
86
86
|
appId,
|
|
87
87
|
appData: null,
|
|
88
88
|
appEventMachineFactory,
|
|
89
|
-
appParticipantMachineFactory,
|
|
90
89
|
anearEventMachines: {}, // All concurrent anear events handled by this core service
|
|
91
90
|
pugTemplates: {},
|
|
92
91
|
imageAssetsUrl: null,
|
|
@@ -493,14 +492,13 @@ function normalizeVersionToken(value) {
|
|
|
493
492
|
return String(value).replace(/[^A-Za-z0-9_.-]/g, '_')
|
|
494
493
|
}
|
|
495
494
|
|
|
496
|
-
const AnearCoreServiceMachine = (appEventMachineFactory
|
|
495
|
+
const AnearCoreServiceMachine = (appEventMachineFactory) => {
|
|
497
496
|
const appId = process.env.ANEARAPP_APP_ID
|
|
498
497
|
const machineConfig = AnearCoreServiceMachineConfig(appId)
|
|
499
498
|
|
|
500
499
|
const anearCoreServiceMachineContext = AnearCoreServiceMachineContext(
|
|
501
500
|
appId,
|
|
502
|
-
appEventMachineFactory
|
|
503
|
-
appParticipantMachineFactory
|
|
501
|
+
appEventMachineFactory
|
|
504
502
|
)
|
|
505
503
|
|
|
506
504
|
const coreServiceMachine = createMachine(machineConfig, AnearCoreServiceMachineFunctions)
|