@livedigital/client 3.48.0 → 3.49.1

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.
Files changed (166) hide show
  1. package/LICENSE +1 -1
  2. package/dist/constants/encodings.d.ts +3 -3
  3. package/dist/constants/encodings.ts +3 -3
  4. package/dist/engine/handlers/ChannelAudioObserverEventHandler.d.ts +3 -1
  5. package/dist/engine/handlers/ChannelAudioObserverMissingProducerRestorer.d.ts +10 -0
  6. package/dist/engine/handlers/MediaEventHandler.d.ts +0 -1
  7. package/dist/engine/index.d.ts +7 -4
  8. package/dist/engine/network/DatachannelHeartbeater.d.ts +2 -2
  9. package/dist/engine/network/NetworkTransportPolicyManager.d.ts +22 -0
  10. package/dist/engine/network/index.d.ts +10 -8
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.es.js +2 -2
  13. package/dist/index.js +2 -2
  14. package/dist/inversify.tokens.d.ts +3 -1
  15. package/dist/types/network.d.ts +6 -6
  16. package/package.json +2 -3
  17. package/src/ClientMetaProvider.ts +0 -41
  18. package/src/EnhancedEventEmitter.ts +0 -75
  19. package/src/config/ConfigService.ts +0 -66
  20. package/src/constants/common.ts +0 -85
  21. package/src/constants/encodings.ts +0 -26
  22. package/src/constants/events.ts +0 -126
  23. package/src/constants/mutex.ts +0 -6
  24. package/src/constants/stats.ts +0 -1
  25. package/src/constants/videoConstrains.ts +0 -21
  26. package/src/engine/CallState.ts +0 -19
  27. package/src/engine/ChannelStateSynchronizer/ChannelStateSynchronizer.ts +0 -448
  28. package/src/engine/ChannelStateSynchronizer/types.ts +0 -22
  29. package/src/engine/EventsQueue.ts +0 -255
  30. package/src/engine/IntegrationsService.ts +0 -163
  31. package/src/engine/LocalMutex.ts +0 -45
  32. package/src/engine/Logger.ts +0 -234
  33. package/src/engine/MyPeer.ts +0 -25
  34. package/src/engine/Peer.ts +0 -602
  35. package/src/engine/PeerConsumer.ts +0 -276
  36. package/src/engine/PeerProducer.ts +0 -50
  37. package/src/engine/Peers.ts +0 -150
  38. package/src/engine/PeersStorage.ts +0 -45
  39. package/src/engine/RemotePeerTracks.ts +0 -73
  40. package/src/engine/WIDHandler.ts +0 -166
  41. package/src/engine/WebRTCStats/ConnectionStatsManager.ts +0 -31
  42. package/src/engine/WebRTCStats/InboundTrackStatsManager.ts +0 -51
  43. package/src/engine/WebRTCStats/OutboudTrackStatsManager.ts +0 -51
  44. package/src/engine/WebRTCStats/StatsHandler.ts +0 -80
  45. package/src/engine/WebRTCStats/TransportsStatsProvider.ts +0 -123
  46. package/src/engine/WebRTCStats/types.ts +0 -20
  47. package/src/engine/analyticsApiClient/LogApi.ts +0 -24
  48. package/src/engine/analyticsApiClient/MetricsApi.ts +0 -30
  49. package/src/engine/analyticsApiClient/helper.ts +0 -88
  50. package/src/engine/analyticsApiClient/index.ts +0 -42
  51. package/src/engine/analyticsApiClient/types.ts +0 -33
  52. package/src/engine/handlers/ChannelAudioObserverEventHandler.ts +0 -177
  53. package/src/engine/handlers/ChannelEventHandler.ts +0 -268
  54. package/src/engine/handlers/ChannelStateSyncEventHandler/ChannelStateConsistencyCheckResult.ts +0 -31
  55. package/src/engine/handlers/ChannelStateSyncEventHandler/ChannelStateConsistencyChecker.ts +0 -146
  56. package/src/engine/handlers/ChannelStateSyncEventHandler/consts.ts +0 -7
  57. package/src/engine/handlers/ChannelStateSyncEventHandler/index.ts +0 -342
  58. package/src/engine/handlers/ChannelStateSyncEventHandler/types.ts +0 -21
  59. package/src/engine/handlers/MediaEventHandler.ts +0 -273
  60. package/src/engine/index.ts +0 -793
  61. package/src/engine/media/index.ts +0 -574
  62. package/src/engine/media/producer/PendingClosureProducerStorage.ts +0 -37
  63. package/src/engine/media/producer/ProducerCloseManager.ts +0 -115
  64. package/src/engine/media/streamEffects/ProcessorsCache.ts +0 -41
  65. package/src/engine/media/streamEffects/audio/AudioTrackProcessor.ts +0 -7
  66. package/src/engine/media/streamEffects/audio/asdk/ASDKTrackProcessor.ts +0 -275
  67. package/src/engine/media/streamEffects/audio/asdk/atsrb.d.ts +0 -36
  68. package/src/engine/media/streamEffects/audio/asdk/errorBus.d.ts +0 -47
  69. package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionAudioWorkletNode.ts +0 -35
  70. package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionNodeProvider.ts +0 -44
  71. package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionScriptProcessorNode.ts +0 -69
  72. package/src/engine/media/streamEffects/audio/noiseSuppression/RNNoiseTrackProcessor.ts +0 -134
  73. package/src/engine/media/streamEffects/audio/noiseSuppression/WasmModuleCompiler.ts +0 -9
  74. package/src/engine/media/streamEffects/video/esdk/TrackProcessor.ts +0 -386
  75. package/src/engine/media/streamEffects/video/esdk/components/component.d.ts +0 -35
  76. package/src/engine/media/streamEffects/video/esdk/components/countdown/countdown.d.ts +0 -27
  77. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/doubleSlideRect.d.ts +0 -33
  78. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/horizontalMirror.d.ts +0 -29
  79. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/leftTextbox.d.ts +0 -31
  80. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/slideBold.d.ts +0 -41
  81. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/twoSideRects/animatedBox.d.ts +0 -59
  82. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/twoSideRects/twoSlideRects.d.ts +0 -27
  83. package/src/engine/media/streamEffects/video/esdk/components/lower-third/lowerThird.d.ts +0 -83
  84. package/src/engine/media/streamEffects/video/esdk/components/overlay-screen/overlayScreen.d.ts +0 -40
  85. package/src/engine/media/streamEffects/video/esdk/components/overlay-screen/overlaySprite.d.ts +0 -10
  86. package/src/engine/media/streamEffects/video/esdk/components/stickers/stickerSprite.d.ts +0 -51
  87. package/src/engine/media/streamEffects/video/esdk/components/stickers/stickers.d.ts +0 -54
  88. package/src/engine/media/streamEffects/video/esdk/components/utils/positionHelper.d.ts +0 -14
  89. package/src/engine/media/streamEffects/video/esdk/components/waterMark/waterMark.d.ts +0 -20
  90. package/src/engine/media/streamEffects/video/esdk/tsvb.d.ts +0 -187
  91. package/src/engine/media/streamEffects/video/esdk/utils/errorBus.d.ts +0 -42
  92. package/src/engine/media/tracks/DefaultAudioTrack.ts +0 -178
  93. package/src/engine/media/tracks/DefaultBaseTrack.ts +0 -592
  94. package/src/engine/media/tracks/DefaultVideoTrack.ts +0 -301
  95. package/src/engine/media/tracks/MediaStreamTrackManager.ts +0 -50
  96. package/src/engine/media/tracks/PeerTrack.ts +0 -558
  97. package/src/engine/network/DataChannelsManager.ts +0 -164
  98. package/src/engine/network/DatachannelHeartbeater.ts +0 -122
  99. package/src/engine/network/SignalingHeartbeater.ts +0 -55
  100. package/src/engine/network/index.ts +0 -961
  101. package/src/engine/signalingApiClient/SignalingApiClient.ts +0 -95
  102. package/src/engine/signalingApiClient/api.ts +0 -2289
  103. package/src/engine/system/index.ts +0 -221
  104. package/src/errors/AlreadyConnectedError.ts +0 -11
  105. package/src/errors/AlreadyCreatedError.ts +0 -11
  106. package/src/errors/ForbiddenError.ts +0 -11
  107. package/src/errors/InvalidPayloadError.ts +0 -11
  108. package/src/errors/InvalidRequestError.ts +0 -11
  109. package/src/errors/LivedigitalSDKError.ts +0 -15
  110. package/src/errors/NeedJoinFirstError.ts +0 -11
  111. package/src/errors/NotFoundError.ts +0 -11
  112. package/src/errors/OperationError.ts +0 -47
  113. package/src/errors/RequestError.ts +0 -11
  114. package/src/errors/TimeoutError.ts +0 -11
  115. package/src/errors/TooManyRequestsError.ts +0 -11
  116. package/src/errors/UnauthorizedError.ts +0 -11
  117. package/src/errors/UnsupportedError.ts +0 -15
  118. package/src/errors/signalingApiErrorMapper.ts +0 -143
  119. package/src/helpers/appDataValidator.ts +0 -21
  120. package/src/helpers/browser.ts +0 -37
  121. package/src/helpers/channelMessageConverter.ts +0 -124
  122. package/src/helpers/common.ts +0 -96
  123. package/src/helpers/datetime.ts +0 -11
  124. package/src/helpers/errors.ts +0 -25
  125. package/src/helpers/filterStatsCodecs.ts +0 -3
  126. package/src/helpers/loader.ts +0 -59
  127. package/src/helpers/media.ts +0 -57
  128. package/src/helpers/peer.ts +0 -19
  129. package/src/helpers/randomString.ts +0 -18
  130. package/src/helpers/retry.ts +0 -74
  131. package/src/index.ts +0 -171
  132. package/src/inversify.config.ts +0 -333
  133. package/src/inversify.factories.ts +0 -191
  134. package/src/inversify.tokens.ts +0 -42
  135. package/src/proto/.gitkeep +0 -0
  136. package/src/proto/generated/channel/channel_activity_confirmation_time.ts +0 -110
  137. package/src/proto/generated/channel/channel_management_event.ts +0 -213
  138. package/src/proto/generated/channel/channel_produce_permissions.ts +0 -171
  139. package/src/proto/generated/channel/channel_state.ts +0 -94
  140. package/src/proto/generated/channel/channel_state_short.ts +0 -282
  141. package/src/proto/generated/channel_message/channel_event.ts +0 -401
  142. package/src/proto/generated/channel_message/channel_message.ts +0 -139
  143. package/src/proto/generated/channel_message/media_event.ts +0 -290
  144. package/src/proto/generated/consumer/consumer.ts +0 -167
  145. package/src/proto/generated/google/protobuf/struct.ts +0 -588
  146. package/src/proto/generated/google/protobuf/timestamp.ts +0 -229
  147. package/src/proto/generated/peer/peer.ts +0 -430
  148. package/src/proto/generated/peer/peer_group.ts +0 -48
  149. package/src/proto/generated/peer/peer_role.ts +0 -48
  150. package/src/proto/generated/producer/producer.ts +0 -204
  151. package/src/proto/generated/producer/producer_kind.ts +0 -48
  152. package/src/proto/generated/producer/producer_label.ts +0 -78
  153. package/src/proto/generated/producer/producer_spatial_layer_request.ts +0 -116
  154. package/src/proto/generated/transport/transport_connection_timeout.ts +0 -156
  155. package/src/proto/generated/transport/transport_connection_timeout_reason.ts +0 -48
  156. package/src/proto/generated/transport/transport_direction.ts +0 -48
  157. package/src/types/channelAudioObserver.ts +0 -34
  158. package/src/types/channelStateSyncronizer.ts +0 -22
  159. package/src/types/client.ts +0 -27
  160. package/src/types/common.ts +0 -399
  161. package/src/types/container.ts +0 -31
  162. package/src/types/engine.ts +0 -97
  163. package/src/types/media.ts +0 -146
  164. package/src/types/mediasoup.ts +0 -10
  165. package/src/types/network.ts +0 -10
  166. package/src/types/streamEffects.ts +0 -23
