anear-js-api 0.4.38 → 0.4.39

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.
@@ -40,6 +40,7 @@ const AnearParticipantMachineContext = (anearParticipant, anearEvent, appPartici
40
40
  appParticipantMachineFactory,
41
41
  appParticipantMachine: null,
42
42
  actionTimeoutMsecs: null,
43
+ actionTimeoutStart: null,
43
44
  lastSeen: CurrentDateTimestamp()
44
45
  })
45
46
 
@@ -71,10 +72,7 @@ const AnearParticipantMachineConfig = participantId => ({
71
72
  on: {
72
73
  ATTACHED: {
73
74
  actions: [
74
- (context, event) => logger.debug(
75
- "APM Got ATTACHED for privateChannel for ",
76
- context.anearParticipant.id
77
- ),
75
+ 'logAttached',
78
76
  'sendParticipantReady'
79
77
  ],
80
78
  target: '#setupAppMachine'
@@ -90,7 +88,7 @@ const AnearParticipantMachineConfig = participantId => ({
90
88
  },
91
89
  live: {
92
90
  id: 'live',
93
- entry: (c, e) => logger.debug(`Participant ${participantId} is LIVE!`),
91
+ entry: 'logLive',
94
92
  initial: 'idle',
95
93
  states: {
96
94
  idle: {
@@ -105,28 +103,46 @@ const AnearParticipantMachineConfig = participantId => ({
105
103
  target: 'waitReconnect'
106
104
  },
107
105
  PARTICIPANT_EXIT: {
108
- actions: (c, e) => logger.debug('APM got PARTICIPANT_EXIT. Exiting...'),
106
+ actions: 'logExit',
109
107
  target: '#cleanupAndExit'
110
108
  },
111
- ACTION: {
112
- actions: ['updateLastSeen', 'sendActionToAppParticipantMachine']
113
- }
109
+ PARTICIPANT_RECONNECT: [
110
+ {
111
+ cond: 'hasRemainingTimeoutAndRenderEvent',
112
+ actions: [
113
+ 'logReconnected',
114
+ 'republishWithRemainingTimeout'
115
+ ],
116
+ target: 'waitParticipantResponse'
117
+ },
118
+ {
119
+ actions: 'logReconnected',
120
+ target: 'idle'
121
+ }
122
+ ]
114
123
  }
115
124
  },
116
125
  waitReconnect: {
117
- entry: (c, e) => logger.info(`Participant ${c.anearParticipant.id} has DISCONNECTED`),
126
+ entry: 'logDisconnected',
118
127
  after: {
119
- reconnectTimeout: {
120
- actions: [c => logger.info(`Participant ${c.anearParticipant.id} never RECONNECTED. Exiting.`)],
121
- target: '#cleanupAndExit'
122
- }
128
+ dynamicReconnectTimeout: [
129
+ {
130
+ cond: 'wasMidTurnOnDisconnect',
131
+ actions: 'logActionTimeoutWhileDisconnected',
132
+ target: '#participantTimedOut'
133
+ },
134
+ {
135
+ actions: 'logNeverReconnected',
136
+ target: '#cleanupAndExit'
137
+ }
138
+ ]
123
139
  },
124
140
  on: {
125
141
  PARTICIPANT_EXIT: {
126
142
  target: '#cleanupAndExit'
127
143
  },
128
144
  PARTICIPANT_RECONNECT: {
129
- actions: (c, e) => logger.info(`Participant ${c.anearParticipant.id} has RECONNECTED`),
145
+ actions: 'logReconnected',
130
146
  target: 'idle'
131
147
  }
132
148
  }
@@ -146,6 +162,11 @@ const AnearParticipantMachineConfig = participantId => ({
146
162
  }
147
163
  },
148
164
  waitParticipantResponse: {
165
+ always: {
166
+ cond: 'isTimeoutImmediate',
167
+ actions: 'logImmediateTimeout',
168
+ target: '#participantTimedOut'
169
+ },
149
170
  after: {
150
171
  actionTimeout: {
151
172
  actions: 'nullActionTimeout',
@@ -160,28 +181,32 @@ const AnearParticipantMachineConfig = participantId => ({
160
181
  'nullActionTimeout'
161
182
  ],
162
183
  target: 'idle'
184
+ },
185
+ PARTICIPANT_DISCONNECT: {
186
+ actions: 'updateRemainingTimeoutOnDisconnect',
187
+ target: 'waitReconnect'
163
188
  }
164
189
  }
165
190
  },
166
191
  participantTimedOut: {
167
192
  id: 'participantTimedOut',
168
- entry: 'sendTimeoutEvents',
193
+ entry: ['sendTimeoutEvents', 'nullActionTimeout'],
169
194
  always: 'idle'
170
195
  },
171
196
  cleanupAndExit: {
172
197
  id: 'cleanupAndExit',
173
198
  // Ignore most events during cleanup, but allow exit displays
174
199
  on: {
175
- RENDER_DISPLAY: { actions: (c, e) => logger.debug('APM ignoring RENDER_DISPLAY during cleanup') },
176
- PRIVATE_DISPLAY: { actions: (c, e) => logger.debug('APM ignoring PRIVATE_DISPLAY during cleanup') },
200
+ RENDER_DISPLAY: { actions: 'logIgnoringRenderDisplayCleanup' },
201
+ PRIVATE_DISPLAY: { actions: 'logIgnoringPrivateDisplayCleanup' },
177
202
  PARTICIPANT_EXIT: {
178
- actions: () => logger.debug('APM ignoring redundant PARTICIPANT_EXIT during cleanup')
203
+ actions: 'logIgnoringRedundantExit'
179
204
  },
180
205
  PARTICIPANT_RECONNECT: {
181
- actions: () => logger.debug('APM ignoring PARTICIPANT_RECONNECT during cleanup - already timed out')
206
+ actions: 'logIgnoringReconnectCleanup'
182
207
  },
183
208
  ACTION: {
184
- actions: () => logger.debug('APM ignoring ACTION during cleanup')
209
+ actions: 'logIgnoringActionCleanup'
185
210
  }
186
211
  },
187
212
  invoke: {
@@ -202,10 +227,10 @@ const AnearParticipantMachineConfig = participantId => ({
202
227
  entry: ['notifyEventMachineExit'],
203
228
  // Final state - ignore all events except exit displays
204
229
  on: {
205
- RENDER_DISPLAY: { actions: () => logger.debug('APM ignoring RENDER_DISPLAY in final state') },
206
- PRIVATE_DISPLAY: { actions: () => logger.debug('APM ignoring PRIVATE_DISPLAY in final state') },
230
+ RENDER_DISPLAY: { actions: 'logIgnoringRenderDisplayDone' },
231
+ PRIVATE_DISPLAY: { actions: 'logIgnoringPrivateDisplayDone' },
207
232
  '*': {
208
- actions: (_c, e) => logger.debug('APM ignoring event in final state: ', e.type)
233
+ actions: 'logIgnoringEventDone'
209
234
  }
210
235
  },
211
236
  type: 'final'
@@ -256,8 +281,40 @@ const AnearParticipantMachineFunctions = {
256
281
  updateLastSeen: assign({
257
282
  lastSeen: context => CurrentDateTimestamp()
258
283
  }),
259
- updateActionTimeout: assign({actionTimeoutMsecs: (_c, event) => event.data.timeout}),
260
- nullActionTimeout: assign({actionTimeoutMsecs: _c => null}),
284
+ updateActionTimeout: assign((context, event) => {
285
+ const newTimeoutDuration = event.data.timeout
286
+
287
+ if (context.actionTimeoutStart) {
288
+ const elapsed = CurrentDateTimestamp() - context.actionTimeoutStart
289
+ const remaining = newTimeoutDuration - elapsed
290
+ logger.debug(`[APM] Resuming timer for ${context.anearParticipant.id} with ${remaining}ms remaining`)
291
+ return {
292
+ actionTimeoutMsecs: remaining > 0 ? remaining : 0
293
+ }
294
+ } else {
295
+ logger.debug(`[APM] Starting new timer for ${context.anearParticipant.id} with ${newTimeoutDuration}ms`)
296
+ return {
297
+ actionTimeoutMsecs: newTimeoutDuration,
298
+ actionTimeoutStart: CurrentDateTimestamp()
299
+ }
300
+ }
301
+ }),
302
+ nullActionTimeout: assign({
303
+ actionTimeoutMsecs: _c => null,
304
+ actionTimeoutStart: _c => null
305
+ }),
306
+ updateRemainingTimeoutOnDisconnect: assign((context, event) => {
307
+ if (context.actionTimeoutStart) {
308
+ const elapsed = CurrentDateTimestamp() - context.actionTimeoutStart
309
+ const remaining = context.actionTimeoutMsecs - elapsed
310
+ const remainingMsecs = remaining > 0 ? remaining : 0
311
+ logger.debug(`[APM] Participant disconnected mid-turn. Storing remaining timeout of ${remainingMsecs}ms`)
312
+ return {
313
+ actionTimeoutMsecs: remainingMsecs
314
+ }
315
+ }
316
+ return {}
317
+ }),
261
318
  notifyEventMachineExit: (context, event) => {
262
319
  context.anearEvent.send('PARTICIPANT_MACHINE_EXIT', { participantId: context.anearParticipant.id })
263
320
  },
@@ -268,7 +325,23 @@ const AnearParticipantMachineFunctions = {
268
325
  } else {
269
326
  logger.error("Error details:", event.data);
270
327
  }
271
- }
328
+ },
329
+ logAttached: (c, e) => logger.debug(`[APM] Got ATTACHED for privateChannel for ${c.anearParticipant.id}`),
330
+ logLive: (c, e) => logger.debug(`[APM] Participant ${c.anearParticipant.id} is LIVE!`),
331
+ logExit: (c, e) => logger.debug('[APM] got PARTICIPANT_EXIT. Exiting...'),
332
+ logDisconnected: (c, e) => logger.info(`[APM] Participant ${c.anearParticipant.id} has DISCONNECTED`),
333
+ logActionTimeoutWhileDisconnected: c => logger.info(`[APM] Participant ${c.anearParticipant.id} timed out on action while disconnected.`),
334
+ logNeverReconnected: c => logger.info(`[APM] Participant ${c.anearParticipant.id} never RECONNECTED. Exiting.`),
335
+ logReconnected: (c, e) => logger.info(`[APM] Participant ${c.anearParticipant.id} has RECONNECTED`),
336
+ logImmediateTimeout: (c, e) => logger.debug(`[APM] Timeout of ${c.actionTimeoutMsecs}ms is immediate for ${c.anearParticipant.id}.`),
337
+ logIgnoringRenderDisplayCleanup: (c, e) => logger.debug('[APM] ignoring RENDER_DISPLAY during cleanup'),
338
+ logIgnoringPrivateDisplayCleanup: (c, e) => logger.debug('[APM] ignoring PRIVATE_DISPLAY during cleanup'),
339
+ logIgnoringRedundantExit: () => logger.debug('[APM] ignoring redundant PARTICIPIPANT_EXIT during cleanup'),
340
+ logIgnoringReconnectCleanup: () => logger.debug('[APM] ignoring PARTICIPANT_RECONNECT during cleanup - already timed out'),
341
+ logIgnoringActionCleanup: () => logger.debug('[APM] ignoring ACTION during cleanup'),
342
+ logIgnoringRenderDisplayDone: () => logger.debug('[APM] ignoring RENDER_DISPLAY in final state'),
343
+ logIgnoringPrivateDisplayDone: () => logger.debug('[APM] ignoring PRIVATE_DISPLAY in final state'),
344
+ logIgnoringEventDone: (_c, e) => logger.debug('[APM] ignoring event in final state: ', e.type)
272
345
  },
273
346
  services: {
274
347
  publishPrivateDisplay: async (context, event) => {
@@ -289,11 +362,22 @@ const AnearParticipantMachineFunctions = {
289
362
  },
290
363
  guards: {
291
364
  hasAppParticipantMachine: context => context.appParticipantMachineFactory !== null,
292
- hasActionTimeout: (_c, event) => event.data && event.data.timeout > 0
365
+ hasActionTimeout: (_c, event) => event.data && event.data.timeout > 0,
366
+ isTimeoutImmediate: context => context.actionTimeoutMsecs !== null && context.actionTimeoutMsecs <= 0,
367
+ wasMidTurnOnDisconnect: context => context.actionTimeoutMsecs !== null && context.actionTimeoutMsecs > 0
293
368
  },
294
369
  delays: {
295
370
  actionTimeout: context => context.actionTimeoutMsecs,
296
- reconnectTimeout: _c => C.TIMEOUT_MSECS.RECONNECT // client must reconnect in this time
371
+ dynamicReconnectTimeout: context => {
372
+ // If an action timeout is active, use its remaining time.
373
+ if (context.actionTimeoutMsecs !== null && context.actionTimeoutMsecs > 0) {
374
+ logger.debug(`[APM] Using remaining action timeout for reconnect window: ${context.actionTimeoutMsecs}ms`)
375
+ return context.actionTimeoutMsecs
376
+ }
377
+ // Otherwise, use the standard reconnect timeout.
378
+ logger.debug(`[APM] Using standard reconnect timeout: ${C.TIMEOUT_MSECS.RECONNECT}ms`)
379
+ return C.TIMEOUT_MSECS.RECONNECT
380
+ }
297
381
  }
298
382
  }
299
383
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anear-js-api",
3
- "version": "0.4.38",
3
+ "version": "0.4.39",
4
4
  "description": "Javascript Developer API for Anear Apps",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {