anear-js-api 0.1.37 → 0.3.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/lib/api/AnearApi.js +8 -1
- package/lib/api/ApiService.js +1 -1
- package/lib/index.js +2 -3
- package/lib/messaging/AnearMessaging.js +127 -126
- package/lib/messaging/__mocks__/AnearMessaging.js +0 -4
- package/lib/models/AnearEvent.js +131 -88
- package/lib/models/JsonApiResource.js +5 -38
- package/lib/utils/AnearXstate.js +71 -0
- package/lib/utils/AnearXstateDefaults.js +108 -0
- package/lib/utils/Logger.js +11 -7
- package/lib/utils/Participants.js +10 -2
- package/lib/utils/Persist.js +1 -31
- package/package.json +8 -7
- package/tests/AnearEvent.test.js +250 -129
- package/tests/AnearParticipant.test.js +5 -5
- package/tests/Participants.test.js +18 -5
- package/tests/Persist.test.js +0 -42
package/lib/api/AnearApi.js
CHANGED
|
@@ -24,6 +24,13 @@ class AnearApi extends ApiService {
|
|
|
24
24
|
return json
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
async getApp(appId) {
|
|
28
|
+
logger.debug(`API: GET app ${appId}`)
|
|
29
|
+
|
|
30
|
+
const json = await this.get("apps", {id: appId})
|
|
31
|
+
return json
|
|
32
|
+
}
|
|
33
|
+
|
|
27
34
|
async getZoneEvents(zoneId) {
|
|
28
35
|
logger.debug(`API: GET zone_events ${zoneId}`)
|
|
29
36
|
|
|
@@ -38,7 +45,7 @@ class AnearApi extends ApiService {
|
|
|
38
45
|
try {
|
|
39
46
|
const json = await this.post("transitions", {event_name: eventName}, relationships)
|
|
40
47
|
const attrs = json.data.attributes
|
|
41
|
-
logger.info(`newState is ${attrs.state}`)
|
|
48
|
+
logger.info(`API: newState is ${attrs.state}`)
|
|
42
49
|
return attrs
|
|
43
50
|
} catch(err) {
|
|
44
51
|
logger.error(err)
|
package/lib/api/ApiService.js
CHANGED
package/lib/index.js
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
const JsonApiResource = require('./models/JsonApiResource')
|
|
4
4
|
const JsonApiArrayResource = require('./models/JsonApiArrayResource')
|
|
5
|
-
const AnearEvent = require('./models/AnearEvent')
|
|
5
|
+
const {AnearEvent, logger} = require('./models/AnearEvent')
|
|
6
6
|
const AnearParticipant = require('./models/AnearParticipant')
|
|
7
7
|
const AnearMessaging = require('./messaging/AnearMessaging')
|
|
8
8
|
const AnearApiService = require('./api/ApiService')
|
|
9
|
-
const Logger = require('./utils/Logger')
|
|
10
9
|
const Fixtures = require('../tests/fixtures')
|
|
11
10
|
const MockMessaging = require('./messaging/__mocks__/AnearMessaging')
|
|
12
11
|
|
|
@@ -14,10 +13,10 @@ module.exports = {
|
|
|
14
13
|
JsonApiResource,
|
|
15
14
|
JsonApiArrayResource,
|
|
16
15
|
AnearEvent,
|
|
16
|
+
logger,
|
|
17
17
|
AnearParticipant,
|
|
18
18
|
AnearMessaging,
|
|
19
19
|
AnearApiService,
|
|
20
|
-
Logger,
|
|
21
20
|
Fixtures,
|
|
22
21
|
MockMessaging,
|
|
23
22
|
}
|
|
@@ -2,17 +2,20 @@
|
|
|
2
2
|
const Ably = require('ably/promises')
|
|
3
3
|
const AnearApi = require('../api/AnearApi')
|
|
4
4
|
const logger = require('../utils/Logger')
|
|
5
|
+
const { Mutex } = require('async-mutex')
|
|
5
6
|
|
|
6
7
|
const AppId = process.env.ANEARAPP_APP_ID
|
|
7
8
|
|
|
8
9
|
const BroadcastMessageType = 'broadcast'
|
|
9
10
|
const PublicDisplayMessageType = 'public_display'
|
|
10
|
-
const CssDisplayMessageType = 'css_display'
|
|
11
11
|
const ActionMessageType = 'client_action'
|
|
12
12
|
const CreateEventMessageType = 'create_event'
|
|
13
13
|
const ExitEventMessageType = 'exit_event'
|
|
14
14
|
const EventTransitionMessageType = 'event_transition'
|
|
15
15
|
|
|
16
|
+
const PRESENCE_ENTER = 'enter'
|
|
17
|
+
const PRESENCE_LEAVE = 'leave'
|
|
18
|
+
|
|
16
19
|
// any channel messages sent with 5 secs (5s) of initial attach will be delivered
|
|
17
20
|
// to the subscribers
|
|
18
21
|
const ChannelParams = {params: {rewind: "5s"}}
|
|
@@ -27,6 +30,7 @@ class AnearMessaging {
|
|
|
27
30
|
this.api = new AnearApi()
|
|
28
31
|
this.AnearEventClass = AnearEventClass
|
|
29
32
|
this.AnearParticipantClass = AnearParticipantClass
|
|
33
|
+
this.mutex = new Mutex()
|
|
30
34
|
|
|
31
35
|
|
|
32
36
|
const baseUrl = this.api.api_base_url
|
|
@@ -63,6 +67,7 @@ class AnearMessaging {
|
|
|
63
67
|
this.realtime.connection.on(
|
|
64
68
|
"connected",
|
|
65
69
|
async () => {
|
|
70
|
+
await this.getAppInfo(AppId)
|
|
66
71
|
logger.info("Ably connected!")
|
|
67
72
|
await this.reloadAnyEventsInProgress(AppId)
|
|
68
73
|
await this.setupCreateEventChannel()
|
|
@@ -70,6 +75,13 @@ class AnearMessaging {
|
|
|
70
75
|
)
|
|
71
76
|
}
|
|
72
77
|
|
|
78
|
+
async getAppInfo(appId) {
|
|
79
|
+
const anearApp = await this.api.getApp(appId)
|
|
80
|
+
logger.info("================")
|
|
81
|
+
logger.info(`STARTING APP ${anearApp.data.attributes['short-name']}`)
|
|
82
|
+
logger.info("================")
|
|
83
|
+
}
|
|
84
|
+
|
|
73
85
|
getChannel(channelName, channelParams = ChannelParams) {
|
|
74
86
|
return this.realtime.channels.get(channelName, channelParams)
|
|
75
87
|
}
|
|
@@ -82,31 +94,31 @@ class AnearMessaging {
|
|
|
82
94
|
}
|
|
83
95
|
}
|
|
84
96
|
|
|
85
|
-
setParticipantTimer(eventId,
|
|
86
|
-
const participantId =
|
|
97
|
+
setParticipantTimer(eventId, participant, timeoutMilliseconds) {
|
|
98
|
+
const participantId = participant.id
|
|
87
99
|
|
|
88
100
|
this.clearParticipantTimer(participantId)
|
|
89
101
|
|
|
90
102
|
if (timeoutMilliseconds === 0) return
|
|
91
103
|
|
|
92
|
-
logger.debug(`setting ${timeoutMilliseconds} msec timer for event ${eventId}, participant ${
|
|
104
|
+
logger.debug(`setting ${timeoutMilliseconds} msec timer for event ${eventId}, participant ${participant.id}`)
|
|
93
105
|
|
|
94
106
|
this.participantTimers[participantId] = setTimeout(
|
|
95
|
-
async () => await this.timerExpired(eventId,
|
|
107
|
+
async () => await this.timerExpired(eventId, participant, timeoutMilliseconds),
|
|
96
108
|
timeoutMilliseconds
|
|
97
109
|
)
|
|
98
110
|
}
|
|
99
111
|
|
|
100
|
-
async timerExpired(eventId,
|
|
101
|
-
const participantId =
|
|
112
|
+
async timerExpired(eventId, participant, timeoutMilliseconds) {
|
|
113
|
+
const participantId = participant.id
|
|
102
114
|
|
|
103
115
|
logger.debug(`participant (${eventId}, ${participantId}) TIMED OUT after ${timeoutMilliseconds} msecs`)
|
|
104
116
|
|
|
105
117
|
await this.getAnearEventWithLockFromStorage(
|
|
106
118
|
eventId,
|
|
107
119
|
async anearEvent => {
|
|
108
|
-
const
|
|
109
|
-
await anearEvent.participantTimedOut(
|
|
120
|
+
const participant = await this.getAnearParticipantFromStorage(participantId)
|
|
121
|
+
await anearEvent.participantTimedOut(participant)
|
|
110
122
|
await anearEvent.update()
|
|
111
123
|
}
|
|
112
124
|
)
|
|
@@ -116,25 +128,10 @@ class AnearMessaging {
|
|
|
116
128
|
return await this.AnearEventClass.getFromStorage(eventId, this)
|
|
117
129
|
}
|
|
118
130
|
|
|
119
|
-
async getAnearEventWithLockFromStorage(eventId, callback) {
|
|
120
|
-
return await this.AnearEventClass.getWithLockFromStorage(
|
|
121
|
-
eventId,
|
|
122
|
-
callback,
|
|
123
|
-
this
|
|
124
|
-
)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
131
|
async getAnearParticipantFromStorage(participantId) {
|
|
128
132
|
return await this.AnearParticipantClass.getFromStorage(participantId)
|
|
129
133
|
}
|
|
130
134
|
|
|
131
|
-
async getAnearParticipantWithLockFromStorage(participantId, callback) {
|
|
132
|
-
return await this.AnearParticipantClass.getWithLockFromStorage(
|
|
133
|
-
participantId,
|
|
134
|
-
callback
|
|
135
|
-
)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
135
|
async initEventRealtimeMessaging(anearEvent) {
|
|
139
136
|
|
|
140
137
|
if (this.eventChannels.hasOwnProperty(anearEvent.id)) {
|
|
@@ -163,33 +160,38 @@ class AnearMessaging {
|
|
|
163
160
|
// create the AnearEvent subclass, persist it in storage, and
|
|
164
161
|
// initialize its realtime messaging
|
|
165
162
|
//
|
|
166
|
-
logger.info(`
|
|
163
|
+
logger.info(`createEventMessagingCallback(${message.name})`)
|
|
167
164
|
|
|
168
165
|
try {
|
|
169
166
|
const eventJson = JSON.parse(message.data)
|
|
170
167
|
const anearEvent = new this.AnearEventClass(eventJson, this)
|
|
168
|
+
|
|
171
169
|
//
|
|
172
170
|
// if we are getting this event create message from history after a quick restart,
|
|
173
171
|
// we just return if the event already exists
|
|
174
172
|
//
|
|
175
|
-
await this.
|
|
173
|
+
await this.loadOrPersistEventAndInitialize(anearEvent)
|
|
176
174
|
} catch(err) {
|
|
177
175
|
logger.error(err)
|
|
178
176
|
}
|
|
179
177
|
}
|
|
180
178
|
|
|
181
|
-
async
|
|
179
|
+
async loadOrPersistEventAndInitialize(anearEvent) {
|
|
182
180
|
const eventExists = await anearEvent.exists()
|
|
183
181
|
|
|
184
182
|
logger.info(`Event ${anearEvent.id} ${eventExists ? "already exists" : "does not exist"} in Storage`)
|
|
185
183
|
|
|
186
184
|
if (!eventExists) {
|
|
187
|
-
await
|
|
188
|
-
|
|
185
|
+
await this.runExclusive("createEventCallback", async () => {
|
|
186
|
+
await anearEvent.createdEventCallback()
|
|
187
|
+
await anearEvent.persist()
|
|
188
|
+
})
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
logger.info(`New ${anearEvent.constructor.name} Event: `, anearEvent.toJSON())
|
|
192
192
|
|
|
193
|
+
anearEvent.startStateMachine()
|
|
194
|
+
|
|
193
195
|
await this.initEventRealtimeMessaging(anearEvent)
|
|
194
196
|
}
|
|
195
197
|
|
|
@@ -203,7 +205,7 @@ class AnearMessaging {
|
|
|
203
205
|
for (const eventData of events) {
|
|
204
206
|
const eventJson = await this.api.getEvent(eventData.id)
|
|
205
207
|
const anearEvent = new this.AnearEventClass(eventJson, this)
|
|
206
|
-
await this.
|
|
208
|
+
await this.loadOrPersistEventAndInitialize(anearEvent)
|
|
207
209
|
}
|
|
208
210
|
}
|
|
209
211
|
} catch (err) {
|
|
@@ -239,14 +241,14 @@ class AnearMessaging {
|
|
|
239
241
|
|
|
240
242
|
this.subscribePresenceEvent(
|
|
241
243
|
spectatorsChannel,
|
|
242
|
-
|
|
243
|
-
async message => await this.spectatorEnterMessagingCallback(anearEvent
|
|
244
|
+
PRESENCE_ENTER,
|
|
245
|
+
async message => await this.spectatorEnterMessagingCallback(anearEvent, message)
|
|
244
246
|
)
|
|
245
247
|
|
|
246
248
|
this.subscribePresenceEvent(
|
|
247
249
|
spectatorsChannel,
|
|
248
|
-
|
|
249
|
-
async message => await this.spectatorLeaveMessagingCallback(anearEvent
|
|
250
|
+
PRESENCE_LEAVE,
|
|
251
|
+
async message => await this.spectatorLeaveMessagingCallback(anearEvent, message)
|
|
250
252
|
)
|
|
251
253
|
}
|
|
252
254
|
|
|
@@ -259,23 +261,23 @@ class AnearMessaging {
|
|
|
259
261
|
|
|
260
262
|
await this.subscribePresenceEventWithHistory(
|
|
261
263
|
actionsChannel,
|
|
262
|
-
|
|
263
|
-
async message => await this.participantEnterMessagingCallback(anearEvent
|
|
264
|
+
PRESENCE_ENTER,
|
|
265
|
+
async message => await this.participantEnterMessagingCallback(anearEvent, message)
|
|
264
266
|
)
|
|
265
267
|
this.subscribeEventMessages(
|
|
266
268
|
actionsChannel,
|
|
267
269
|
ActionMessageType,
|
|
268
|
-
async message => await this.participantActionMessagingCallback(anearEvent
|
|
270
|
+
async message => await this.participantActionMessagingCallback(anearEvent, message)
|
|
269
271
|
)
|
|
270
272
|
this.subscribePresenceEvent(
|
|
271
273
|
actionsChannel,
|
|
272
|
-
|
|
273
|
-
async message => await this.participantLeaveMessagingCallback(anearEvent
|
|
274
|
+
PRESENCE_LEAVE,
|
|
275
|
+
async message => await this.participantLeaveMessagingCallback(anearEvent, message)
|
|
274
276
|
)
|
|
275
277
|
this.subscribeEventMessages(
|
|
276
278
|
actionsChannel,
|
|
277
279
|
ExitEventMessageType,
|
|
278
|
-
async message => await this.participantExplicitExitMessagingCallback(anearEvent
|
|
280
|
+
async message => await this.participantExplicitExitMessagingCallback(anearEvent, message)
|
|
279
281
|
)
|
|
280
282
|
}
|
|
281
283
|
|
|
@@ -299,20 +301,22 @@ class AnearMessaging {
|
|
|
299
301
|
return participantsChannel
|
|
300
302
|
}
|
|
301
303
|
|
|
302
|
-
async participantExplicitExitMessagingCallback(
|
|
304
|
+
async participantExplicitExitMessagingCallback(anearEvent, message) {
|
|
303
305
|
//
|
|
304
306
|
// client user deliberately cancels out of event
|
|
305
307
|
//
|
|
306
308
|
const participantId = message.data.participantId
|
|
307
309
|
|
|
308
|
-
logger.debug(`ExitEventMessage received from ${participantId} for event ${
|
|
310
|
+
logger.debug(`ExitEventMessage received from ${participantId} for event ${anearEvent.id}`)
|
|
309
311
|
|
|
310
|
-
await this.closeParticipant(
|
|
311
|
-
|
|
312
|
+
await this.closeParticipant(
|
|
313
|
+
anearEvent,
|
|
314
|
+
participantId,
|
|
315
|
+
(anearEvent, participant) => anearEvent.participantClose(participant)
|
|
312
316
|
)
|
|
313
317
|
}
|
|
314
318
|
|
|
315
|
-
async participantEnterMessagingCallback(
|
|
319
|
+
async participantEnterMessagingCallback(anearEvent, presenceMessage) {
|
|
316
320
|
// presenceMessage.clientId is the participant's user_id
|
|
317
321
|
// presenceMessage.data = {
|
|
318
322
|
// id: participantId,
|
|
@@ -322,91 +326,80 @@ class AnearMessaging {
|
|
|
322
326
|
const participantId = presenceMessage.data.id
|
|
323
327
|
const geoLocation = presenceMessage.data.geoLocation
|
|
324
328
|
|
|
325
|
-
logger.debug(`**** ENTER PARTICIPANT **** event: ${
|
|
329
|
+
logger.debug(`**** ENTER PARTICIPANT **** event: ${anearEvent.id}, participant: ${participantId}`)
|
|
326
330
|
|
|
327
331
|
//
|
|
328
|
-
// get the participant data from the API (this will also validate the participant).
|
|
329
|
-
// check if the participant is already in storage, and if so, instantiate, else
|
|
332
|
+
// get the participant data from the API (this will also validate the participant).
|
|
333
|
+
// check if the participant is already in storage, and if so, instantiate, else
|
|
330
334
|
// instantiate from API response
|
|
331
335
|
//
|
|
332
336
|
try {
|
|
333
337
|
logger.debug(`API fetch participant info for ${participantId}`)
|
|
334
338
|
|
|
335
|
-
const
|
|
336
|
-
const
|
|
339
|
+
const participantJson = await this.api.getEventParticipantJson(participantId)
|
|
340
|
+
const participant = new this.AnearParticipantClass(participantJson)
|
|
337
341
|
|
|
338
|
-
|
|
342
|
+
participant.geoLocation = geoLocation
|
|
339
343
|
|
|
340
|
-
await this.setupPrivatePublishingChannel(
|
|
344
|
+
await this.setupPrivatePublishingChannel(participant)
|
|
341
345
|
|
|
342
346
|
const persistedAnearParticipant = await this.AnearParticipantClass.getFromStorage(participantId)
|
|
343
347
|
|
|
344
|
-
const eventLockCallback = async (anearEvent) => {
|
|
345
|
-
await anearEvent.publishCss(anearParticipant)
|
|
346
|
-
await anearEvent.participantEnter(anearParticipant)
|
|
347
|
-
await anearEvent.update()
|
|
348
|
-
}
|
|
349
|
-
|
|
350
348
|
if (persistedAnearParticipant) {
|
|
351
|
-
|
|
352
|
-
await anearParticipant.update()
|
|
349
|
+
participant.context = persistedAnearParticipant.context
|
|
353
350
|
}
|
|
354
351
|
|
|
355
|
-
await this.
|
|
356
|
-
|
|
352
|
+
await this.runExclusive("participantEnterCallback", async () => {
|
|
353
|
+
await anearEvent.participantEnter(participant)
|
|
354
|
+
await anearEvent.update()
|
|
355
|
+
})
|
|
357
356
|
} catch(error) {
|
|
358
357
|
// participant not found or is not currently marked active at the API service
|
|
359
358
|
// don't allow participation. FIX: we need to publish to the private channel
|
|
360
359
|
// with an error message type.
|
|
361
|
-
logger.error(`participantEnterMessagingCallback(${
|
|
360
|
+
logger.error(`participantEnterMessagingCallback(${anearEvent.id}, ${participantId}) error: `, error)
|
|
362
361
|
}
|
|
363
362
|
}
|
|
364
363
|
|
|
365
|
-
async spectatorEnterMessagingCallback(
|
|
364
|
+
async spectatorEnterMessagingCallback(anearEvent, message) {
|
|
366
365
|
const userId = message.clientId
|
|
367
|
-
const anearEvent = await this.getAnearEventFromStorage(eventId)
|
|
368
366
|
|
|
369
|
-
logger.debug(`**** ENTER SPECTATOR **** event: ${
|
|
367
|
+
logger.debug(`**** ENTER SPECTATOR **** event: ${anearEvent.id}, user: ${userId}`)
|
|
370
368
|
|
|
371
|
-
await anearEvent.publishSpectatorCss()
|
|
372
369
|
await anearEvent.refreshSpectator()
|
|
373
370
|
}
|
|
374
371
|
|
|
375
|
-
async spectatorLeaveMessagingCallback(
|
|
372
|
+
async spectatorLeaveMessagingCallback(anearEvent, message) {
|
|
376
373
|
const userId = message.clientId
|
|
377
|
-
logger.debug(`**** LEAVE SPECTATOR **** event: ${
|
|
374
|
+
logger.debug(`**** LEAVE SPECTATOR **** event: ${anearEvent.id}, user: ${userId}`)
|
|
378
375
|
}
|
|
379
376
|
|
|
380
|
-
async participantLeaveMessagingCallback(
|
|
377
|
+
async participantLeaveMessagingCallback(anearEvent, message) {
|
|
381
378
|
// this can be just a temporary leave (refresh browser for example), so we don't do anything
|
|
382
379
|
// for now
|
|
383
380
|
const userId = message.clientId
|
|
384
381
|
logger.debug(`**** LEAVE PARTICIPANT **** participantLeaveMessagingCallback(user: ${userId})`)
|
|
385
382
|
}
|
|
386
383
|
|
|
387
|
-
async closeParticipant(
|
|
384
|
+
async closeParticipant(anearEvent, participantId, callback) {
|
|
388
385
|
logger.debug(`closeParticipant(${participantId})`)
|
|
389
386
|
|
|
390
387
|
this.clearParticipantTimer(participantId)
|
|
391
388
|
|
|
392
|
-
await this.
|
|
393
|
-
eventId,
|
|
394
|
-
async (anearEvent) => {
|
|
395
|
-
const anearParticipant = await this.getAnearParticipantFromStorage(participantId)
|
|
396
|
-
|
|
389
|
+
const participant = await this.getAnearParticipantFromStorage(participantId)
|
|
397
390
|
|
|
398
|
-
|
|
399
|
-
|
|
391
|
+
if (participant) {
|
|
392
|
+
await this.detachParticipantPrivateChannel(anearEvent.id, participant)
|
|
400
393
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
}
|
|
405
|
-
|
|
394
|
+
await this.runExclusive("closeParticipant", async () => {
|
|
395
|
+
await callback(anearEvent, participant)
|
|
396
|
+
await anearEvent.update()
|
|
397
|
+
})
|
|
398
|
+
}
|
|
406
399
|
}
|
|
407
400
|
|
|
408
|
-
async detachParticipantPrivateChannel(eventId,
|
|
409
|
-
const userId =
|
|
401
|
+
async detachParticipantPrivateChannel(eventId, participant) {
|
|
402
|
+
const userId = participant.userId
|
|
410
403
|
const channel = this.eventChannels[eventId].privates[userId]
|
|
411
404
|
|
|
412
405
|
if (channel) {
|
|
@@ -414,26 +407,33 @@ class AnearMessaging {
|
|
|
414
407
|
delete this.eventChannels[eventId].privates[userId]
|
|
415
408
|
}
|
|
416
409
|
}
|
|
417
|
-
|
|
418
|
-
|
|
410
|
+
async participantActionMessagingCallback(anearEvent, message) {
|
|
411
|
+
// e.g. message.data
|
|
412
|
+
// {
|
|
413
|
+
// participantId: "93387343489",
|
|
414
|
+
// payload: "{"reviewResponse":{"questionId": "ab88373ccf", "decision":"approved"}}"
|
|
415
|
+
// }
|
|
416
|
+
//
|
|
417
|
+
// actionEventName => "reviewResponse"
|
|
418
|
+
// actionPayload => {questionId: "ab88373ccf", decision:"approved"}
|
|
419
|
+
//
|
|
419
420
|
const payload = message.data.payload
|
|
420
421
|
const participantId = message.data.participantId
|
|
421
422
|
|
|
422
|
-
logger.debug(`participantActionMessagingCallback(${
|
|
423
|
+
logger.debug(`participantActionMessagingCallback(${anearEvent.id}, ${participantId})`)
|
|
423
424
|
|
|
424
425
|
this.clearParticipantTimer(participantId)
|
|
425
426
|
|
|
426
427
|
const actionJSON = JSON.parse(payload)
|
|
427
428
|
const [actionEventName, actionPayload] = Object.entries(actionJSON)[0]
|
|
428
429
|
|
|
429
|
-
await this.
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
)
|
|
430
|
+
const participant = await this.getAnearParticipantFromStorage(participantId)
|
|
431
|
+
|
|
432
|
+
await this.runExclusive("participantActionCallback", async () => {
|
|
433
|
+
await anearEvent.participantAction(participant, actionEventName, actionPayload)
|
|
434
|
+
await anearEvent.update()
|
|
435
|
+
await participant.update()
|
|
436
|
+
})
|
|
437
437
|
}
|
|
438
438
|
|
|
439
439
|
async eventBroadcastMessagingCallback(eventId, message) {
|
|
@@ -444,12 +444,12 @@ class AnearMessaging {
|
|
|
444
444
|
await anearEvent.update()
|
|
445
445
|
}
|
|
446
446
|
|
|
447
|
-
async setupPrivatePublishingChannel(
|
|
448
|
-
const privateChannel = this.getChannel(
|
|
449
|
-
this.eventChannels[
|
|
447
|
+
async setupPrivatePublishingChannel(participant) {
|
|
448
|
+
const privateChannel = this.getChannel(participant.privateChannelName, {})
|
|
449
|
+
this.eventChannels[participant.eventId].privates[participant.userId] = privateChannel
|
|
450
450
|
await this.attachChannel(privateChannel)
|
|
451
451
|
|
|
452
|
-
logger.debug(`setupPrivatePublishingChannel(${
|
|
452
|
+
logger.debug(`setupPrivatePublishingChannel(${participant.privateChannelName}) state ${privateChannel.state}`)
|
|
453
453
|
}
|
|
454
454
|
|
|
455
455
|
async attachChannel(channel) {
|
|
@@ -460,6 +460,18 @@ class AnearMessaging {
|
|
|
460
460
|
}
|
|
461
461
|
}
|
|
462
462
|
|
|
463
|
+
async runExclusive(name, callback) {
|
|
464
|
+
logger.debug(`waiting for ${name} mutex`)
|
|
465
|
+
|
|
466
|
+
await this.mutex.runExclusive(
|
|
467
|
+
async () => {
|
|
468
|
+
logger.debug(`mutex ${name} locked!`)
|
|
469
|
+
await callback()
|
|
470
|
+
}
|
|
471
|
+
)
|
|
472
|
+
logger.debug(`mutex ${name} released!`)
|
|
473
|
+
}
|
|
474
|
+
|
|
463
475
|
subscribeEventMessages(channel, messageType, callback) {
|
|
464
476
|
channel.subscribe(messageType, callback)
|
|
465
477
|
logger.debug(`subscribed to ${messageType} messages on ${channel.name}`)
|
|
@@ -488,7 +500,7 @@ class AnearMessaging {
|
|
|
488
500
|
}
|
|
489
501
|
}
|
|
490
502
|
|
|
491
|
-
async publishEventParticipantsMessage(eventId, participants, message, timeoutMilliseconds=0, timeoutCallback=null) {
|
|
503
|
+
async publishEventParticipantsMessage(eventId, participants, css, message, timeoutMilliseconds=0, timeoutCallback=null) {
|
|
492
504
|
const channel = this.eventChannels[eventId].participants
|
|
493
505
|
|
|
494
506
|
const setTimerFunction = () => this.setMultipleParticipantTimers(eventId, participants, timeoutMilliseconds)
|
|
@@ -496,6 +508,7 @@ class AnearMessaging {
|
|
|
496
508
|
await this.publishChannelMessageWithTimeout(
|
|
497
509
|
channel,
|
|
498
510
|
PublicDisplayMessageType,
|
|
511
|
+
css,
|
|
499
512
|
message,
|
|
500
513
|
timeoutMilliseconds,
|
|
501
514
|
setTimerFunction,
|
|
@@ -507,53 +520,39 @@ class AnearMessaging {
|
|
|
507
520
|
if (timeoutMilliseconds === 0) return
|
|
508
521
|
|
|
509
522
|
participants.forEach(
|
|
510
|
-
|
|
523
|
+
participant => this.setParticipantTimer(eventId, participant, timeoutMilliseconds)
|
|
511
524
|
)
|
|
512
525
|
}
|
|
513
526
|
|
|
514
|
-
async publishEventSpectatorsMessage(eventId, message, messageType = PublicDisplayMessageType) {
|
|
527
|
+
async publishEventSpectatorsMessage(eventId, css, message, messageType = PublicDisplayMessageType) {
|
|
515
528
|
const channel = this.eventChannels[eventId].spectators
|
|
516
|
-
const payload = {
|
|
529
|
+
const payload = {
|
|
530
|
+
css: css,
|
|
531
|
+
content: message
|
|
532
|
+
}
|
|
517
533
|
|
|
518
534
|
await this.publishChannelMessage(channel, messageType, payload)
|
|
519
535
|
}
|
|
520
536
|
|
|
521
|
-
async publishEventCssMessage(eventId, anearParticipant, cssMessage) {
|
|
522
|
-
logger.debug(`publishEventCssMessage(${eventId})`)
|
|
523
|
-
|
|
524
|
-
await this.publishEventPrivateMessage(
|
|
525
|
-
eventId,
|
|
526
|
-
anearParticipant,
|
|
527
|
-
CssDisplayMessageType,
|
|
528
|
-
cssMessage
|
|
529
|
-
)
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
async publishSpectatorsCssMessage(eventId, cssMessage) {
|
|
533
|
-
await this.publishEventSpectatorsMessage(
|
|
534
|
-
eventId,
|
|
535
|
-
cssMessage,
|
|
536
|
-
CssDisplayMessageType
|
|
537
|
-
)
|
|
538
|
-
}
|
|
539
|
-
|
|
540
537
|
async publishEventPrivateMessage(
|
|
541
538
|
eventId,
|
|
542
|
-
|
|
539
|
+
participant,
|
|
543
540
|
messageType,
|
|
541
|
+
css,
|
|
544
542
|
message,
|
|
545
543
|
timeoutMilliseconds=0,
|
|
546
544
|
timeoutCallback=null) {
|
|
547
545
|
|
|
548
|
-
const userId =
|
|
546
|
+
const userId = participant.userId
|
|
549
547
|
const channel = this.eventChannels[eventId].privates[userId]
|
|
550
548
|
if (!channel) throw new Error(`private channel not found. invalid user id ${userId}`)
|
|
551
549
|
|
|
552
|
-
const setTimerFunction = () => this.setParticipantTimer(eventId,
|
|
550
|
+
const setTimerFunction = () => this.setParticipantTimer(eventId, participant, timeoutMilliseconds)
|
|
553
551
|
|
|
554
552
|
await this.publishChannelMessageWithTimeout(
|
|
555
553
|
channel,
|
|
556
554
|
messageType,
|
|
555
|
+
css,
|
|
557
556
|
message,
|
|
558
557
|
timeoutMilliseconds,
|
|
559
558
|
setTimerFunction,
|
|
@@ -564,6 +563,7 @@ class AnearMessaging {
|
|
|
564
563
|
async publishChannelMessageWithTimeout(
|
|
565
564
|
channel,
|
|
566
565
|
messageType,
|
|
566
|
+
css,
|
|
567
567
|
message,
|
|
568
568
|
timeoutMilliseconds=0,
|
|
569
569
|
setTimerFunction,
|
|
@@ -575,6 +575,7 @@ class AnearMessaging {
|
|
|
575
575
|
}
|
|
576
576
|
|
|
577
577
|
const payload = {
|
|
578
|
+
css: css,
|
|
578
579
|
content: message,
|
|
579
580
|
timeout: timeoutMilliseconds
|
|
580
581
|
}
|