import { IClient , ISignalClient } from "@fluidframework/protocol-definitions" ; import { IClientManager } from "@fluidframework/server-services-core" ; import { executeRedisMultiWithHmsetExpire , IRedisParameters } from "@fluidframework/server-services-utils" ; import { Redis } from "ioredis" ; import * as winston from "winston" ; import { Lumberjack } from "@fluidframework/server-services-telemetry" ; export class ClientManager implements IClientManager { private readonly expireAfterSeconds : number = 60 * 60 * 24 ; private readonly prefix : string = "client" ; constructor ( private readonly client , parameters ? ) { if ( parameters ?. expireAfterSeconds ) { this . expireAfterSeconds = parameters . expireAfterSeconds ; } if ( parameters ?. prefix ) { this . prefix = parameters . prefix ; } client . on ( "error" , ( error ) => { winston . error ( "Client Manager Redis Error:" , error ) ; Lumberjack . error ( "Client Manager Redis Error" , undefined , error ) ; } ) ; } public async addClient ( tenantId , documentId , clientId , details ) { const key = this . getKey ( tenantId , documentId ) ; const data = { [ clientId ] : JSON . stringify ( details ) } ; return executeRedisMultiWithHmsetExpire ( this . client , key , data , this . expireAfterSeconds ) ; } public async removeClient ( tenantId , documentId , clientId ) { await this . client . hdel ( this . getKey ( tenantId , documentId ) , clientId ) ; } public async getClients ( tenantId , documentId ) { const dbClients = await this . client . hgetall ( this . getKey ( tenantId , documentId ) ) ; const clients = [ ] ; if ( dbClients ) { for ( const clientId of Object . keys ( dbClients ) ) { clients . push ( { clientId , client : JSON . parse ( dbClients [ clientId ] ) } ) ; } } return clients ; } private getKey ( tenantId , documentId ) { return `${ this . prefix }:${ tenantId }:${ documentId }` ; } }