anear-js-api 0.2.2 → 0.3.2

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.
@@ -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)
@@ -1,7 +1,7 @@
1
1
  "use strict"
2
2
  const ErrorResponse = require('./ErrorResponse')
3
3
  const qs = require('qs')
4
- const fetch = require('node-fetch')
4
+ const fetch = require('cross-fetch')
5
5
 
6
6
  const DeveloperApiURL = "https://api.anearapp.com/developer/v1"
7
7
 
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,6 +2,7 @@
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
 
@@ -12,6 +13,9 @@ const CreateEventMessageType = 'create_event'
12
13
  const ExitEventMessageType = 'exit_event'
13
14
  const EventTransitionMessageType = 'event_transition'
14
15
 
16
+ const PRESENCE_ENTER = 'enter'
17
+ const PRESENCE_LEAVE = 'leave'
18
+
15
19
  // any channel messages sent with 5 secs (5s) of initial attach will be delivered
16
20
  // to the subscribers
17
21
  const ChannelParams = {params: {rewind: "5s"}}
@@ -26,6 +30,7 @@ class AnearMessaging {
26
30
  this.api = new AnearApi()
27
31
  this.AnearEventClass = AnearEventClass
28
32
  this.AnearParticipantClass = AnearParticipantClass
33
+ this.mutex = new Mutex()
29
34
 
30
35
 
31
36
  const baseUrl = this.api.api_base_url
@@ -62,13 +67,21 @@ class AnearMessaging {
62
67
  this.realtime.connection.on(
63
68
  "connected",
64
69
  async () => {
70
+ await this.getAppInfo(AppId)
65
71
  logger.info("Ably connected!")
66
- await this.reloadAnyEventsInProgress(AppId)
67
72
  await this.setupCreateEventChannel()
73
+ await this.reloadAnyEventsInProgress(AppId)
68
74
  }
69
75
  )
70
76
  }
71
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
+
72
85
  getChannel(channelName, channelParams = ChannelParams) {
73
86
  return this.realtime.channels.get(channelName, channelParams)
74
87
  }
@@ -81,31 +94,31 @@ class AnearMessaging {
81
94
  }
82
95
  }
83
96
 
