@@ -13,6 +13,20 @@ import { type ClaimUpdate, processPresence } from './lib/presenceEngine';
1313const MAX_CONNECTIONS = 200 ;
1414const MAX_TIMEOUT_DELAY_MS = 2 ** 31 - 1 ;
1515
16+ type PresenceUser = Pick <
17+ IUser ,
18+ | '_id'
19+ | 'username'
20+ | 'roles'
21+ | 'status'
22+ | 'statusDefault'
23+ | 'statusSource'
24+ | 'statusText'
25+ | 'statusExpiresAt'
26+ | 'statusConnection'
27+ | 'previousState'
28+ > ;
29+
1630export class Presence extends ServiceClass implements IPresence {
1731 protected name = 'presence' ;
1832
@@ -111,8 +125,8 @@ export class Presence extends ServiceClass implements IPresence {
111125 // TODO: in MS mode every instance runs this independently.
112126 // Add a job-level lock to avoid redundant cross-instance reads.
113127 const expiredCursor = Users . findExpiredStatuses ( ) ;
114- for await ( const { _id } of expiredCursor ) {
115- await this . updateUserPresence ( _id , { type : 'endActive' } ) ;
128+ for await ( const user of expiredCursor ) {
129+ await this . updateUserPresence ( user , { type : 'endActive' } ) ;
116130 }
117131 }
118132
@@ -338,39 +352,28 @@ export class Presence extends ServiceClass implements IPresence {
338352 * Low-level presence update. Does not reschedule the expiration job.
339353 * Prefer {@link updatePresenceAndReschedule} for public-facing methods.
340354 */
341- private async updateUserPresence ( uid : string , claimUpdate ?: ClaimUpdate ) : Promise < boolean > {
342- const user = await Users . findOneById <
343- Pick <
344- IUser ,
345- | '_id'
346- | 'username'
347- | 'roles'
348- | 'status'
349- | 'statusDefault'
350- | 'statusSource'
351- | 'statusText'
352- | 'statusExpiresAt'
353- | 'statusConnection'
354- | 'previousState'
355- >
356- > ( uid , {
357- projection : {
358- username : 1 ,
359- roles : 1 ,
360- status : 1 ,
361- statusDefault : 1 ,
362- statusSource : 1 ,
363- statusText : 1 ,
364- statusExpiresAt : 1 ,
365- statusConnection : 1 ,
366- previousState : 1 ,
367- } ,
368- } ) ;
355+ private async updateUserPresence ( uidOrUser : string | PresenceUser , claimUpdate ?: ClaimUpdate ) : Promise < boolean > {
356+ const user =
357+ typeof uidOrUser === 'string'
358+ ? await Users . findOneById < PresenceUser > ( uidOrUser , {
359+ projection : {
360+ username : 1 ,
361+ roles : 1 ,
362+ status : 1 ,
363+ statusDefault : 1 ,
364+ statusSource : 1 ,
365+ statusText : 1 ,
366+ statusExpiresAt : 1 ,
367+ statusConnection : 1 ,
368+ previousState : 1 ,
369+ } ,
370+ } )
371+ : uidOrUser ;
369372 if ( ! user ) {
370373 return false ;
371374 }
372375
373- const userSessions = await UsersSessions . findOneById ( uid ) ;
376+ const userSessions = await UsersSessions . findOneById ( user . _id ) ;
374377 const sessions = userSessions ?. connections ?? [ ] ;
375378
376379 const result = processPresence ( user , sessions , claimUpdate ) ;
@@ -388,7 +391,7 @@ export class Presence extends ServiceClass implements IPresence {
388391 }
389392 : undefined ;
390393
391- const updatedUser = await Users . updatePresenceAndStatus ( uid , result . values , result . clear , guard ) ;
394+ const updatedUser = await Users . updatePresenceAndStatus ( user . _id , result . values , result . clear , guard ) ;
392395 if ( updatedUser ) {
393396 this . broadcast ( updatedUser , user . status ) ;
394397 }
0 commit comments