@eleven-am/pondsocket 0.1.182 → 0.1.184
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.
- package/abstracts/redisClient.js +18 -14
- package/managers/distributedManager.js +64 -3
- package/package.json +1 -1
package/abstracts/redisClient.js
CHANGED
|
@@ -33,7 +33,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
33
33
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
34
34
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
35
35
|
};
|
|
36
|
-
var _RedisClient_instances, _RedisClient_heartbeatInterval, _RedisClient_cleanupInterval, _RedisClient_instanceTtl, _RedisClient_redisClient, _RedisClient_pubClient, _RedisClient_subClient, _RedisClient_instanceId, _RedisClient_assignsPublisher, _RedisClient_presencePublisher, _RedisClient_userLeavesPublisher, _RedisClient_channelMessagePublisher, _RedisClient_stateSyncPublisher, _RedisClient_heartbeatTimer, _RedisClient_cleanupTimer, _RedisClient_presence_changes_channel_get, _RedisClient_assigns_changes_channel_get, _RedisClient_channel_messages_channel_get, _RedisClient_user_leaves_channel_get,
|
|
36
|
+
var _RedisClient_instances, _RedisClient_heartbeatInterval, _RedisClient_cleanupInterval, _RedisClient_instanceTtl, _RedisClient_redisClient, _RedisClient_pubClient, _RedisClient_subClient, _RedisClient_instanceId, _RedisClient_assignsPublisher, _RedisClient_presencePublisher, _RedisClient_userLeavesPublisher, _RedisClient_channelMessagePublisher, _RedisClient_stateSyncPublisher, _RedisClient_heartbeatTimer, _RedisClient_cleanupTimer, _RedisClient_presence_changes_channel_get, _RedisClient_assigns_changes_channel_get, _RedisClient_channel_messages_channel_get, _RedisClient_user_leaves_channel_get, _RedisClient_handleErrors, _RedisClient_getPresenceCacheChannel, _RedisClient_getAssignsCacheChannel, _RedisClient_publishPresenceChange, _RedisClient_publishAssignsChange, _RedisClient_publishChannelMessage, _RedisClient_publishUserLeave, _RedisClient_registerInstance, _RedisClient_unregisterInstance, _RedisClient_unsubscribeFromChannels, _RedisClient_subscribeToChannels, _RedisClient_startHeartbeat, _RedisClient_startPeriodicCleanup, _RedisClient_performConsistencyCheck, _RedisClient_handleRedisMessage, _RedisClient_publishCacheMessage, _RedisClient_emitStateSyncEvent, _RedisClient_subscribeToCacheChanges, _RedisClient_subscribeToChannelMessages, _RedisClient_subscribeToUserLeaves, _RedisClient_subscribeToStateSync, _RedisClient_handleExit, _RedisClient_deleteKeysByPattern;
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
38
|
exports.RedisClient = void 0;
|
|
39
39
|
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
@@ -97,11 +97,12 @@ class RedisClient {
|
|
|
97
97
|
}
|
|
98
98
|
shutdown() {
|
|
99
99
|
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
const batchSize = 1000;
|
|
100
101
|
clearInterval(__classPrivateFieldGet(this, _RedisClient_heartbeatTimer, "f"));
|
|
101
102
|
clearInterval(__classPrivateFieldGet(this, _RedisClient_cleanupTimer, "f"));
|
|
102
103
|
yield __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_unsubscribeFromChannels).call(this);
|
|
103
104
|
yield __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_unregisterInstance).call(this);
|
|
104
|
-
yield __classPrivateFieldGet(this, _RedisClient_instances, "m",
|
|
105
|
+
yield __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_deleteKeysByPattern).call(this, `*_cache:${__classPrivateFieldGet(this, _RedisClient_instanceId, "f")}:*`, batchSize);
|
|
105
106
|
});
|
|
106
107
|
}
|
|
107
108
|
}
|
|
@@ -114,15 +115,6 @@ _RedisClient_heartbeatInterval = new WeakMap(), _RedisClient_cleanupInterval = n
|
|
|
114
115
|
return 'channel_messages';
|
|
115
116
|
}, _RedisClient_user_leaves_channel_get = function _RedisClient_user_leaves_channel_get() {
|
|
116
117
|
return 'user_leaves';
|
|
117
|
-
}, _RedisClient_cleanup = function _RedisClient_cleanup() {
|
|
118
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
119
|
-
const pipeline = __classPrivateFieldGet(this, _RedisClient_redisClient, "f").pipeline();
|
|
120
|
-
const presenceKeys = yield __classPrivateFieldGet(this, _RedisClient_redisClient, "f").keys('presence_cache:*');
|
|
121
|
-
presenceKeys.forEach((key) => pipeline.del(key));
|
|
122
|
-
const assignsKeys = yield __classPrivateFieldGet(this, _RedisClient_redisClient, "f").keys('assigns_cache:*');
|
|
123
|
-
assignsKeys.forEach((key) => pipeline.del(key));
|
|
124
|
-
yield pipeline.exec();
|
|
125
|
-
});
|
|
126
118
|
}, _RedisClient_handleErrors = function _RedisClient_handleErrors() {
|
|
127
119
|
__classPrivateFieldGet(this, _RedisClient_redisClient, "f").on('error', (err) => console.error('Redis client error:', err));
|
|
128
120
|
__classPrivateFieldGet(this, _RedisClient_pubClient, "f").on('error', (err) => console.error('Redis pub client error:', err));
|
|
@@ -312,8 +304,8 @@ _RedisClient_heartbeatInterval = new WeakMap(), _RedisClient_cleanupInterval = n
|
|
|
312
304
|
const state = message.state ? JSON.stringify(message.state) : '';
|
|
313
305
|
yield __classPrivateFieldGet(this, _RedisClient_redisClient, "f").eval(script, 2, cacheKey, key, messageData, message.userId, state);
|
|
314
306
|
});
|
|
315
|
-
}, _RedisClient_emitStateSyncEvent = function _RedisClient_emitStateSyncEvent(
|
|
316
|
-
return __awaiter(this,
|
|
307
|
+
}, _RedisClient_emitStateSyncEvent = function _RedisClient_emitStateSyncEvent(endpointId_1, channelId_1) {
|
|
308
|
+
return __awaiter(this, arguments, void 0, function* (endpointId, channelId, initialFetch = false) {
|
|
317
309
|
const script = `
|
|
318
310
|
local active_instances = redis.call('SMEMBERS', 'distributed_instances')
|
|
319
311
|
local presence_data = {}
|
|
@@ -341,6 +333,7 @@ _RedisClient_heartbeatInterval = new WeakMap(), _RedisClient_cleanupInterval = n
|
|
|
341
333
|
const event = {
|
|
342
334
|
endpointId,
|
|
343
335
|
channelId,
|
|
336
|
+
initialFetch,
|
|
344
337
|
presence: new Map(Object.entries(JSON.parse(presenceData))),
|
|
345
338
|
assigns: new Map(Object.entries(JSON.parse(assignsData))),
|
|
346
339
|
};
|
|
@@ -374,7 +367,7 @@ _RedisClient_heartbeatInterval = new WeakMap(), _RedisClient_cleanupInterval = n
|
|
|
374
367
|
return callback(data);
|
|
375
368
|
}
|
|
376
369
|
});
|
|
377
|
-
void __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_emitStateSyncEvent).call(this, endpoint, channel);
|
|
370
|
+
void __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_emitStateSyncEvent).call(this, endpoint, channel, true);
|
|
378
371
|
return () => {
|
|
379
372
|
clearInterval(interval);
|
|
380
373
|
subscription();
|
|
@@ -389,4 +382,15 @@ _RedisClient_heartbeatInterval = new WeakMap(), _RedisClient_cleanupInterval = n
|
|
|
389
382
|
process.exit(1);
|
|
390
383
|
}
|
|
391
384
|
});
|
|
385
|
+
}, _RedisClient_deleteKeysByPattern = function _RedisClient_deleteKeysByPattern(pattern, batchSize) {
|
|
386
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
387
|
+
let cursor = '0';
|
|
388
|
+
do {
|
|
389
|
+
const [newCursor, keys] = yield __classPrivateFieldGet(this, _RedisClient_redisClient, "f").scan(cursor, 'MATCH', pattern, 'COUNT', batchSize);
|
|
390
|
+
cursor = newCursor;
|
|
391
|
+
if (keys.length > 0) {
|
|
392
|
+
yield __classPrivateFieldGet(this, _RedisClient_redisClient, "f").del(...keys);
|
|
393
|
+
}
|
|
394
|
+
} while (cursor !== '0');
|
|
395
|
+
});
|
|
392
396
|
};
|
|
@@ -10,13 +10,15 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
10
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
12
|
};
|
|
13
|
-
var _DistributedManager_client, _DistributedManager_subscriptions;
|
|
13
|
+
var _DistributedManager_instances, _DistributedManager_client, _DistributedManager_subscriptions, _DistributedManager_parseAndUpdatePresence;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.DistributedManager = void 0;
|
|
16
|
+
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
16
17
|
const manager_1 = require("./manager");
|
|
17
18
|
class DistributedManager extends manager_1.Manager {
|
|
18
19
|
constructor(client) {
|
|
19
20
|
super(client.channelId);
|
|
21
|
+
_DistributedManager_instances.add(this);
|
|
20
22
|
_DistributedManager_client.set(this, void 0);
|
|
21
23
|
_DistributedManager_subscriptions.set(this, null);
|
|
22
24
|
__classPrivateFieldSet(this, _DistributedManager_client, client, "f");
|
|
@@ -84,7 +86,7 @@ class DistributedManager extends manager_1.Manager {
|
|
|
84
86
|
});
|
|
85
87
|
const stateSyncSubscription = __classPrivateFieldGet(this, _DistributedManager_client, "f").subscribeToStateSync((state) => {
|
|
86
88
|
this.assignsCache = new Map(state.assigns);
|
|
87
|
-
this.
|
|
89
|
+
__classPrivateFieldGet(this, _DistributedManager_instances, "m", _DistributedManager_parseAndUpdatePresence).call(this, new Map(state.presence), state.initialFetch);
|
|
88
90
|
});
|
|
89
91
|
__classPrivateFieldSet(this, _DistributedManager_subscriptions, () => {
|
|
90
92
|
leaveSubscription();
|
|
@@ -101,4 +103,63 @@ class DistributedManager extends manager_1.Manager {
|
|
|
101
103
|
}
|
|
102
104
|
}
|
|
103
105
|
exports.DistributedManager = DistributedManager;
|
|
104
|
-
_DistributedManager_client = new WeakMap(), _DistributedManager_subscriptions = new WeakMap()
|
|
106
|
+
_DistributedManager_client = new WeakMap(), _DistributedManager_subscriptions = new WeakMap(), _DistributedManager_instances = new WeakSet(), _DistributedManager_parseAndUpdatePresence = function _DistributedManager_parseAndUpdatePresence(newCache, initialFetch) {
|
|
107
|
+
if (initialFetch) {
|
|
108
|
+
this.presenceCache = newCache;
|
|
109
|
+
}
|
|
110
|
+
const newUsers = new Set(newCache.keys());
|
|
111
|
+
const oldUsers = new Set(this.presenceCache.keys());
|
|
112
|
+
const usersToAdd = new Set([...newUsers].filter((user) => !oldUsers.has(user)));
|
|
113
|
+
const usersToRemove = new Set([...oldUsers].filter((user) => !newUsers.has(user)));
|
|
114
|
+
const noChange = new Set([...newUsers].filter((user) => oldUsers.has(user)));
|
|
115
|
+
const usersToUpdate = new Set([...noChange]
|
|
116
|
+
.filter((user) => {
|
|
117
|
+
const oldData = this.presenceCache.get(user);
|
|
118
|
+
const newData = newCache.get(user);
|
|
119
|
+
return JSON.stringify(oldData) !== JSON.stringify(newData);
|
|
120
|
+
}));
|
|
121
|
+
const upSertInfo = [
|
|
122
|
+
...[...usersToAdd]
|
|
123
|
+
.map((user) => ({
|
|
124
|
+
userId: user,
|
|
125
|
+
state: newCache.get(user),
|
|
126
|
+
event: pondsocket_common_1.PresenceEventTypes.JOIN,
|
|
127
|
+
})),
|
|
128
|
+
...[...usersToUpdate]
|
|
129
|
+
.map((user) => ({
|
|
130
|
+
userId: user,
|
|
131
|
+
state: newCache.get(user),
|
|
132
|
+
event: pondsocket_common_1.PresenceEventTypes.UPDATE,
|
|
133
|
+
})),
|
|
134
|
+
];
|
|
135
|
+
const upsertMessages = upSertInfo.map(({ userId, state, event }) => {
|
|
136
|
+
this.presenceCache.set(userId, state);
|
|
137
|
+
return {
|
|
138
|
+
event,
|
|
139
|
+
requestId: (0, pondsocket_common_1.uuid)(),
|
|
140
|
+
recipients: Array.from(this.presenceCache.keys()),
|
|
141
|
+
channelName: this.channelId,
|
|
142
|
+
action: pondsocket_common_1.ServerActions.PRESENCE,
|
|
143
|
+
payload: {
|
|
144
|
+
changed: state,
|
|
145
|
+
presence: Array.from(this.presenceCache.values()),
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
const removeMessages = [...usersToRemove].map((user) => {
|
|
150
|
+
const current = this.presenceCache.get(user);
|
|
151
|
+
this.presenceCache.delete(user);
|
|
152
|
+
return {
|
|
153
|
+
event: pondsocket_common_1.PresenceEventTypes.LEAVE,
|
|
154
|
+
requestId: (0, pondsocket_common_1.uuid)(),
|
|
155
|
+
recipients: Array.from(this.presenceCache.keys()),
|
|
156
|
+
channelName: this.channelId,
|
|
157
|
+
action: pondsocket_common_1.ServerActions.PRESENCE,
|
|
158
|
+
payload: {
|
|
159
|
+
changed: current,
|
|
160
|
+
presence: Array.from(this.presenceCache.values()),
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
[...upsertMessages, ...removeMessages].forEach((message) => this.broadcast(message));
|
|
165
|
+
};
|