84
- setParticipantTimer(eventId, anearParticipant, timeoutMilliseconds) {
85
- const participantId = anearParticipant.id
97
+ setParticipantTimer(eventId, participant, timeoutMilliseconds) {
98
+ const participantId = participant.id
86
99
 
87
100
  this.clearParticipantTimer(participantId)
88
101
 
89
102
  if (timeoutMilliseconds === 0) return
90
103
 
91
- logger.debug(`setting ${timeoutMilliseconds} msec timer for event ${eventId}, participant ${anearParticipant.id}`)
104
+ logger.debug(`setting ${timeoutMilliseconds} msec timer for event ${eventId}, participant ${participant.id}`)
92
105
 
93
106
  this.participantTimers[participantId] = setTimeout(
94
- async () => await this.timerExpired(eventId, anearParticipant, timeoutMilliseconds),
107
+ async () => await this.timerExpired(eventId, participant, timeoutMilliseconds),
95
108
  timeoutMilliseconds
96
109
  )
97
110
  }
98
111
 
99
- async timerExpired(eventId, anearParticipant, timeoutMilliseconds) {
100
- const participantId = anearParticipant.id
112
+ async timerExpired(eventId, participant, timeoutMilliseconds) {
113
+ const participantId = participant.id
101
114
 
102
115
  logger.debug(`participant (${eventId}, ${participantId}) TIMED OUT after ${timeoutMilliseconds} msecs`)
103
116
 
104
117
  await this.getAnearEventWithLockFromStorage(
105
118
  eventId,
106
119
  async anearEvent => {
107
- const anearParticipant = await this.getAnearParticipantFromStorage(participantId)
108
- await anearEvent.participantTimedOut(anearParticipant)
120
+ const participant = await this.getAnearParticipantFromStorage(participantId)
121
+ await anearEvent.participantTimedOut(participant)
109
122
  await anearEvent.update()
110
123
  }
111
124
  )
@@ -115,25 +128,10 @@ class AnearMessaging {
115
128
  return await this.AnearEventClass.getFromStorage(eventId, this)
116
129
  }
117
130
 
118
- async getAnearEventWithLockFromStorage(eventId, callback) {
119
- return await this.AnearEventClass.getWithLockFromStorage(
120
- eventId,
121
- callback,
122
- this
123
- )
124
- }
125
-
126
131
  async getAnearParticipantFromStorage(participantId) {
127
132
  return await this.AnearParticipantClass.getFromStorage(participantId)
128
133
  }
129
134
 
130
- async getAnearParticipantWithLockFromStorage(participantId, callback) {
131
- return await this.AnearParticipantClass.getWithLockFromStorage(
132
- participantId,
133
- callback
134
- )
135
- }
136
-
137
135
  async initEventRealtimeMessaging(anearEvent) {
138
136
 
139
137
  if (this.eventChannels.hasOwnProperty(anearEvent.id)) {
@@ -162,34 +160,45 @@ class AnearMessaging {
162
160
  // create the AnearEvent subclass, persist it in storage, and
163
161
  // initialize its realtime messaging
164
162
  //
165
- logger.info(`Ably message received....createEventMessagingCallback(${message.name})`)
163
+ logger.info(`createEventMessagingCallback(${message.name})`)
166
164
 
167
165
  try {
168
166
  const eventJson = JSON.parse(message.data)
169
167
  const anearEvent = new this.AnearEventClass(eventJson, this)
168
+
170
169
  //
171
170
  // if we are getting this event create message from history after a quick restart,
172
171
  // we just return if the event already exists
173
172
  //
174
- await this.loadOrPersistEventAndInitMessaging(anearEvent)
173
+ await this.loadOrPersistEventAndInitialize(anearEvent)
175
174
  } catch(err) {
176
175
  logger.error(err)
177
176
  }
178
177
  }
179
178
 
180
- async loadOrPersistEventAndInitMessaging(anearEvent) {
179
+ async loadOrPersistEventAndInitialize(anearEvent) {
181
180
  const eventExists = await anearEvent.exists()
182
181
 
183
182
  logger.info(`Event ${anearEvent.id} ${eventExists ? "already exists" : "does not exist"} in Storage`)
184
183
 
184
+ let loadedEvent = anearEvent
185
+
185
186
  if (!eventExists) {
186
- await anearEvent.createdEventCallback()
187
- await anearEvent.persist()
187
+ await this.runExclusive("createEventCallback", async () => {
188
+ await anearEvent.createdEventCallback()
189
+ await anearEvent.persist()
190
+ anearEvent.startStateMachine()
191
+ await this.initEventRealtimeMessaging(anearEvent)
192
+ })
193
+ } else {
194
+ loadedEvent = await this.getAnearEventFromStorage(anearEvent.id)
195
+ await this.initEventRealtimeMessaging(loadedEvent)
196
+ loadedEvent.startStateMachine()
188
197
  }
189
198
 
190
- logger.info(`New ${anearEvent.constructor.name} Event: `, anearEvent.toJSON())
199
+ logger.info(`New ${loadedEvent.constructor.name} Event: `, loadedEvent.toJSON())
191
200
 
192
- await this.initEventRealtimeMessaging(anearEvent)
201
+ return loadedEvent
193
202
  }
194
203
 
195
204
  async reloadAnyEventsInProgress(appId) {
@@ -202,7 +211,8 @@ class AnearMessaging {
202
211
  for (const eventData of events) {
203
212
  const eventJson = await this.api.getEvent(eventData.id)
204
213
  const anearEvent = new this.AnearEventClass(eventJson, this)
205
- await this.loadOrPersistEventAndInitMessaging(anearEvent)
214
+ // const loadedEvent = await this.loadOrPersistEventAndInitialize(anearEvent)
215
+ // await this.refreshActiveParticipants(loadedEvent) DOES NOT WORK YET
206
216
  }
207
217
  }
208
218
  } catch (err) {
@@ -210,6 +220,20 @@ class AnearMessaging {
210
220
  }
211
221
  }
212
222
 
223
+ async refreshActiveParticipants(anearEvent) {
224
+ const allParticipants = anearEvent.participants.active(false)
225
+
226
+ return Promise.all(
227
+ allParticipants.map(
228
+ async participant => await this.processParticipantEnter(
229
+ anearEvent,
230
+ participant.id,
231
+ participant.geoLocation
232
+ )
233
+ )
234
+ )
235
+ }
236
+
213
237
  async setupCreateEventChannel() {
214
238
  logger.info(`attaching to channel ${AnearCreateEventChannelName}`)
215
239
 
@@ -238,14 +262,14 @@ class AnearMessaging {
238
262
 
239
263
  this.subscribePresenceEvent(
240
264
  spectatorsChannel,
241
- 'enter',
242
- async message => await this.spectatorEnterMessagingCallback(anearEvent.id, message)
265
+ PRESENCE_ENTER,
266
+ async message => await this.spectatorEnterMessagingCallback(anearEvent, message)
243
267
  )
244
268
 
245
269
  this.subscribePresenceEvent(
246
270
  spectatorsChannel,
247
- 'leave',
248
- async message => await this.spectatorLeaveMessagingCallback(anearEvent.id, message)
271
+ PRESENCE_LEAVE,
272
+ async message => await this.spectatorLeaveMessagingCallback(anearEvent, message)
249
273
  )
250
274
  }
251
275
 
@@ -258,23 +282,23 @@ class AnearMessaging {
258
282
 
259
283
  await this.subscribePresenceEventWithHistory(
260
284
  actionsChannel,
261
- 'enter',
262
- async message => await this.participantEnterMessagingCallback(anearEvent.id, message)
285
+ PRESENCE_ENTER,
286
+ async message => await this.participantEnterMessagingCallback(anearEvent, message)
263
287
  )
264
288
  this.subscribeEventMessages(
265
289
  actionsChannel,
266
290
  ActionMessageType,
267
- async message => await this.participantActionMessagingCallback(anearEvent.id, message)
291
+ async message => await this.participantActionMessagingCallback(anearEvent, message)
268
292
  )
269
293
  this.subscribePresenceEvent(
270
294
  actionsChannel,
271
- 'leave',
272
- async message => await this.participantLeaveMessagingCallback(anearEvent.id, message)
295
+ PRESENCE_LEAVE,
296
+ async message => await this.participantLeaveMessagingCallback(anearEvent, message)
273
297
  )
274
298
  this.subscribeEventMessages(
275
299
  actionsChannel,
276
300
  ExitEventMessageType,
277
- async message => await this.participantExplicitExitMessagingCallback(anearEvent.id, message)
301
+ async message => await this.participantExplicitExitMessagingCallback(anearEvent, message)
278
302
  )
279
303
  }
280
304
 
@@ -298,20 +322,22 @@ class AnearMessaging {
298
322
  return participantsChannel
299
323
  }
300
324
 
301
- async participantExplicitExitMessagingCallback(eventId, message) {
325
+ async participantExplicitExitMessagingCallback(anearEvent, message) {
302
326
  //
303
327
  // client user deliberately cancels out of event
304
328
  //
305
329
  const participantId = message.data.participantId
306
330
 
307
- logger.debug(`ExitEventMessage received from ${participantId} for event ${eventId}`)
331
+ logger.debug(`ExitEventMessage received from ${participantId} for event ${anearEvent.id}`)
308
332
 
309
- await this.closeParticipant(eventId, participantId,
310
- (anearEvent, anearParticipant) => anearEvent.participantClose(anearParticipant)
333
+ await this.closeParticipant(
334
+ anearEvent,
335
+ participantId,
336
+ (anearEvent, participant) => anearEvent.participantClose(participant)
311
337
  )
312
338
  }
313
339
 
314
- async participantEnterMessagingCallback(eventId, presenceMessage) {
340
+ async participantEnterMessagingCallback(anearEvent, presenceMessage) {
315
341
  // presenceMessage.clientId is the participant's user_id
316
342
  // presenceMessage.data = {
317
343
  // id: participantId,
@@ -321,89 +347,83 @@ class AnearMessaging {
321
347
  const participantId = presenceMessage.data.id
322
348
  const geoLocation = presenceMessage.data.geoLocation
323
349
 
324
- logger.debug(`**** ENTER PARTICIPANT **** event: ${eventId}, participant: ${participantId}`)
350
+ logger.debug(`**** ENTER PARTICIPANT **** event: ${anearEvent.id}, participant: ${participantId}`)
325
351
 
352
+ await this.processParticipantEnter(anearEvent, participantId, geoLocation)
353
+ }
354
+
355
+ async processParticipantEnter(anearEvent, participantId, geoLocation) {
356
+
357
+ logger.debug(`processing Participant Enter for event: ${anearEvent.id}, participant: ${participantId}`)
326
358
  //
327
359
  // get the participant data from the API (this will also validate the participant).
328
360
  // check if the participant is already in storage, and if so, instantiate, else
329
361
  // instantiate from API response
330
362
  //
331
363
  try {
332
- logger.debug(`API fetch participant info for ${participantId}`)
333
-
334
- const anearParticipantJson = await this.api.getEventParticipantJson(participantId)
335
- const anearParticipant = new this.AnearParticipantClass(anearParticipantJson)
364
+ const participantJson = await this.api.getEventParticipantJson(participantId)
365
+ const participant = new this.AnearParticipantClass(participantJson)
336
366
 
337
- anearParticipant.geoLocation = geoLocation
338
-
339
- await this.setupPrivatePublishingChannel(anearParticipant)
367
+ participant.geoLocation = geoLocation
340
368
 
341
369
  const persistedAnearParticipant = await this.AnearParticipantClass.getFromStorage(participantId)
342
370
 
343
- const eventLockCallback = async (anearEvent) => {
344
- await anearEvent.participantEnter(anearParticipant)
345
- await anearEvent.update()
346
- }
347
-
348
371
  if (persistedAnearParticipant) {
349
- anearParticipant.appData = persistedAnearParticipant.appData
350
- await anearParticipant.update()
372
+ participant.context = persistedAnearParticipant.context
351
373
  }
352
374
 
353
- await this.getAnearEventWithLockFromStorage(anearParticipant.eventId, eventLockCallback)
354
-
375
+ await this.runExclusive("participantEnterCallback", async () => {
376
+ await this.setupPrivatePublishingChannel(participant)
377
+ await anearEvent.participantEnter(participant)
378
+ await anearEvent.update()
379
+ })
355
380
  } catch(error) {
356
381
  // participant not found or is not currently marked active at the API service
357
382
  // don't allow participation. FIX: we need to publish to the private channel
358
383
  // with an error message type.
359
- logger.error(`participantEnterMessagingCallback(${eventId}, ${participantId}) error: `, error)
384
+ logger.error(`processParticipanEnter(${anearEvent.id}, ${participantId}) error: `, error)
360
385
  }
361
386
  }
362
387
 
363
- async spectatorEnterMessagingCallback(eventId, message) {
388
+ async spectatorEnterMessagingCallback(anearEvent, message) {
364
389
  const userId = message.clientId
365
- const anearEvent = await this.getAnearEventFromStorage(eventId)
366
390
 
367
- logger.debug(`**** ENTER SPECTATOR **** event: ${eventId}, user: ${userId}`)
391
+ logger.debug(`**** ENTER SPECTATOR **** event: ${anearEvent.id}, user: ${userId}`)
368
392
 
369
393
  await anearEvent.refreshSpectator()
370
394
  }
371
395
 
372
- async spectatorLeaveMessagingCallback(eventId, message) {
396
+ async spectatorLeaveMessagingCallback(anearEvent, message) {
373
397
  const userId = message.clientId
374
- logger.debug(`**** LEAVE SPECTATOR **** event: ${eventId}, user: ${userId}`)
398
+ logger.debug(`**** LEAVE SPECTATOR **** event: ${anearEvent.id}, user: ${userId}`)
375
399
  }
376
400
 
377
- async participantLeaveMessagingCallback(eventId, message) {
401
+ async participantLeaveMessagingCallback(anearEvent, message) {
378
402
  // this can be just a temporary leave (refresh browser for example), so we don't do anything
379
403
  // for now
380
404
  const userId = message.clientId
381
405
  logger.debug(`**** LEAVE PARTICIPANT **** participantLeaveMessagingCallback(user: ${userId})`)
382
406
  }
383
407
 
384
- async closeParticipant(eventId, participantId, callback) {
408
+ async closeParticipant(anearEvent, participantId, callback) {
385
409
  logger.debug(`closeParticipant(${participantId})`)
386
410
 
387
411
  this.clearParticipantTimer(participantId)
388
412
 
389
- await this.getAnearEventWithLockFromStorage(
390
- eventId,
391
- async (anearEvent) => {
392
- const anearParticipant = await this.getAnearParticipantFromStorage(participantId)
393
-
413
+ const participant = await this.getAnearParticipantFromStorage(participantId)
394
414
 
395
- if (anearParticipant) {
396
- await this.detachParticipantPrivateChannel(eventId, anearParticipant)
415
+ if (participant) {
416
+ await this.detachParticipantPrivateChannel(anearEvent.id, participant)
397
417
 
398
- await callback(anearEvent, anearParticipant)
399
- await anearEvent.update()
400
- }
401
- }
402
- )
418
+ await this.runExclusive("closeParticipant", async () => {
419
+ await callback(anearEvent, participant)
420
+ await anearEvent.update()
421
+ })
422
+ }
403
423
  }
404
424
 
405
- async detachParticipantPrivateChannel(eventId, anearParticipant) {
406
- const userId = anearParticipant.userId
425
+ async detachParticipantPrivateChannel(eventId, participant) {
426
+ const userId = participant.userId
407
427
  const channel = this.eventChannels[eventId].privates[userId]
408
428
 
409
429
  if (channel) {
@@ -411,26 +431,33 @@ class AnearMessaging {
411
431
  delete this.eventChannels[eventId].privates[userId]
412
432
  }
413
433
  }
414
-
415
- async participantActionMessagingCallback(eventId, message) {
434
+ async participantActionMessagingCallback(anearEvent, message) {
435
+ // e.g. message.data
436
+ // {
437
+ // participantId: "93387343489",
438
+ // payload: "{"reviewResponse":{"questionId": "ab88373ccf", "decision":"approved"}}"
439
+ // }
440
+ //
441
+ // actionEventName => "reviewResponse"
442
+ // actionPayload => {questionId: "ab88373ccf", decision:"approved"}
443
+ //
416
444
  const payload = message.data.payload
417
445
  const participantId = message.data.participantId
418
446
 
419
- logger.debug(`participantActionMessagingCallback(${eventId}, ${participantId})`)
447
+ logger.debug(`participantActionMessagingCallback(${anearEvent.id}, ${participantId})`)
420
448
 
421
449
  this.clearParticipantTimer(participantId)
422
450
 
423
451
  const actionJSON = JSON.parse(payload)
424
452
  const [actionEventName, actionPayload] = Object.entries(actionJSON)[0]
425
453
 
426
- await this.getAnearEventWithLockFromStorage(
427
- eventId,
428
- async anearEvent => {
429
- const anearParticipant = await this.getAnearParticipantFromStorage(participantId)
430
- await anearEvent.participantAction(anearParticipant, actionEventName, actionPayload)
431
- await anearEvent.update()
432
- }
433
- )
454
+ const participant = await this.getAnearParticipantFromStorage(participantId)
455
+
456
+ await this.runExclusive("participantActionCallback", async () => {
457
+ await anearEvent.participantAction(participant, actionEventName, actionPayload)
458
+ await anearEvent.update()
459
+ await participant.update()
460
+ })
434
461
  }
435
462
 
436
463
  async eventBroadcastMessagingCallback(eventId, message) {
@@ -441,12 +468,12 @@ class AnearMessaging {
441
468
  await anearEvent.update()
442
469
  }
443
470
 
444
- async setupPrivatePublishingChannel(anearParticipant) {
445
- const privateChannel = this.getChannel(anearParticipant.privateChannelName, {})
446
- this.eventChannels[anearParticipant.eventId].privates[anearParticipant.userId] = privateChannel
471
+ async setupPrivatePublishingChannel(participant) {
472
+ const privateChannel = this.getChannel(participant.privateChannelName, {})
473
+ this.eventChannels[participant.eventId].privates[participant.userId] = privateChannel
447
474
  await this.attachChannel(privateChannel)
448
475
 
449
- logger.debug(`setupPrivatePublishingChannel(${anearParticipant.privateChannelName}) state ${privateChannel.state}`)
476
+ logger.debug(`setupPrivatePublishingChannel(${participant.privateChannelName}) state ${privateChannel.state}`)
450
477
  }
451
478
 
452
479
  async attachChannel(channel) {
@@ -457,6 +484,18 @@ class AnearMessaging {
457
484
  }
458
485
  }
459
486
 
487
+ async runExclusive(name, callback) {
488
+ logger.debug(`waiting for ${name} mutex`)
489
+
490
+ await this.mutex.runExclusive(
491
+ async () => {
492
+ logger.debug(`mutex ${name} locked!`)
493
+ await callback()
494
+ }
495
+ )
496
+ logger.debug(`mutex ${name} released!`)
497
+ }
498
+
460
499
  subscribeEventMessages(channel, messageType, callback) {
461
500
  channel.subscribe(messageType, callback)
462
501
  logger.debug(`subscribed to ${messageType} messages on ${channel.name}`)
@@ -505,7 +544,7 @@ class AnearMessaging {
505
544
  if (timeoutMilliseconds === 0) return
506
545
 
507
546
  participants.forEach(
508
- anearParticipant => this.setParticipantTimer(eventId, anearParticipant, timeoutMilliseconds)
547
+ participant => this.setParticipantTimer(eventId, participant, timeoutMilliseconds)
509
548
  )
510
549
  }
511
550
 
@@ -521,18 +560,18 @@ class AnearMessaging {
521
560
 
522
561
  async publishEventPrivateMessage(
523
562
  eventId,
524
- anearParticipant,
563
+ participant,
525
564
  messageType,
526
565
  css,
527
566
  message,
528
567
  timeoutMilliseconds=0,
529
568
  timeoutCallback=null) {
530
569
 
531
- const userId = anearParticipant.userId
570
+ const userId = participant.userId
532
571
  const channel = this.eventChannels[eventId].privates[userId]
533
572
  if (!channel) throw new Error(`private channel not found. invalid user id ${userId}`)
534
573
 
535
- const setTimerFunction = () => this.setParticipantTimer(eventId, anearParticipant, timeoutMilliseconds)
574
+ const setTimerFunction = () => this.setParticipantTimer(eventId, participant, timeoutMilliseconds)
536
575
 
537
576
  await this.publishChannelMessageWithTimeout(
538
577
  channel,