@mulingai-npm/redis 3.5.2 → 3.7.0
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/dist/enums/redis-database.d.ts +2 -1
- package/dist/enums/redis-database.js +1 -0
- package/dist/managers/mulingstream-listener-manager.d.ts +0 -4
- package/dist/managers/mulingstream-listener-manager.js +0 -4
- package/dist/managers/mulingstream-speaker-manager.d.ts +0 -4
- package/dist/managers/mulingstream-speaker-manager.js +1 -11
- package/dist/managers/page-content-manager.d.ts +23 -0
- package/dist/managers/page-content-manager.js +63 -0
- package/package.json +1 -1
|
@@ -6,4 +6,5 @@ var RedisDatabase;
|
|
|
6
6
|
RedisDatabase[RedisDatabase["MULINGSTREAM_LISTENER"] = 0] = "MULINGSTREAM_LISTENER";
|
|
7
7
|
RedisDatabase[RedisDatabase["MULINGSTREAM_CHUNK"] = 1] = "MULINGSTREAM_CHUNK";
|
|
8
8
|
RedisDatabase[RedisDatabase["MULINGSTREAM_SPEAKER"] = 2] = "MULINGSTREAM_SPEAKER";
|
|
9
|
+
RedisDatabase[RedisDatabase["CONTENT_DATA"] = 3] = "CONTENT_DATA";
|
|
9
10
|
})(RedisDatabase = exports.RedisDatabase || (exports.RedisDatabase = {}));
|
|
@@ -21,9 +21,5 @@ export declare class MulingstreamListenerManager {
|
|
|
21
21
|
updateNameLanguage(listenerIdOrToken: string, name: string, language: string): Promise<boolean>;
|
|
22
22
|
updateSocketId(listenerIdOrToken: string, socketId: string): Promise<boolean>;
|
|
23
23
|
getTargetSocketIdsByRoomLanguage(roomId: string, language: string): Promise<string[]>;
|
|
24
|
-
/**
|
|
25
|
-
* Returns an array of unique languages for the given room, from highest frequency to lowest.
|
|
26
|
-
* If a listener has no language (empty string / undefined), it is ignored.
|
|
27
|
-
*/
|
|
28
24
|
getUniqueLanguagesByRoom(roomId: string): Promise<string[]>;
|
|
29
25
|
}
|
|
@@ -139,10 +139,6 @@ class MulingstreamListenerManager {
|
|
|
139
139
|
});
|
|
140
140
|
return filteredListeners.map((listener) => listener.socketId);
|
|
141
141
|
}
|
|
142
|
-
/**
|
|
143
|
-
* Returns an array of unique languages for the given room, from highest frequency to lowest.
|
|
144
|
-
* If a listener has no language (empty string / undefined), it is ignored.
|
|
145
|
-
*/
|
|
146
142
|
async getUniqueLanguagesByRoom(roomId) {
|
|
147
143
|
// 1) Fetch all listeners for the room.
|
|
148
144
|
// (This includes inactive ones, but feel free to filter out isActive === false if you only want active ones.)
|
|
@@ -15,11 +15,7 @@ export declare class MulingstreamSpeakerManager {
|
|
|
15
15
|
private redisClient;
|
|
16
16
|
constructor(redisClient: RedisClient);
|
|
17
17
|
private buildLockKey;
|
|
18
|
-
/** Try to claim the speaker slot for this room.
|
|
19
|
-
* @returns true when the lock was acquired, false if someone else holds it.
|
|
20
|
-
*/
|
|
21
18
|
acquireRoomLock(roomId: string, socketId: string, ttl?: number): Promise<boolean>;
|
|
22
|
-
/** Release the lock if we still own it. */
|
|
23
19
|
releaseRoomLock(roomId: string, socketId: string): Promise<void>;
|
|
24
20
|
private parseHash;
|
|
25
21
|
private serialize;
|
|
@@ -7,19 +7,12 @@ class MulingstreamSpeakerManager {
|
|
|
7
7
|
constructor(redisClient) {
|
|
8
8
|
this.redisClient = redisClient;
|
|
9
9
|
}
|
|
10
|
-
/* ------------------------------------------------------------------ */
|
|
11
|
-
/* One-speaker-per-room locking helpers */
|
|
12
|
-
/* ------------------------------------------------------------------ */
|
|
13
10
|
buildLockKey(roomId) {
|
|
14
11
|
return `room:${roomId}:speaker_lock`;
|
|
15
12
|
}
|
|
16
|
-
/** Try to claim the speaker slot for this room.
|
|
17
|
-
* @returns true when the lock was acquired, false if someone else holds it.
|
|
18
|
-
*/
|
|
19
13
|
async acquireRoomLock(roomId, socketId, ttl = LOCK_TTL) {
|
|
20
14
|
return this.redisClient.setNxEx(this.buildLockKey(roomId), socketId, ttl);
|
|
21
15
|
}
|
|
22
|
-
/** Release the lock if we still own it. */
|
|
23
16
|
async releaseRoomLock(roomId, socketId) {
|
|
24
17
|
const lockKey = this.buildLockKey(roomId);
|
|
25
18
|
const current = await this.redisClient.get(lockKey);
|
|
@@ -27,9 +20,6 @@ class MulingstreamSpeakerManager {
|
|
|
27
20
|
await this.redisClient.del(lockKey);
|
|
28
21
|
}
|
|
29
22
|
}
|
|
30
|
-
/* ------------------------------------------------------------------ */
|
|
31
|
-
/* Speaker CRUD + queries */
|
|
32
|
-
/* ------------------------------------------------------------------ */
|
|
33
23
|
parseHash(hash) {
|
|
34
24
|
return {
|
|
35
25
|
speakerId: hash.speakerId,
|
|
@@ -210,7 +200,7 @@ class MulingstreamSpeakerManager {
|
|
|
210
200
|
this.redisClient.srem(`room:${roomId}:speakers`, speakerId),
|
|
211
201
|
this.redisClient.srem(`user:${userId}:speakers`, speakerId),
|
|
212
202
|
this.redisClient.del(`socket:${socketId}:speaker`),
|
|
213
|
-
this.redisClient.del(this.buildLockKey(roomId))
|
|
203
|
+
this.redisClient.del(this.buildLockKey(roomId))
|
|
214
204
|
]);
|
|
215
205
|
}
|
|
216
206
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RedisClient } from '../redis-client';
|
|
2
|
+
export interface CachedPageContent {
|
|
3
|
+
id: string;
|
|
4
|
+
path: string;
|
|
5
|
+
locale: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
payload: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class PageContentManager {
|
|
10
|
+
private redis;
|
|
11
|
+
private static DEFAULT_TTL;
|
|
12
|
+
constructor(redis: RedisClient);
|
|
13
|
+
private key;
|
|
14
|
+
private build;
|
|
15
|
+
private scanAll;
|
|
16
|
+
addPageContent(locale: string, slug: string, payload: unknown, ttl?: number): Promise<void>;
|
|
17
|
+
getPageContent(locale: string, slug: string): Promise<CachedPageContent | null>;
|
|
18
|
+
getAllPageContents(): Promise<CachedPageContent[]>;
|
|
19
|
+
getAllPageContentsByLocale(locale: string): Promise<CachedPageContent[]>;
|
|
20
|
+
clearPageContent(locale: string, slug: string): Promise<void>;
|
|
21
|
+
clearAllPageContents(): Promise<void>;
|
|
22
|
+
clearAllPageContentsByLocale(locale: string): Promise<void>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PageContentManager = void 0;
|
|
4
|
+
class PageContentManager {
|
|
5
|
+
constructor(redis) {
|
|
6
|
+
this.redis = redis;
|
|
7
|
+
}
|
|
8
|
+
key(locale, slug) {
|
|
9
|
+
return `page-content--[${locale.toLowerCase()}]-[${slug.toLowerCase()}]`;
|
|
10
|
+
}
|
|
11
|
+
build(locale, slug, payload) {
|
|
12
|
+
const id = this.key(locale, slug);
|
|
13
|
+
return { id, path: `/${locale}/${slug}`, locale, slug, payload: JSON.stringify(payload) };
|
|
14
|
+
}
|
|
15
|
+
async scanAll() {
|
|
16
|
+
let cursor = '0';
|
|
17
|
+
const out = [];
|
|
18
|
+
do {
|
|
19
|
+
const [next, keys] = await this.redis.scan(Number(cursor), 'page-content--[*');
|
|
20
|
+
cursor = next;
|
|
21
|
+
out.push(...keys);
|
|
22
|
+
} while (cursor !== '0');
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
async addPageContent(locale, slug, payload, ttl = PageContentManager.DEFAULT_TTL) {
|
|
26
|
+
const obj = this.build(locale, slug, payload);
|
|
27
|
+
await this.redis.set(obj.id, JSON.stringify(obj));
|
|
28
|
+
await this.redis.expire(obj.id, ttl);
|
|
29
|
+
}
|
|
30
|
+
async getPageContent(locale, slug) {
|
|
31
|
+
const raw = await this.redis.get(this.key(locale, slug));
|
|
32
|
+
return raw ? JSON.parse(raw) : null;
|
|
33
|
+
}
|
|
34
|
+
async getAllPageContents() {
|
|
35
|
+
const keys = await this.scanAll();
|
|
36
|
+
if (!keys.length)
|
|
37
|
+
return [];
|
|
38
|
+
const p = this.redis.pipeline();
|
|
39
|
+
keys.forEach((k) => p.get(k));
|
|
40
|
+
const r = await p.exec();
|
|
41
|
+
return r.flatMap(([_, v]) => (v ? [JSON.parse(v)] : []));
|
|
42
|
+
}
|
|
43
|
+
async getAllPageContentsByLocale(locale) {
|
|
44
|
+
const all = await this.getAllPageContents();
|
|
45
|
+
return all.filter((c) => c.locale.toLowerCase() === locale.toLowerCase());
|
|
46
|
+
}
|
|
47
|
+
async clearPageContent(locale, slug) {
|
|
48
|
+
await this.redis.unlink(this.key(locale, slug));
|
|
49
|
+
}
|
|
50
|
+
async clearAllPageContents() {
|
|
51
|
+
const keys = await this.scanAll();
|
|
52
|
+
if (keys.length)
|
|
53
|
+
await this.redis.unlink(...keys);
|
|
54
|
+
}
|
|
55
|
+
async clearAllPageContentsByLocale(locale) {
|
|
56
|
+
const keys = await this.scanAll();
|
|
57
|
+
const toDel = keys.filter((k) => k.startsWith(`page-content--[${locale.toLowerCase()}]-[`));
|
|
58
|
+
if (toDel.length)
|
|
59
|
+
await this.redis.unlink(...toDel);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.PageContentManager = PageContentManager;
|
|
63
|
+
PageContentManager.DEFAULT_TTL = 24 * 60 * 60;
|