@river-build/sdk
Version:
For more details, visit the following resources:
116 lines • 4.22 kB
JavaScript
import { check, dlog, dlogError } from '@river-build/dlog';
import { isDefined } from './check';
import { streamIdAsString } from './id';
import { SyncState, SyncedStreamsLoop } from './syncedStreamsLoop';
export class SyncedStreams {
unpackEnvelopeOpts;
logId;
streamOpts;
syncedStreamsLoop;
highPriorityIds = new Set();
// userId is the current user id
userId;
// mapping of stream id to stream
streams = new Map();
// loggers
log;
logError;
// clientEmitter is used to proxy the events from the streams to the client
clientEmitter;
// rpcClient is used to receive sync updates from the server
rpcClient;
constructor(userId, rpcClient, clientEmitter, unpackEnvelopeOpts, logId, streamOpts) {
this.unpackEnvelopeOpts = unpackEnvelopeOpts;
this.logId = logId;
this.streamOpts = streamOpts;
this.userId = userId;
this.rpcClient = rpcClient;
this.clientEmitter = clientEmitter;
this.log = dlog('csb:cl:sync').extend(this.logId);
this.logError = dlogError('csb:cl:sync:stream').extend(this.logId);
}
get syncState() {
return this.syncedStreamsLoop?.syncState ?? SyncState.NotSyncing;
}
get pingInfo() {
return this.syncedStreamsLoop?.pingInfo;
}
stats() {
return this.syncedStreamsLoop?.stats();
}
has(streamId) {
return this.streams.get(streamIdAsString(streamId)) !== undefined;
}
get(streamId) {
return this.streams.get(streamIdAsString(streamId));
}
set(streamId, stream) {
this.log('stream set', streamId);
const id = streamIdAsString(streamId);
check(id.length > 0, 'streamId cannot be empty');
this.streams.set(id, stream);
}
setHighPriorityStreams(streamIds) {
this.highPriorityIds = new Set(streamIds);
this.syncedStreamsLoop?.setHighPriorityStreams(streamIds);
}
delete(inStreamId) {
const streamId = streamIdAsString(inStreamId);
this.streams.get(streamId)?.stop();
this.streams.delete(streamId);
}
size() {
return this.streams.size;
}
getSyncId() {
return this.syncedStreamsLoop?.getSyncId();
}
getStreams() {
return Array.from(this.streams.values());
}
getStreamIds() {
return Array.from(this.streams.keys());
}
onNetworkStatusChanged(isOnline) {
this.log('network status changed. Network online?', isOnline);
this.syncedStreamsLoop?.onNetworkStatusChanged(isOnline);
}
startSyncStreams() {
const streamRecords = Array.from(this.streams.values())
.filter((x) => isDefined(x.syncCookie))
.map((stream) => ({ syncCookie: stream.syncCookie, stream }));
this.syncedStreamsLoop = new SyncedStreamsLoop(this.clientEmitter, this.rpcClient, streamRecords, this.logId, this.unpackEnvelopeOpts, this.highPriorityIds, this.streamOpts);
this.syncedStreamsLoop.start();
}
async stopSync() {
await this.syncedStreamsLoop?.stop();
this.syncedStreamsLoop = undefined;
}
// adds stream to the sync subscription
addStreamToSync(streamId, syncCookie) {
if (!this.syncedStreamsLoop) {
return;
}
this.log('addStreamToSync', streamId);
const stream = this.streams.get(streamId);
if (!stream) {
// perhaps we called stopSync while loading a stream from persistence
this.logError('streamId not in this.streams, not adding to sync', streamId);
return;
}
this.syncedStreamsLoop.addStreamToSync(streamId, syncCookie, stream);
}
// remove stream from the sync subsbscription
async removeStreamFromSync(inStreamId) {
const streamId = streamIdAsString(inStreamId);
const stream = this.streams.get(streamId);
if (!stream) {
this.log('removeStreamFromSync streamId not found', streamId);
// no such stream
return;
}
await this.syncedStreamsLoop?.removeStreamFromSync(streamId);
this.streams.delete(streamId);
}
}
//# sourceMappingURL=syncedStreams.js.map