@@ -1,42 +0,0 @@
1
- import axios, { AxiosInstance } from 'axios';
2
- import qs from 'qs';
3
- import { injectable } from 'inversify';
4
- import { receiveClientTrackingId } from './helper';
5
- import LogApi from './LogApi';
6
- import MetricsApi from './MetricsApi';
7
-
8
- @injectable()
9
- export default class AnalyticsApiClient {
10
- private readonly api: AxiosInstance;
11
-
12
- private readonly logApi: LogApi;
13
-
14
- private readonly metricsApi: MetricsApi;
15
-
16
- constructor() {
17
- this.api = axios.create({
18
- baseURL: process.env.LIVEDIGITAL_APP_ANALYTICS_API_BASE_URL,
19
- timeout: 10_000,
20
- withCredentials: true,
21
- paramsSerializer: (params) => qs.stringify(params),
22
- headers: {
23
- 'x-cl-id': receiveClientTrackingId(),
24
- },
25
- });
26
-
27
- this.api.defaults.headers.common['Cache-Control'] = 'no-cache';
28
- this.api.defaults.headers.common.Pragma = 'no-cache';
29
- this.api.defaults.headers.common.Expires = '0';
30
-
31
- this.logApi = new LogApi(this.api);
32
- this.metricsApi = new MetricsApi(this.api);
33
- }
34
-
35
- get log(): LogApi {
36
- return this.logApi;
37
- }
38
-
39
- get metrics(): MetricsApi {
40
- return this.metricsApi;
41
- }
42
- }
@@ -1,33 +0,0 @@
1
- import type { ClientMetaPayload } from '../../ClientMetaProvider';
2
- import type { LogToRemotePayload } from '../Logger';
3
-
4
- export interface BatchLogPayload {
5
- logs: LogToRemotePayload[];
6
- clientMeta: Record<string, unknown>;
7
- }
8
-
9
- export interface NetworkMetric {
10
- jitter: number;
11
- rtt: number;
12
- packetLoss: number;
13
- mos: number;
14
- streams: number;
15
- node: string;
16
- direction: 'inbound' | 'outbound';
17
- timestamp: string;
18
- bitrate: number;
19
- }
20
-
21
- export interface NetworkMetricsBatch {
22
- metrics: NetworkMetric[];
23
- clientMeta: ClientMetaPayload & {
24
- clientUniqueId: string;
25
- };
26
- }
27
-
28
- export interface WIDMetricsBatch {
29
- reasons: string[];
30
- clientMeta: ClientMetaPayload & {
31
- clientUniqueId: string;
32
- };
33
- }
@@ -1,177 +0,0 @@
1
- import { inject, injectable } from 'inversify';
2
- import { serializeError } from 'serialize-error';
3
- import { CLIENT_EVENTS } from '../../constants/events';
4
- import EnhancedEventEmitter from '../../EnhancedEventEmitter';
5
- import InvalidPayloadError from '../../errors/InvalidPayloadError';
6
- import { TOKEN } from '../../inversify.tokens';
7
- import {
8
- AudioObserverEvents,
9
- ChannelAudioObserverEvents,
10
- DominantSpeakerEvent,
11
- PeersVolumesEvent,
12
- } from '../../types/channelAudioObserver';
13
- import { TrackLabel } from '../../types/common';
14
- import Logger from '../Logger';
15
- import Peer from '../Peer';
16
- import PeersStorage from '../PeersStorage';
17
-
18
- @injectable()
19
- class ChannelAudioObserverEventHandler {
20
- readonly #logger: Logger;
21
-
22
- #activePeerId?: Peer['id'];
23
-
24
- #currentActiveSpeaker?: Peer;
25
-
26
- #prevActiveSpeaker?: Peer;
27
-
28
- constructor(
29
- @inject(TOKEN.PeersStorage) private readonly peersStorage: PeersStorage,
30
- @inject(TOKEN.ClientEventEmitter) private readonly clientEventEmitter: EnhancedEventEmitter,
31
- @inject(TOKEN.LoggerFactory) loggerFactory: (namespace: string) => Logger,
32
- ) {
33
- this.#logger = loggerFactory('ChannelAudioObserverEventHandler');
34
-
35
- this.watchPeersLeave();
36
- }
37
-
38
- public handle(data: string): void {
39
- try {
40
- const payload: AudioObserverEvents = JSON.parse(data);
41
- ChannelAudioObserverEventHandler.validateEventPayload(payload);
42
-
43
- switch (payload.event) {
44
- case ChannelAudioObserverEvents.DominantSpeaker: {
45
- this.handleDominantSpeaker(payload);
46
- break;
47
- }
48
-
49
- case ChannelAudioObserverEvents.PeersVolumes: {
50
- this.handlePeerVolumes(payload);
51
- break;
52
- }
53
-
54
- case ChannelAudioObserverEvents.Silence: {
55
- this.handleSilence();
56
- break;
57
- }
58
- default:
59
- break;
60
- }
61
- } catch (error) {
62
- this.#logger.warn('Failed to handle audio observer event', {
63
- error: serializeError(error),
64
- eventData: data,
65
- });
66
- }
67
- }
68
-
69
- private handleDominantSpeaker(payload: DominantSpeakerEvent): void {
70
- const { peerId } = payload.data;
71
- const peer = this.peersStorage.get(peerId);
72
- this.#currentActiveSpeaker = peer;
73
- this.#prevActiveSpeaker = peer;
74
- this.setActiveSpeaker(peer);
75
- }
76
-
77
- private handlePeerVolumes(payload: PeersVolumesEvent): void {
78
- payload.volumes.forEach((item) => {
79
- const { peerId, trackLabel, value } = item;
80
- const peer = this.peersStorage.get(peerId);
81
-
82
- if (!peer) {
83
- return;
84
- }
85
-
86
- if (value > 0 && !this.#currentActiveSpeaker && peer.id === this.#prevActiveSpeaker?.id) {
87
- this.#currentActiveSpeaker = peer;
88
- this.setActiveSpeaker(peer);
89
- }
90
-
91
- const track = peer?.tracks.get(trackLabel);
92
-
93
- if (!track) {
94
- return;
95
- }
96
-
97
- track.setVolume(value);
98
- });
99
- }
100
-
101
- private handleSilence(): void {
102
- const tracks = this.peersStorage.all().flatMap((peer) => Array.from(peer.tracks.values()));
103
- tracks.forEach((track) => track.setVolume(0));
104
- this.#currentActiveSpeaker = undefined;
105
- this.setActiveSpeaker(undefined);
106
- }
107
-
108
- private watchPeersLeave(): void {
109
- this.clientEventEmitter.on(CLIENT_EVENTS.peerLeft, (peerId: Peer['id']): void => {
110
- if (peerId === this.#currentActiveSpeaker?.id) {
111
- this.setActiveSpeaker(undefined);
112
- }
113
- });
114
- }
115
-
116
- private setActiveSpeaker(peer?: Peer): void {
117
- if (this.#activePeerId === peer?.id) {
118
- return;
119
- }
120
-
121
- this.#activePeerId = peer?.id;
122
- this.clientEventEmitter.safeEmit(CLIENT_EVENTS.activeSpeakerChanged, { peer });
123
- }
124
-
125
- private static validateEventPayload(payload: AudioObserverEvents): void {
126
- switch (payload.event) {
127
- case ChannelAudioObserverEvents.Silence: {
128
- break;
129
- }
130
-
131
- case ChannelAudioObserverEvents.DominantSpeaker: {
132
- if (!payload.data) {
133
- ChannelAudioObserverEventHandler.throwInvalidPayload();
134
- }
135
-
136
- const { peerId, producerId, trackLabel } = payload.data;
137
-
138
- if (typeof peerId !== 'string' || typeof producerId !== 'string' || trackLabel !== TrackLabel.Microphone) {
139
- ChannelAudioObserverEventHandler.throwInvalidPayload();
140
- }
141
- break;
142
- }
143
-
144
- case ChannelAudioObserverEvents.PeersVolumes: {
145
- if (!Array.isArray(payload.volumes)) {
146
- ChannelAudioObserverEventHandler.throwInvalidPayload();
147
- }
148
-
149
- payload.volumes.forEach((item) => {
150
- const {
151
- peerId, producerId, value, trackLabel,
152
- } = item;
153
-
154
- if (
155
- typeof peerId !== 'string'
156
- || typeof producerId !== 'string'
157
- || typeof value !== 'number'
158
- || trackLabel !== TrackLabel.Microphone
159
- ) {
160
- ChannelAudioObserverEventHandler.throwInvalidPayload();
161
- }
162
- });
163
- break;
164
- }
165
-
166
- default: {
167
- ChannelAudioObserverEventHandler.throwInvalidPayload();
168
- }
169
- }
170
- }
171
-
172
- static throwInvalidPayload(): void {
173
- throw new InvalidPayloadError('invalid_channel_audio_observer_payload');
174
- }
175
- }
176
-
177
- export default ChannelAudioObserverEventHandler;
@@ -1,268 +0,0 @@
1
- import { inject, injectable } from 'inversify';
2
- import { CHANNEL_EVENTS, CLIENT_EVENTS } from '../../constants/events';
3
- import EnhancedEventEmitter from '../../EnhancedEventEmitter';
4
- import { logResponse } from '../../helpers/peer';
5
- import { TOKEN } from '../../inversify.tokens';
6
- import Logger from '../Logger';
7
- import { Peers } from '../Peers';
8
- import { serializeError } from 'serialize-error';
9
- import ChannelStateSyncEventHandler from './ChannelStateSyncEventHandler';
10
- import type { ChannelEvent } from '../../proto/generated/channel_message/channel_event';
11
- import { ChannelEventType } from '../../proto/generated/channel_message/channel_event';
12
- import ChannelStateSynchronizer from '../ChannelStateSynchronizer/ChannelStateSynchronizer';
13
- import {
14
- convertChannelMessagePeerToPeerResponse,
15
- convertChannelMessagePeerGroupsToPeerGroups,
16
- convertPeerGroupsToChannelMessagePeerGroups,
17
- convertChannelMessageProducerLabelsToTrackLabels,
18
- } from '../../helpers/channelMessageConverter';
19
- import { ActivityConfirmationRequiredPayload } from '../../types/common';
20
-
21
- @injectable()
22
- class ChannelEventHandler {
23
- readonly #logger: Logger;
24
-
25
- constructor(
26
- @inject(TOKEN.Peers) private readonly peers: Peers,
27
- @inject(TOKEN.ClientEventEmitter) private readonly clientEventEmitter: EnhancedEventEmitter,
28
- @inject(TOKEN.LoggerFactory) loggerFactory: (namespace: string) => Logger,
29
- @inject(TOKEN.ChannelStateSyncEventHandler)
30
- private readonly channelStateSyncEventHandler: ChannelStateSyncEventHandler,
31
- @inject(TOKEN.ChannelStateSynchronizer) private readonly channelStateSynchronizer: ChannelStateSynchronizer,
32
- ) {
33
- this.#logger = loggerFactory('ChannelEvents');
34
- }
35
-
36
- public async handleChannelEvent(event: ChannelEvent): Promise<void> {
37
- switch (event.eventType) {
38
- case ChannelEventType.CHANNEL_EVENT_TYPE_CHANNEL_STATE:
39
- await this.handleChannelState(event);
40
- break;
41
-
42
- case ChannelEventType.CHANNEL_EVENT_TYPE_CHANNEL_STATE_SHORT:
43
- this.handleChannelStateShort(event);
44
- break;
45
-
46
- case ChannelEventType.CHANNEL_EVENT_TYPE_CHANNEL_MANAGEMENT_EVENT:
47
- this.handleChannelManagementEvent(event);
48
- break;
49
-
50
- case ChannelEventType.CHANNEL_EVENT_TYPE_PEER_JOINED:
51
- this.handlePeerJoined(event);
52
- break;
53
-
54
- case ChannelEventType.CHANNEL_EVENT_TYPE_PEER_LEFT:
55
- this.handlePeerLeft(event);
56
- break;
57
-
58
- case ChannelEventType.CHANNEL_EVENT_TYPE_PEER_APP_DATA_CHANGED:
59
- this.handlePeerAppDataChanged(event);
60
- break;
61
-
62
- case ChannelEventType.CHANNEL_EVENT_TYPE_PEER_GROUP_CHANGED:
63
- this.handlePeerGroupsChanged(event);
64
- break;
65
-
66
- case ChannelEventType.CHANNEL_EVENT_TYPE_CHANNEL_ACTIVITY_CONFIRMATION_ACQUIRED:
67
- this.handleChannelActivityConfirmationAcquired();
68
- break;
69
-
70
- case ChannelEventType.CHANNEL_EVENT_TYPE_CHANNEL_ACTIVITY_CONFIRMATION_EXPIRED:
71
- this.handleChannelActivityConfirmationExpired();
72
- break;
73
-
74
- case ChannelEventType.CHANNEL_EVENT_TYPE_CHANNEL_ACTIVITY_CONFIRMATION_REQUIRED:
75
- this.handleChannelActivityConfirmationRequired(event);
76
- break;
77
-
78
- case ChannelEventType.CHANNEL_EVENT_TYPE_CHANNEL_PRODUCE_PERMISSIONS_CHANGED:
79
- this.handleChannelProducePermissionsChanged(event);
80
- break;
81
-
82
- case ChannelEventType.CHANNEL_EVENT_TYPE_PEER_PRODUCE_PERMISSIONS_CHANGED:
83
- this.handlePeerProducePermissionsChanged(event);
84
- break;
85
-
86
- case ChannelEventType.CHANNEL_EVENT_TYPE_CHANNEL_PRODUCE_PERMISSIONS_DELETED:
87
- this.handleChannelProducePermissionsDeleted(event);
88
- break;
89
-
90
- default:
91
- throw new Error(`Unsupported event type: ${ event.eventType }`);
92
- }
93
- }
94
-
95
- private handleChannelManagementEvent(event: ChannelEvent): void {
96
- if (!event.channelManagementEvent) {
97
- throw new Error('Missing channelManagementEvent in CHANNEL_MANAGEMENT_EVENT');
98
- }
99
-
100
- const channelManagementEvent = event.channelManagementEvent.event;
101
- this.clientEventEmitter.safeEmit(CLIENT_EVENTS.channelEvent, channelManagementEvent);
102
- this.#logger.debug('New channel event', { event: channelManagementEvent });
103
- }
104
-
105
- private handlePeerJoined(event: ChannelEvent): void {
106
- if (!event.peer) {
107
- throw new Error('Missing peer in PEER_APP_DATA_CHANGED event');
108
- }
109
-
110
- const peer = this.peers.add(convertChannelMessagePeerToPeerResponse(event.peer));
111
- this.#logger.debug('Peer joined to the channel', { peer: logResponse(peer) });
112
- }
113
-
114
- private handlePeerLeft(event: ChannelEvent): void {
115
- if (!event.peer) {
116
- throw new Error('Missing peer in PEER_LEFT event');
117
- }
118
-
119
- this.peers.remove(event.peer.id).catch((error: unknown) => {
120
- this.#logger.debug('Failed to remove peer', {
121
- error: serializeError(error),
122
- });
123
- });
124
-
125
- this.#logger.debug('Peer left the channel', { peerId: event.peer.id });
126
- }
127
-
128
- private async handleChannelState(event: ChannelEvent): Promise<void> {
129
- if (!event.channelState) {
130
- throw new Error('Missing channelState in CHANNEL_STATE event');
131
- }
132
-
133
- try {
134
- await this.channelStateSynchronizer.handleChannelStateEvent(event.channelState);
135
- } catch (error) {
136
- this.#logger.error('Failed to restore channel state', {
137
- case: 'restoreLocalState',
138
- error: serializeError(error),
139
- });
140
- }
141
- }
142
-
143
- private handleChannelStateShort(event: ChannelEvent): void {
144
- if (!event.channelStateShort) {
145
- throw new Error('Missing channelStateShort in CHANNEL_STATE_SHORT event');
146
- }
147
-
148
- this.channelStateSyncEventHandler.handleChannelStateShort(event.channelStateShort).catch((error: unknown) => {
149
- this.#logger.error('Failed to handle channel state short event', { error: serializeError(error) });
150
- });
151
- }
152
-
153
- private handlePeerAppDataChanged(event: ChannelEvent): void {
154
- if (!event.peer) {
155
- throw new Error('Missing peer in PEER_APP_DATA_CHANGED event');
156
- }
157
-
158
- const peer = this.peers.get(event.peer.id);
159
-
160
- if (peer) {
161
- peer.observer.emit(CHANNEL_EVENTS.updatePeerAppData, event.peer.appData);
162
- }
163
- }
164
-
165
- private handlePeerGroupsChanged(event: ChannelEvent): void {
166
- if (!event.peer) {
167
- throw new Error('Missing peer in PEER_GROUP_CHANGED event');
168
- }
169
-
170
- const peer = this.peers.get(event.peer.id);
171
- peer?.handleGroupsChange(event.peer.groups.map(convertChannelMessagePeerGroupsToPeerGroups));
172
- }
173
-
174
- private handleChannelActivityConfirmationExpired(): void {
175
- this.clientEventEmitter.safeEmit(CLIENT_EVENTS.activityConfirmationExpired);
176
- this.#logger.info('Notify the channel that it has disconnected due to the activity confirmation expiring', {});
177
- }
178
-
179
- private handleChannelActivityConfirmationAcquired(): void {
180
- this.clientEventEmitter.safeEmit(CLIENT_EVENTS.activityConfirmationAcquired);
181
- this.#logger.info('Notify the channel that the activity has been acquired.', {});
182
- }
183
-
184
- private handleChannelActivityConfirmationRequired(event: ChannelEvent): void {
185
- if (!event.channelActivityConfirmationTime) {
186
- throw new Error('Missing channelActivityConfirmationTime in CHANNEL_ACTIVITY_CONFIRMATION_REQUIRED event');
187
- }
188
-
189
- const eventPayload = event.channelActivityConfirmationTime as ActivityConfirmationRequiredPayload;
190
- this.clientEventEmitter.safeEmit(CLIENT_EVENTS.activityConfirmationRequired, eventPayload);
191
- this.#logger.info('Notify the channel that activity confirmation is required', {
192
- event: event.channelActivityConfirmationTime,
193
- });
194
- }
195
-
196
- private handleChannelProducePermissionsChanged(event: ChannelEvent): void {
197
- if (!event.channelProducePermissions) {
198
- throw new Error('Missing channelProducePermissions in CHANNEL_PRODUCE_PERMISSIONS_CHANGED event');
199
- }
200
-
201
- const { groups } = event.channelProducePermissions;
202
- const peers = this.peers.all().filter((peer) => peer
203
- .groups
204
- .some((group) => groups.includes(convertPeerGroupsToChannelMessagePeerGroups(group))));
205
-
206
- const producePermissions = event
207
- .channelProducePermissions
208
- .producePermissions.map(convertChannelMessageProducerLabelsToTrackLabels);
209
-
210
- const changedProducePermissions = event
211
- .channelProducePermissions
212
- .changedProducePermissions.map(convertChannelMessageProducerLabelsToTrackLabels);
213
-
214
- peers.forEach((peer) => {
215
- const newProducePermissions = Array.from(new Set([...peer.producePermissions, ...changedProducePermissions]))
216
- .filter((label) => {
217
- return (changedProducePermissions.includes(label) ? producePermissions.includes(label) : true);
218
- });
219
-
220
- peer.handleProducePermissionsChange(newProducePermissions);
221
- });
222
-
223
- this.#logger.info('Peers changed produce permissions', { groups, producePermissions });
224
- }
225
-
226
- private handlePeerProducePermissionsChanged(event: ChannelEvent): void {
227
- if (!event.peer) {
228
- throw new Error('Missing peer in PEER_PRODUCE_PERMISSIONS_CHANGED event');
229
- }
230
-
231
- const peer = this.peers.get(event.peer.id);
232
-
233
- if (!peer) {
234
- return;
235
- }
236
-
237
- const producePermissions = event.peer.producePermissions.map(convertChannelMessageProducerLabelsToTrackLabels);
238
- peer.handleProducePermissionsChange(producePermissions);
239
- }
240
-
241
- private handleChannelProducePermissionsDeleted(event: ChannelEvent): void {
242
- if (!event.channelProducePermissions) {
243
- throw new Error('Missing channelProducePermissions in CHANNEL_PRODUCE_PERMISSIONS_DELETED event');
244
- }
245
-
246
- const { groups } = event.channelProducePermissions;
247
- const peers = this.peers.all().filter((peer) => peer
248
- .groups
249
- .some((group) => groups.includes(convertPeerGroupsToChannelMessagePeerGroups(group))));
250
-
251
- const producePermissions = event
252
- .channelProducePermissions
253
- .producePermissions
254
- .map(convertChannelMessageProducerLabelsToTrackLabels);
255
-
256
- peers.forEach((peer) => {
257
- const newProducePermissions = peer
258
- .producePermissions
259
- .filter((permission) => !producePermissions.includes(permission));
260
-
261
- peer.handleProducePermissionsChange(newProducePermissions);
262
- });
263
-
264
- this.#logger.info('Peers deleted produce permissions', { groups, producePermissions });
265
- }
266
- }
267
-
268
- export default ChannelEventHandler;
@@ -1,31 +0,0 @@
1
- import type { ChannelStateConsistencyCheckResultsParams } from './types';
2
-
3
- class ChannelStateConsistencyCheckResult {
4
- readonly missingPeers: string[];
5
-
6
- readonly missingProducers: string[];
7
-
8
- readonly consumersWithInconsistentState: string[];
9
-
10
- readonly producersWithInconsistentState: string[];
11
-
12
- readonly peersWithInconsistentAppData: string[];
13
-
14
- constructor(params: ChannelStateConsistencyCheckResultsParams) {
15
- this.missingPeers = params.missingPeers;
16
- this.missingProducers = params.missingProducers;
17
- this.consumersWithInconsistentState = params.consumersWithInconsistentState;
18
- this.producersWithInconsistentState = params.producersWithInconsistentState;
19
- this.peersWithInconsistentAppData = params.peersWithInconsistentAppData;
20
- }
21
-
22
- hasInconsistencyCases(): boolean {
23
- return this.missingPeers.length > 0
24
- || this.missingProducers.length > 0
25
- || this.consumersWithInconsistentState.length > 0
26
- || this.producersWithInconsistentState.length > 0
27
- || this.peersWithInconsistentAppData.length > 0;
28
- }
29
- }
30
-
31
- export default ChannelStateConsistencyCheckResult;
@@ -1,146 +0,0 @@
1
- import { FIVE_SECONDS_IN_MS } from '../../../constants/common';
2
- import type {
3
- ChannelStateShort,
4
- } from '../../../proto/generated/channel/channel_state_short';
5
- import type {
6
- LocalChannelState,
7
- LocalChannelStatePeer,
8
- LocalChannelStatePeerConsumer,
9
- LocalChannelStatePeerProducer,
10
- } from '../../../types/channelStateSyncronizer';
11
- import ChannelStateConsistencyCheckResult from './ChannelStateConsistencyCheckResult';
12
-
13
- interface ChannelStateConsistencyCheckerParams {
14
- localState: LocalChannelState;
15
- remoteState: ChannelStateShort;
16
- }
17
-
18
- class ChannelStateConsistencyChecker {
19
- private readonly localState: LocalChannelState;
20
-
21
- private readonly remoteState: ChannelStateShort;
22
-
23
- private missingPeers: string[] = [];
24
-
25
- private missingProducers: string[] = [];
26
-
27
- private consumersWithInconsistentState: string[] = [];
28
-
29
- private producersWithInconsistentState: string[] = [];
30
-
31
- private peersWithInconsistentAppData: string[] = [];
32
-
33
- constructor(params: ChannelStateConsistencyCheckerParams) {
34
- this.localState = params.localState;
35
- this.remoteState = params.remoteState;
36
- }
37
-
38
- check(): ChannelStateConsistencyCheckResult {
39
- this.resetPreviousCheckResults();
40
- this.remoteState.peers.forEach((remotePeer) => {
41
- const localPeer = this.findLocalPeerById(remotePeer.id);
42
-
43
- if (!localPeer) {
44
- this.missingPeers.push(remotePeer.id);
45
-
46
- return;
47
- }
48
-
49
- const isDifferentAppData = localPeer.appDataHash !== remotePeer.appDataHash;
50
-
51
- if (isDifferentAppData) {
52
- this.peersWithInconsistentAppData.push(remotePeer.id);
53
- }
54
-
55
- remotePeer.producers.forEach((remoteProducer) => {
56
- const localProducer = this.findLocalProducerById(localPeer, remoteProducer.id);
57
-
58
- if (!localProducer) {
59
- this.missingProducers.push(remoteProducer.id);
60
-
61
- return;
62
- }
63
-
64
- if (this.isLocalProducerStateChangedRecently(localProducer)) {
65
- return;
66
- }
67
-
68
- const isInconsistentState = localProducer.paused !== remoteProducer.paused;
69
-
70
- if (isInconsistentState) {
71
- this.producersWithInconsistentState.push(remoteProducer.id);
72
-
73
- // don't check consumer state while producer state is inconsistent
74
- return;
75
- }
76
-
77
- const localConsumer = this.findLocalConsumerByProducerId(localPeer, remoteProducer.id);
78
-
79
- if (localConsumer && localConsumer.paused !== remoteProducer.paused) {
80
- this.consumersWithInconsistentState.push(localConsumer.id);
81
- }
82
-
83
- if (!localProducer) {
84
- this.missingProducers.push(remoteProducer.id);
85
- }
86
- });
87
- });
88
-
89
- return new ChannelStateConsistencyCheckResult({
90
- missingPeers: this.missingPeers,
91
- missingProducers: this.missingProducers,
92
- consumersWithInconsistentState: this.consumersWithInconsistentState,
93
- producersWithInconsistentState: this.producersWithInconsistentState,
94
- peersWithInconsistentAppData: this.peersWithInconsistentAppData,
95
- });
96
- }
97
-
98
- getMissingPeers(): string[] {
99
- return this.missingPeers;
100
- }
101
-
102
- getMissingProducers(): string[] {
103
- return this.missingProducers;
104
- }
105
-
106
- getConsumersWithInconsistentState(): string[] {
107
- return this.consumersWithInconsistentState;
108
- }
109
-
110
- getProducersWithInconsistentState(): string[] {
111
- return this.producersWithInconsistentState;
112
- }
113
-
114
- getPeersWithInconsistentAppData(): string[] {
115
- return this.peersWithInconsistentAppData;
116
- }
117
-
118
- private findLocalPeerById(id: string): LocalChannelStatePeer | undefined {
119
- return this.localState.peers.find((item) => item.id === id);
120
- }
121
-
122
- private findLocalConsumerByProducerId(
123
- peer: LocalChannelStatePeer,
124
- producerId: string,
125
- ): LocalChannelStatePeerConsumer | undefined {
126
- return peer.consumers?.find((item) => item.producerId === producerId);
127
- }
128
-
129
- private findLocalProducerById(peer: LocalChannelStatePeer, id: string): LocalChannelStatePeerProducer | undefined {
130
- return peer.producers.find((item) => item.id === id);
131
- }
132
-
133
- private resetPreviousCheckResults(): void {
134
- this.missingPeers = [];
135
- this.missingProducers = [];
136
- this.consumersWithInconsistentState = [];
137
- this.producersWithInconsistentState = [];
138
- this.peersWithInconsistentAppData = [];
139
- }
140
-
141
- private isLocalProducerStateChangedRecently(producer: LocalChannelStatePeerProducer): boolean {
142
- return Date.now() - producer.stateChangedAt < FIVE_SECONDS_IN_MS;
143
- }
144
- }
145
-
146
- export default ChannelStateConsistencyChecker;