@lyxa.ai/core 1.3.76 → 1.3.80

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 (51) hide show
  1. package/dist/index.js +2 -2
  2. package/dist/index.js.map +1 -1
  3. package/dist/libraries/socket/PushNotificationEvent.d.ts +1 -1
  4. package/dist/libraries/socket/PushNotificationEvent.js.map +1 -1
  5. package/dist/libraries/socket/adapters/socket-subscription.d.ts +2 -0
  6. package/dist/libraries/socket/adapters/socket-subscription.js +4 -2
  7. package/dist/libraries/socket/adapters/socket-subscription.js.map +1 -1
  8. package/dist/libraries/socket/connections/batch.d.ts +12 -0
  9. package/dist/libraries/socket/connections/batch.js +58 -0
  10. package/dist/libraries/socket/connections/batch.js.map +1 -0
  11. package/dist/libraries/socket/connections/cache.d.ts +9 -0
  12. package/dist/libraries/socket/connections/cache.js +36 -0
  13. package/dist/libraries/socket/connections/cache.js.map +1 -0
  14. package/dist/libraries/socket/connections/constants.d.ts +2 -0
  15. package/dist/libraries/socket/connections/constants.js +6 -0
  16. package/dist/libraries/socket/connections/constants.js.map +1 -0
  17. package/dist/libraries/socket/connections/event-subscribers.d.ts +5 -0
  18. package/dist/libraries/socket/connections/event-subscribers.js +60 -0
  19. package/dist/libraries/socket/connections/event-subscribers.js.map +1 -0
  20. package/dist/libraries/socket/connections/index.d.ts +7 -0
  21. package/dist/libraries/socket/connections/index.js +24 -0
  22. package/dist/libraries/socket/connections/index.js.map +1 -0
  23. package/dist/libraries/socket/connections/instance-disconnect.d.ts +2 -0
  24. package/dist/libraries/socket/connections/instance-disconnect.js +43 -0
  25. package/dist/libraries/socket/connections/instance-disconnect.js.map +1 -0
  26. package/dist/libraries/socket/connections/keys.d.ts +10 -0
  27. package/dist/libraries/socket/connections/keys.js +23 -0
  28. package/dist/libraries/socket/connections/keys.js.map +1 -0
  29. package/dist/libraries/socket/connections/presence.d.ts +4 -0
  30. package/dist/libraries/socket/connections/presence.js +23 -0
  31. package/dist/libraries/socket/connections/presence.js.map +1 -0
  32. package/dist/libraries/socket/connections/redis-helpers.d.ts +2 -0
  33. package/dist/libraries/socket/connections/redis-helpers.js +14 -0
  34. package/dist/libraries/socket/connections/redis-helpers.js.map +1 -0
  35. package/dist/libraries/socket/connections/subscription.d.ts +13 -0
  36. package/dist/libraries/socket/connections/subscription.js +73 -0
  37. package/dist/libraries/socket/connections/subscription.js.map +1 -0
  38. package/dist/libraries/socket/core/index.d.ts +0 -1
  39. package/dist/libraries/socket/core/index.js +0 -1
  40. package/dist/libraries/socket/core/index.js.map +1 -1
  41. package/dist/libraries/socket/core/local-subscription-registry.d.ts +1 -1
  42. package/dist/libraries/socket/core/local-subscription-registry.js.map +1 -1
  43. package/dist/libraries/socket/core/socket-event-publisher.d.ts +1 -1
  44. package/dist/libraries/socket/core/socket-event-publisher.js +9 -15
  45. package/dist/libraries/socket/core/socket-event-publisher.js.map +1 -1
  46. package/dist/types/README.md +1 -1
  47. package/dist/types/package.json +1 -1
  48. package/package.json +1 -1
  49. package/dist/libraries/socket/core/socket-redis-connections.d.ts +0 -36
  50. package/dist/libraries/socket/core/socket-redis-connections.js +0 -412
  51. package/dist/libraries/socket/core/socket-redis-connections.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.js","sourceRoot":"/","sources":["libraries/socket/connections/presence.ts"],"names":[],"mappings":";;AAQA,sCAGC;AAKD,wCAGC;AAKD,wCAUC;AAlCD,gCAAwC;AAExC,iCAAyC;AAMlC,KAAK,UAAU,aAAa,CAAC,MAAc,EAAE,IAAoB,EAAE,YAAoB,IAAI,CAAC,GAAG,EAAE;IACvG,MAAM,KAAK,GAAG,IAAA,gBAAY,GAAE,CAAC,eAAe,EAAE,CAAC,WAAoB,CAAC;IACpE,MAAM,KAAK,CAAC,IAAI,CAAC,IAAA,sBAAe,EAAC,IAAI,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;AAC5D,CAAC;AAKM,KAAK,UAAU,cAAc,CAAC,MAAc,EAAE,IAAoB;IACxE,MAAM,KAAK,GAAG,IAAA,gBAAY,GAAE,CAAC,eAAe,EAAE,CAAC,WAAoB,CAAC;IACpE,MAAM,KAAK,CAAC,IAAI,CAAC,IAAA,sBAAe,EAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;AACjD,CAAC;AAKM,KAAK,UAAU,cAAc,CACnC,IAAoB,EACpB,OAAe,CAAC,EAChB,WAAmB,GAAG;IAEtB,MAAM,KAAK,GAAG,IAAA,gBAAY,GAAE,CAAC,eAAe,EAAE,CAAC,WAAoB,CAAC;IACpE,MAAM,OAAO,GAAG,IAAA,sBAAe,EAAC,IAAI,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;IACpC,MAAM,GAAG,GAAG,KAAK,GAAG,QAAQ,GAAG,CAAC,CAAC;IACjC,OAAO,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AAChD,CAAC","sourcesContent":["import { getLibraries } from '../../..';\nimport { AuthEntityType } from '../../auth';\nimport { kOnlineEntities } from './keys';\nimport type { Redis } from 'ioredis';\n\n/**\n * Add or update a user as online in the type-based ZSET.\n */\nexport async function setUserOnline(userId: string, type: AuthEntityType, timestamp: number = Date.now()) {\n\tconst redis = getLibraries().getRedisService().redisClient as Redis;\n\tawait redis.zadd(kOnlineEntities(type), timestamp, userId);\n}\n\n/**\n * Remove a user from the type-based online ZSET (on disconnect).\n */\nexport async function setUserOffline(userId: string, type: AuthEntityType) {\n\tconst redis = getLibraries().getRedisService().redisClient as Redis;\n\tawait redis.zrem(kOnlineEntities(type), userId);\n}\n\n/**\n * Paginate online users for a given entity type (deep pagination, scalable).\n */\nexport async function getOnlineUsers(\n\ttype: AuthEntityType,\n\tpage: number = 1,\n\tpageSize: number = 100\n): Promise<string[]> {\n\tconst redis = getLibraries().getRedisService().redisClient as Redis;\n\tconst zsetKey = kOnlineEntities(type);\n\tconst start = (page - 1) * pageSize;\n\tconst end = start + pageSize - 1;\n\treturn await redis.zrange(zsetKey, start, end);\n}\n/**\n * Example usage:\n *\n * import { getConnectedEntityByType } from './type-queries';\n *\n * // For entity type 'user', get page 2, 100 per page:\n * const users = await getConnectedEntityByType('user', 2, 100);\n */\n"]}
@@ -0,0 +1,2 @@
1
+ import type { Redis } from 'ioredis';
2
+ export declare function scanKeys(redis: Redis, pattern: string): Promise<string[]>;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scanKeys = scanKeys;
4
+ async function scanKeys(redis, pattern) {
5
+ const keys = [];
6
+ let cursor = '0';
7
+ do {
8
+ const [newCursor, foundKeys] = await redis.scan(cursor, 'MATCH', pattern, 'COUNT', 100);
9
+ cursor = newCursor;
10
+ keys.push(...foundKeys);
11
+ } while (cursor !== '0');
12
+ return keys;
13
+ }
14
+ //# sourceMappingURL=redis-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-helpers.js","sourceRoot":"/","sources":["libraries/socket/connections/redis-helpers.ts"],"names":[],"mappings":";;AAGA,4BASC;AATM,KAAK,UAAU,QAAQ,CAAC,KAAY,EAAE,OAAe;IAC3D,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,MAAM,GAAG,GAAG,CAAC;IACjB,GAAG,CAAC;QACH,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QACxF,MAAM,GAAG,SAAS,CAAC;QACnB,IAAI,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;IACzB,CAAC,QAAQ,MAAM,KAAK,GAAG,EAAE;IACzB,OAAO,IAAI,CAAC;AACb,CAAC","sourcesContent":["// Redis set helpers for socket logic\nimport type { Redis } from 'ioredis';\n\nexport async function scanKeys(redis: Redis, pattern: string): Promise<string[]> {\n\tconst keys: string[] = [];\n\tlet cursor = '0';\n\tdo {\n\t\tconst [newCursor, foundKeys] = await redis.scan(cursor, 'MATCH', pattern, 'COUNT', 100);\n\t\tcursor = newCursor;\n\t\tkeys.push(...foundKeys);\n\t} while (cursor !== '0');\n\treturn keys;\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import { EntitySubscription } from './keys';
2
+ export interface SocketRedisEventInformation {
3
+ eventKey: string;
4
+ instanceId: string;
5
+ socketId: string;
6
+ }
7
+ export declare function connectEntityToSocketEvent(entity: EntitySubscription, socketRedisEventInformation: SocketRedisEventInformation): Promise<void>;
8
+ export declare function disconnectEntityFromSocketEvent(entity: EntitySubscription, socketRedisEventInformation: SocketRedisEventInformation): Promise<{
9
+ removed: boolean;
10
+ socketsRemoved: number;
11
+ subscribersRemoved: number;
12
+ }>;
13
+ export declare function refreshEntityEventTTL(entity: EntitySubscription): Promise<void>;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.connectEntityToSocketEvent = connectEntityToSocketEvent;
4
+ exports.disconnectEntityFromSocketEvent = disconnectEntityFromSocketEvent;
5
+ exports.refreshEntityEventTTL = refreshEntityEventTTL;
6
+ const __1 = require("../../..");
7
+ const keys_1 = require("./keys");
8
+ const constants_1 = require("./constants");
9
+ const cache_1 = require("./cache");
10
+ const subscriptionCache = new cache_1.LRUCache(10000);
11
+ const eventSubscribersCache = new cache_1.LRUCache(5000);
12
+ async function connectEntityToSocketEvent(entity, socketRedisEventInformation) {
13
+ const redis = (0, __1.getLibraries)().getRedisService();
14
+ const entityKeyStr = (0, keys_1.entityKey)(entity);
15
+ const { instanceId, socketId, eventKey } = socketRedisEventInformation;
16
+ const socketData = `${instanceId}|${socketId}`;
17
+ const subscriberData = `${entityKeyStr}|${instanceId}|${socketId}`;
18
+ const entityEventKey = (0, keys_1.kEntityEventSockets)(entity, eventKey);
19
+ const eventSubsKey = (0, keys_1.kEventEntity)(eventKey);
20
+ const ledgerKey = (0, keys_1.kEntityEvent)(entity);
21
+ await Promise.all([
22
+ redis.addToSet(entityEventKey, socketData),
23
+ redis.addToSet(eventSubsKey, subscriberData),
24
+ redis.addToSet(ledgerKey, eventKey),
25
+ ]);
26
+ await Promise.all([
27
+ redis.redisClient.expire(entityEventKey, constants_1.REDIS_KEY_TTL_SECONDS),
28
+ redis.redisClient.expire(eventSubsKey, constants_1.REDIS_KEY_TTL_SECONDS),
29
+ redis.redisClient.expire(ledgerKey, constants_1.REDIS_KEY_TTL_SECONDS),
30
+ ]);
31
+ subscriptionCache.delete(`${entityKeyStr}:${eventKey}`);
32
+ eventSubscribersCache.delete(eventKey);
33
+ }
34
+ async function disconnectEntityFromSocketEvent(entity, socketRedisEventInformation) {
35
+ const redis = (0, __1.getLibraries)().getRedisService();
36
+ const entityKeyStr = (0, keys_1.entityKey)(entity);
37
+ const { instanceId, socketId, eventKey } = socketRedisEventInformation;
38
+ const entityEventKey = (0, keys_1.kEntityEventSockets)(entity, eventKey);
39
+ const eventSubsKey = (0, keys_1.kEventEntity)(eventKey);
40
+ const ledgerKey = (0, keys_1.kEntityEvent)(entity);
41
+ const socketData = `${instanceId}|${socketId}`;
42
+ const subscriberData = `${entityKeyStr}|${instanceId}|${socketId}`;
43
+ await Promise.all([
44
+ redis.removeFromSet(entityEventKey, socketData),
45
+ redis.removeFromSet(eventSubsKey, subscriberData),
46
+ ]);
47
+ const entitySockets = await redis.getSetMembers(entityEventKey);
48
+ if (entitySockets.length === 0) {
49
+ await Promise.all([redis.deleteCachedObject(entityEventKey), redis.removeFromSet(ledgerKey, eventKey)]);
50
+ }
51
+ subscriptionCache.delete(`${entityKeyStr}:${eventKey}`);
52
+ eventSubscribersCache.delete(eventKey);
53
+ return {
54
+ removed: true,
55
+ socketsRemoved: 1,
56
+ subscribersRemoved: 1,
57
+ };
58
+ }
59
+ async function refreshEntityEventTTL(entity) {
60
+ const redis = (0, __1.getLibraries)().getRedisService();
61
+ const ledgerKey = (0, keys_1.kEntityEvent)(entity);
62
+ const activeEvents = await redis.getSetMembers(ledgerKey);
63
+ if (!activeEvents.length)
64
+ return;
65
+ const pipeline = redis.redisClient.pipeline();
66
+ pipeline.expire(ledgerKey, constants_1.REDIS_KEY_TTL_SECONDS);
67
+ for (const eventKey of activeEvents) {
68
+ pipeline.expire((0, keys_1.kEntityEventSockets)(entity, eventKey), constants_1.REDIS_KEY_TTL_SECONDS);
69
+ pipeline.expire((0, keys_1.kEventEntity)(eventKey), constants_1.REDIS_KEY_TTL_SECONDS);
70
+ }
71
+ await pipeline.exec();
72
+ }
73
+ //# sourceMappingURL=subscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.js","sourceRoot":"/","sources":["libraries/socket/connections/subscription.ts"],"names":[],"mappings":"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","sourcesContent":["// Subscription management logic for socket Redis\nimport { getLibraries } from '../../..';\nimport { kEntityEventSockets, kEventEntity, kEntityEvent, entityKey, EntitySubscription } from './keys';\nimport { REDIS_KEY_TTL_SECONDS } from './constants';\nimport { LRUCache } from './cache';\n\nexport interface SocketRedisEventInformation {\n\teventKey: string;\n\tinstanceId: string;\n\tsocketId: string;\n}\n\nconst subscriptionCache = new LRUCache<\n\tstring,\n\t{ isSubscribed: boolean; instances: string[]; timestamp: number }\n>(10000);\nconst eventSubscribersCache = new LRUCache<string, { subscribers: EntitySubscription[]; timestamp: number }>(\n\t5000\n);\n\nexport async function connectEntityToSocketEvent(\n\tentity: EntitySubscription,\n\tsocketRedisEventInformation: SocketRedisEventInformation\n) {\n\tconst redis = getLibraries().getRedisService();\n\tconst entityKeyStr = entityKey(entity);\n\tconst { instanceId, socketId, eventKey } = socketRedisEventInformation;\n\tconst socketData = `${instanceId}|${socketId}`;\n\tconst subscriberData = `${entityKeyStr}|${instanceId}|${socketId}`;\n\tconst entityEventKey = kEntityEventSockets(entity, eventKey);\n\tconst eventSubsKey = kEventEntity(eventKey);\n\tconst ledgerKey = kEntityEvent(entity);\n\tawait Promise.all([\n\t\tredis.addToSet(entityEventKey, socketData),\n\t\tredis.addToSet(eventSubsKey, subscriberData),\n\t\tredis.addToSet(ledgerKey, eventKey),\n\t]);\n\tawait Promise.all([\n\t\tredis.redisClient.expire(entityEventKey, REDIS_KEY_TTL_SECONDS),\n\t\tredis.redisClient.expire(eventSubsKey, REDIS_KEY_TTL_SECONDS),\n\t\tredis.redisClient.expire(ledgerKey, REDIS_KEY_TTL_SECONDS),\n\t]);\n\tsubscriptionCache.delete(`${entityKeyStr}:${eventKey}`);\n\teventSubscribersCache.delete(eventKey);\n}\n\nexport async function disconnectEntityFromSocketEvent(\n\tentity: EntitySubscription,\n\tsocketRedisEventInformation: SocketRedisEventInformation\n) {\n\tconst redis = getLibraries().getRedisService();\n\tconst entityKeyStr = entityKey(entity);\n\tconst { instanceId, socketId, eventKey } = socketRedisEventInformation;\n\tconst entityEventKey = kEntityEventSockets(entity, eventKey);\n\tconst eventSubsKey = kEventEntity(eventKey);\n\tconst ledgerKey = kEntityEvent(entity);\n\tconst socketData = `${instanceId}|${socketId}`;\n\tconst subscriberData = `${entityKeyStr}|${instanceId}|${socketId}`;\n\tawait Promise.all([\n\t\tredis.removeFromSet(entityEventKey, socketData),\n\t\tredis.removeFromSet(eventSubsKey, subscriberData),\n\t]);\n\tconst entitySockets = await redis.getSetMembers(entityEventKey);\n\tif (entitySockets.length === 0) {\n\t\tawait Promise.all([redis.deleteCachedObject(entityEventKey), redis.removeFromSet(ledgerKey, eventKey)]);\n\t}\n\tsubscriptionCache.delete(`${entityKeyStr}:${eventKey}`);\n\teventSubscribersCache.delete(eventKey);\n\treturn {\n\t\tremoved: true,\n\t\tsocketsRemoved: 1,\n\t\tsubscribersRemoved: 1,\n\t};\n}\n\nexport async function refreshEntityEventTTL(entity: EntitySubscription) {\n\tconst redis = getLibraries().getRedisService();\n\tconst ledgerKey = kEntityEvent(entity);\n\tconst activeEvents = await redis.getSetMembers(ledgerKey);\n\tif (!activeEvents.length) return;\n\tconst pipeline = redis.redisClient.pipeline();\n\tpipeline.expire(ledgerKey, REDIS_KEY_TTL_SECONDS);\n\tfor (const eventKey of activeEvents) {\n\t\tpipeline.expire(kEntityEventSockets(entity, eventKey), REDIS_KEY_TTL_SECONDS);\n\t\tpipeline.expire(kEventEntity(eventKey), REDIS_KEY_TTL_SECONDS);\n\t}\n\tawait pipeline.exec();\n}\n"]}
@@ -2,6 +2,5 @@ export * from '../BaseSocketEvent';
2
2
  export * from './local-subscription-registry';
3
3
  export * from './socket-event-registry';
4
4
  export * from './zAsyncIterable';
5
- export * from './socket-redis-connections';
6
5
  export * from './socket-event-publisher';
7
6
  export * from './socket-event-consumer';
@@ -18,7 +18,6 @@ __exportStar(require("../BaseSocketEvent"), exports);
18
18
  __exportStar(require("./local-subscription-registry"), exports);
19
19
  __exportStar(require("./socket-event-registry"), exports);
20
20
  __exportStar(require("./zAsyncIterable"), exports);
21
- __exportStar(require("./socket-redis-connections"), exports);
22
21
  __exportStar(require("./socket-event-publisher"), exports);
23
22
  __exportStar(require("./socket-event-consumer"), exports);
24
23
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"/","sources":["libraries/socket/core/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,qDAAmC;AACnC,gEAA8C;AAC9C,0DAAwC;AACxC,mDAAiC;AACjC,6DAA2C;AAC3C,2DAAyC;AACzC,0DAAwC","sourcesContent":["export * from '../BaseSocketEvent';\nexport * from './local-subscription-registry';\nexport * from './socket-event-registry';\nexport * from './zAsyncIterable';\nexport * from './socket-redis-connections';\nexport * from './socket-event-publisher';\nexport * from './socket-event-consumer';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"/","sources":["libraries/socket/core/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,qDAAmC;AACnC,gEAA8C;AAC9C,0DAAwC;AACxC,mDAAiC;AACjC,2DAAyC;AACzC,0DAAwC","sourcesContent":["export * from '../BaseSocketEvent';\nexport * from './local-subscription-registry';\nexport * from './socket-event-registry';\nexport * from './zAsyncIterable';\nexport * from './socket-event-publisher';\nexport * from './socket-event-consumer';\n"]}
@@ -1,5 +1,5 @@
1
1
  import EventEmitter from 'events';
2
- import { EntitySubscription } from './socket-redis-connections';
2
+ import { EntitySubscription } from '../connections';
3
3
  type EventKey = string;
4
4
  type SocketId = string;
5
5
  export declare class LocalEventEmitter {
@@ -1 +1 @@
1
- {"version":3,"file":"local-subscription-registry.js","sourceRoot":"/","sources":["libraries/socket/core/local-subscription-registry.ts"],"names":[],"mappings":";;;;;;AAAA,oDAAkC;AAOlC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;AAC3C,MAAM,SAAS,GAAG,CAAC,MAA0B,EAAU,EAAE;IACxD,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI,SAAS,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;IACvD,IAAI,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,CAAC;QACb,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC,CAAC;AAGF,MAAa,iBAAiB;IACpB,EAAE,CAAe;IACjB,QAAQ,CAAW;IAE5B,YAAY,QAAkB;QAC7B,IAAI,CAAC,EAAE,GAAG,IAAI,gBAAY,EAAE,CAAC;QAC7B,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;CACD;AATD,8CASC;AAED,MAAM,yBAAyB;IAEtB,SAAS,GAAG,IAAI,GAAG,EAAkC,CAAC;IAE9D,IAAI,CAAC,MAA0B,EAAE,QAAkB,EAAE,EAAqB;QACzE,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC/C,IAAI,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE1C,IAAI,CAAC,WAAW,EAAE,CAAC;YAClB,WAAW,GAAG,IAAI,GAAG,EAAE,CAAC;YACxB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QACtC,CAAC;QAED,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC;IAED,MAAM,CAAC,MAA0B,EAAE,QAAkB,EAAE,EAAqB;QAC3E,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE5C,IAAI,WAAW,EAAE,CAAC;YACjB,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACvB,IAAI,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBAC5B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC5B,CAAC;QACF,CAAC;IACF,CAAC;IAGD,IAAI,CAAC,MAA0B,EAAE,QAAkB,EAAE,OAAgB;QACpE,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE1C,IAAI,CAAC,SAAS;YAAE,OAAO;QAGvB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YAClC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;IACF,CAAC;CACD;AAEY,QAAA,SAAS,GAAG,IAAI,yBAAyB,EAAE,CAAC","sourcesContent":["import EventEmitter from 'events';\nimport { EntitySubscription } from './socket-redis-connections';\n\ntype EventKey = string;\ntype SocketId = string;\n\n// Zero-overhead key with memoization\nconst keyCache = new Map<string, string>();\nconst entityKey = (entity: EntitySubscription): string => {\n\tconst raw = `${entity.type ?? 'default'}:${entity.id}`;\n\tlet cached = keyCache.get(raw);\n\tif (!cached) {\n\t\tcached = raw;\n\t\tkeyCache.set(raw, cached);\n\t}\n\treturn cached;\n};\n\n// Remove wrapper class - direct EventEmitter usage\nexport class LocalEventEmitter {\n\treadonly ee: EventEmitter;\n\treadonly socketId: SocketId;\n\n\tconstructor(socketId: SocketId) {\n\t\tthis.ee = new EventEmitter();\n\t\tthis.ee.setMaxListeners(0); // Unlimited listeners\n\t\tthis.socketId = socketId;\n\t}\n}\n\nclass LocalSubscriptionRegistry {\n\t// Direct map for O(1) lookups with minimal overhead\n\tprivate listeners = new Map<string, Set<LocalEventEmitter>>();\n\n\tbind(entity: EntitySubscription, eventKey: EventKey, ee: LocalEventEmitter): void {\n\t\tconst key = `${entityKey(entity)}:${eventKey}`;\n\t\tlet listenerSet = this.listeners.get(key);\n\n\t\tif (!listenerSet) {\n\t\t\tlistenerSet = new Set();\n\t\t\tthis.listeners.set(key, listenerSet);\n\t\t}\n\n\t\tlistenerSet.add(ee);\n\t}\n\n\tunbind(entity: EntitySubscription, eventKey: EventKey, ee: LocalEventEmitter): void {\n\t\tconst key = `${entityKey(entity)}:${eventKey}`;\n\t\tconst listenerSet = this.listeners.get(key);\n\n\t\tif (listenerSet) {\n\t\t\tlistenerSet.delete(ee);\n\t\t\tif (listenerSet.size === 0) {\n\t\t\t\tthis.listeners.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Zero-overhead emit - inline fast path\n\temit(entity: EntitySubscription, eventKey: EventKey, payload: unknown): void {\n\t\tconst key = `${entityKey(entity)}:${eventKey}`;\n\t\tconst listeners = this.listeners.get(key);\n\n\t\tif (!listeners) return;\n\n\t\t// Direct iteration - fastest possible\n\t\tfor (const listener of listeners) {\n\t\t\tlistener.ee.emit(eventKey, payload);\n\t\t}\n\t}\n}\n\nexport const LocalSubs = new LocalSubscriptionRegistry();\n"]}
1
+ {"version":3,"file":"local-subscription-registry.js","sourceRoot":"/","sources":["libraries/socket/core/local-subscription-registry.ts"],"names":[],"mappings":";;;;;;AAAA,oDAAkC;AAOlC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;AAC3C,MAAM,SAAS,GAAG,CAAC,MAA0B,EAAU,EAAE;IACxD,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI,SAAS,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;IACvD,IAAI,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,CAAC;QACb,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC,CAAC;AAGF,MAAa,iBAAiB;IACpB,EAAE,CAAe;IACjB,QAAQ,CAAW;IAE5B,YAAY,QAAkB;QAC7B,IAAI,CAAC,EAAE,GAAG,IAAI,gBAAY,EAAE,CAAC;QAC7B,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;CACD;AATD,8CASC;AAED,MAAM,yBAAyB;IAEtB,SAAS,GAAG,IAAI,GAAG,EAAkC,CAAC;IAE9D,IAAI,CAAC,MAA0B,EAAE,QAAkB,EAAE,EAAqB;QACzE,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC/C,IAAI,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE1C,IAAI,CAAC,WAAW,EAAE,CAAC;YAClB,WAAW,GAAG,IAAI,GAAG,EAAE,CAAC;YACxB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QACtC,CAAC;QAED,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC;IAED,MAAM,CAAC,MAA0B,EAAE,QAAkB,EAAE,EAAqB;QAC3E,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE5C,IAAI,WAAW,EAAE,CAAC;YACjB,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACvB,IAAI,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBAC5B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC5B,CAAC;QACF,CAAC;IACF,CAAC;IAGD,IAAI,CAAC,MAA0B,EAAE,QAAkB,EAAE,OAAgB;QACpE,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE1C,IAAI,CAAC,SAAS;YAAE,OAAO;QAGvB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YAClC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;IACF,CAAC;CACD;AAEY,QAAA,SAAS,GAAG,IAAI,yBAAyB,EAAE,CAAC","sourcesContent":["import EventEmitter from 'events';\nimport { EntitySubscription } from '../connections';\n\ntype EventKey = string;\ntype SocketId = string;\n\n// Zero-overhead key with memoization\nconst keyCache = new Map<string, string>();\nconst entityKey = (entity: EntitySubscription): string => {\n\tconst raw = `${entity.type ?? 'default'}:${entity.id}`;\n\tlet cached = keyCache.get(raw);\n\tif (!cached) {\n\t\tcached = raw;\n\t\tkeyCache.set(raw, cached);\n\t}\n\treturn cached;\n};\n\n// Remove wrapper class - direct EventEmitter usage\nexport class LocalEventEmitter {\n\treadonly ee: EventEmitter;\n\treadonly socketId: SocketId;\n\n\tconstructor(socketId: SocketId) {\n\t\tthis.ee = new EventEmitter();\n\t\tthis.ee.setMaxListeners(0); // Unlimited listeners\n\t\tthis.socketId = socketId;\n\t}\n}\n\nclass LocalSubscriptionRegistry {\n\t// Direct map for O(1) lookups with minimal overhead\n\tprivate listeners = new Map<string, Set<LocalEventEmitter>>();\n\n\tbind(entity: EntitySubscription, eventKey: EventKey, ee: LocalEventEmitter): void {\n\t\tconst key = `${entityKey(entity)}:${eventKey}`;\n\t\tlet listenerSet = this.listeners.get(key);\n\n\t\tif (!listenerSet) {\n\t\t\tlistenerSet = new Set();\n\t\t\tthis.listeners.set(key, listenerSet);\n\t\t}\n\n\t\tlistenerSet.add(ee);\n\t}\n\n\tunbind(entity: EntitySubscription, eventKey: EventKey, ee: LocalEventEmitter): void {\n\t\tconst key = `${entityKey(entity)}:${eventKey}`;\n\t\tconst listenerSet = this.listeners.get(key);\n\n\t\tif (listenerSet) {\n\t\t\tlistenerSet.delete(ee);\n\t\t\tif (listenerSet.size === 0) {\n\t\t\t\tthis.listeners.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Zero-overhead emit - inline fast path\n\temit(entity: EntitySubscription, eventKey: EventKey, payload: unknown): void {\n\t\tconst key = `${entityKey(entity)}:${eventKey}`;\n\t\tconst listeners = this.listeners.get(key);\n\n\t\tif (!listeners) return;\n\n\t\t// Direct iteration - fastest possible\n\t\tfor (const listener of listeners) {\n\t\t\tlistener.ee.emit(eventKey, payload);\n\t\t}\n\t}\n}\n\nexport const LocalSubs = new LocalSubscriptionRegistry();\n"]}
@@ -1,6 +1,6 @@
1
1
  import { BaseSocketEvent } from '../BaseSocketEvent';
2
- import { EntitySubscription } from './socket-redis-connections';
3
2
  import { SocketNotificationEvent } from '../events';
4
3
  import type { ZodTypeAny } from 'zod';
4
+ import { EntitySubscription } from '../connections';
5
5
  export declare function publishSocketEvent(event: BaseSocketEvent<ZodTypeAny, ZodTypeAny, ZodTypeAny | undefined>, recipients: EntitySubscription[]): Promise<void>;
6
6
  export declare function publishNotificationSocketEvent(event: SocketNotificationEvent, recipients: EntitySubscription[]): Promise<void>;
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.publishSocketEvent = publishSocketEvent;
4
4
  exports.publishNotificationSocketEvent = publishNotificationSocketEvent;
5
5
  const __1 = require("../../..");
6
- const socket_redis_connections_1 = require("./socket-redis-connections");
7
6
  const event_1 = require("../../event");
8
7
  const PushNotificationEvent_1 = require("../PushNotificationEvent");
8
+ const connections_1 = require("../connections");
9
9
  const PUBLISH_OPTIONS = {
10
10
  contentType: 'application/json',
11
11
  persistent: true,
@@ -38,16 +38,13 @@ async function getActiveSubscribedRecipients(recipients, localKey) {
38
38
  const subscribed = [];
39
39
  const unsubscribed = [];
40
40
  await Promise.all(recipients.map(async (recipient) => {
41
- const sockets = await redis.getSetMembers((0, socket_redis_connections_1.getEntityEventSocketsKey)(recipient, localKey));
41
+ const sockets = await redis.getSetMembers((0, connections_1.kEntityEventSockets)(recipient, localKey));
42
42
  if (sockets.length > 0) {
43
43
  const instanceSet = new Set();
44
44
  for (let i = 0; i < sockets.length; i++) {
45
- try {
46
- const socketInfo = JSON.parse(sockets[i]);
47
- instanceSet.add(socketInfo.instanceId);
48
- }
49
- catch {
50
- }
45
+ const [instanceId] = sockets[i].split('|');
46
+ if (instanceId)
47
+ instanceSet.add(instanceId);
51
48
  }
52
49
  if (instanceSet.size > 0) {
53
50
  subscribed.push({ recipient, instances: Array.from(instanceSet) });
@@ -94,16 +91,13 @@ async function publishNotificationSocketEvent(event, recipients) {
94
91
  const redis = (0, __1.getLibraries)().getRedisService();
95
92
  const validInstances = [];
96
93
  await Promise.all(recipients.map(async (recipient) => {
97
- const sockets = await redis.getSetMembers((0, socket_redis_connections_1.getEntityEventSocketsKey)(recipient, eventKey));
94
+ const sockets = await redis.getSetMembers((0, connections_1.kEntityEventSockets)(recipient, eventKey));
98
95
  if (sockets.length > 0) {
99
96
  const instanceSet = new Set();
100
97
  for (let i = 0; i < sockets.length; i++) {
101
- try {
102
- const socketInfo = JSON.parse(sockets[i]);
103
- instanceSet.add(socketInfo.instanceId);
104
- }
105
- catch {
106
- }
98
+ const [instanceId] = sockets[i].split('|');
99
+ if (instanceId)
100
+ instanceSet.add(instanceId);
107
101
  }
108
102
  if (instanceSet.size > 0) {
109
103
  validInstances.push({ recipient, instances: Array.from(instanceSet) });
@@ -1 +1 @@
1
- {"version":3,"file":"socket-event-publisher.js","sourceRoot":"/","sources":["libraries/socket/core/socket-event-publisher.ts"],"names":[],"mappings":"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","sourcesContent":["import { getLibraries } from '../../..';\nimport { BaseSocketEvent } from '../BaseSocketEvent';\nimport { EntitySubscription, getEntityEventSocketsKey } from './socket-redis-connections';\nimport { SocketNotificationEvent } from '../events';\nimport { EXCHANGE_NAME, getChannel, INSTANCE_ROUTE_PREFIX, publishEvent } from '../../event';\nimport { PushNotificationEvent } from '../PushNotificationEvent';\nimport type { ZodTypeAny } from 'zod';\n\n// Reusable publish options\nconst PUBLISH_OPTIONS = {\n\tcontentType: 'application/json',\n\tpersistent: true,\n} as const;\n\n// Zero-overhead publishing - minimal allocations\nfunction publishToInstances(\n\trecipientsWithInstances: Array<{ recipient: EntitySubscription; instances: string[] }>,\n\tlocalKey: string,\n\tpayload: unknown\n): void {\n\tif (recipientsWithInstances.length === 0) return;\n\n\tconst channel = getChannel().pubChannel;\n\n\t// Pre-serialize message once\n\tconst message = { localKey, payload, recipient: null as any };\n\n\t// Fire-and-forget with minimal overhead\n\tfor (let i = 0; i < recipientsWithInstances.length; i++) {\n\t\tconst { recipient, instances } = recipientsWithInstances[i];\n\t\tmessage.recipient = recipient;\n\t\tconst messageStr = JSON.stringify(message);\n\n\t\tfor (let j = 0; j < instances.length; j++) {\n\t\t\tconst routingKey = `${INSTANCE_ROUTE_PREFIX}.${instances[j]}`;\n\n\t\t\ttry {\n\t\t\t\t// Direct publish - Buffer.from creates minimal overhead\n\t\t\t\tchannel.publish(EXCHANGE_NAME, routingKey, Buffer.from(messageStr, 'utf8'), PUBLISH_OPTIONS);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`[Socket] Publish failed: ${routingKey}`, error);\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Ultra-simple: Direct Redis lookups, no batch/cache/parsing!\nasync function getActiveSubscribedRecipients(\n\trecipients: EntitySubscription[],\n\tlocalKey: string\n): Promise<{\n\tsubscribed: Array<{ recipient: EntitySubscription; instances: string[] }>;\n\tunsubscribed: EntitySubscription[];\n}> {\n\tif (recipients.length === 0) {\n\t\treturn { subscribed: [], unsubscribed: [] };\n\t}\n\n\tconst redis = getLibraries().getRedisService();\n\tconst subscribed: Array<{ recipient: EntitySubscription; instances: string[] }> = [];\n\tconst unsubscribed: EntitySubscription[] = [];\n\n\t// Parallel lookups - one key per recipient\n\tawait Promise.all(\n\t\trecipients.map(async recipient => {\n\t\t\tconst sockets = await redis.getSetMembers(getEntityEventSocketsKey(recipient, localKey));\n\n\t\t\tif (sockets.length > 0) {\n\t\t\t\t// Extract instances\n\t\t\t\tconst instanceSet = new Set<string>();\n\t\t\t\tfor (let i = 0; i < sockets.length; i++) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst socketInfo = JSON.parse(sockets[i]);\n\t\t\t\t\t\tinstanceSet.add(socketInfo.instanceId);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Skip malformed socket data\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (instanceSet.size > 0) {\n\t\t\t\t\tsubscribed.push({ recipient, instances: Array.from(instanceSet) });\n\t\t\t\t} else {\n\t\t\t\t\tunsubscribed.push(recipient);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tunsubscribed.push(recipient);\n\t\t\t}\n\t\t})\n\t);\n\n\treturn { subscribed, unsubscribed };\n}\n\n// Minimal overhead publish - early returns, lazy evaluation\nexport async function publishSocketEvent(\n\tevent: BaseSocketEvent<ZodTypeAny, ZodTypeAny, ZodTypeAny | undefined>,\n\trecipients: EntitySubscription[]\n): Promise<void> {\n\tconst logger = getLibraries().getLogger().logger;\n\tif (recipients.length === 0) return;\n\n\tconst localKey = event.getSubscriptionKey();\n\tconst payload = event.payload();\n\n\tconst { subscribed, unsubscribed } = await getActiveSubscribedRecipients(recipients, localKey);\n\n\tlogger.debug({ subscribed }, '[Socket] Subscribed recipients:');\n\tlogger.debug({ unsubscribed }, '[Socket] Unsubscribed recipients:');\n\n\tif (subscribed.length > 0) publishToInstances(subscribed, localKey, payload);\n\n\tif (unsubscribed.length > 0) {\n\t\tlogger.debug({ unsubscribed }, '[Socket] Processing unsubscribed recipients');\n\t\tif (event.notificationSettings?.isPushNotification) {\n\t\t\tconst pushNotificationPayload = event.getPushNotificationPayload();\n\t\t\tconst settings = event.notificationSettings;\n\t\t\tawait publishEvent(\n\t\t\t\tnew PushNotificationEvent(event.eventType(), pushNotificationPayload, unsubscribed, settings)\n\t\t\t).catch(err => console.error('[Socket] Push notification failed:', err));\n\t\t}\n\n\t\tconst socketNotificationPayload = event.getSocketNotificationEvent();\n\n\t\tlogger.debug({ socketNotificationPayload }, '[Socket] Socket notification payload');\n\n\t\tif (event.getSocketNotificationEvent()) {\n\t\t\tawait publishNotificationSocketEvent(socketNotificationPayload!, unsubscribed);\n\t\t}\n\t}\n}\n\nexport async function publishNotificationSocketEvent(\n\tevent: SocketNotificationEvent,\n\trecipients: EntitySubscription[]\n): Promise<void> {\n\tif (recipients.length === 0) return;\n\n\tconst eventKey = event.getSubscriptionKey();\n\tconst redis = getLibraries().getRedisService();\n\tconst validInstances: Array<{ recipient: EntitySubscription; instances: string[] }> = [];\n\n\t// Parallel direct lookups\n\tawait Promise.all(\n\t\trecipients.map(async recipient => {\n\t\t\tconst sockets = await redis.getSetMembers(getEntityEventSocketsKey(recipient, eventKey));\n\n\t\t\tif (sockets.length > 0) {\n\t\t\t\tconst instanceSet = new Set<string>();\n\t\t\t\tfor (let i = 0; i < sockets.length; i++) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst socketInfo = JSON.parse(sockets[i]);\n\t\t\t\t\t\tinstanceSet.add(socketInfo.instanceId);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Skip malformed socket data\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (instanceSet.size > 0) {\n\t\t\t\t\tvalidInstances.push({ recipient, instances: Array.from(instanceSet) });\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t);\n\n\tif (validInstances.length > 0) {\n\t\tpublishToInstances(validInstances, eventKey, event.payload());\n\t}\n}\n"]}
1
+ {"version":3,"file":"socket-event-publisher.js","sourceRoot":"/","sources":["libraries/socket/core/socket-event-publisher.ts"],"names":[],"mappings":"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","sourcesContent":["import { getLibraries } from '../../..';\nimport { BaseSocketEvent } from '../BaseSocketEvent';\nimport { SocketNotificationEvent } from '../events';\nimport { EXCHANGE_NAME, getChannel, INSTANCE_ROUTE_PREFIX, publishEvent } from '../../event';\nimport { PushNotificationEvent } from '../PushNotificationEvent';\nimport type { ZodTypeAny } from 'zod';\nimport { EntitySubscription, kEntityEventSockets } from '../connections';\n\n// Reusable publish options\nconst PUBLISH_OPTIONS = {\n\tcontentType: 'application/json',\n\tpersistent: true,\n} as const;\n\n// Zero-overhead publishing - minimal allocations\nfunction publishToInstances(\n\trecipientsWithInstances: Array<{ recipient: EntitySubscription; instances: string[] }>,\n\tlocalKey: string,\n\tpayload: unknown\n): void {\n\tif (recipientsWithInstances.length === 0) return;\n\n\tconst channel = getChannel().pubChannel;\n\n\t// Pre-serialize message once\n\tconst message = { localKey, payload, recipient: null as any };\n\n\t// Fire-and-forget with minimal overhead\n\tfor (let i = 0; i < recipientsWithInstances.length; i++) {\n\t\tconst { recipient, instances } = recipientsWithInstances[i];\n\t\tmessage.recipient = recipient;\n\t\tconst messageStr = JSON.stringify(message);\n\n\t\tfor (let j = 0; j < instances.length; j++) {\n\t\t\tconst routingKey = `${INSTANCE_ROUTE_PREFIX}.${instances[j]}`;\n\n\t\t\ttry {\n\t\t\t\t// Direct publish - Buffer.from creates minimal overhead\n\t\t\t\tchannel.publish(EXCHANGE_NAME, routingKey, Buffer.from(messageStr, 'utf8'), PUBLISH_OPTIONS);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`[Socket] Publish failed: ${routingKey}`, error);\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Ultra-simple: Direct Redis lookups, no batch/cache/parsing!\nasync function getActiveSubscribedRecipients(\n\trecipients: EntitySubscription[],\n\tlocalKey: string\n): Promise<{\n\tsubscribed: Array<{ recipient: EntitySubscription; instances: string[] }>;\n\tunsubscribed: EntitySubscription[];\n}> {\n\tif (recipients.length === 0) {\n\t\treturn { subscribed: [], unsubscribed: [] };\n\t}\n\n\tconst redis = getLibraries().getRedisService();\n\tconst subscribed: Array<{ recipient: EntitySubscription; instances: string[] }> = [];\n\tconst unsubscribed: EntitySubscription[] = [];\n\n\t// Parallel lookups - one key per recipient\n\tawait Promise.all(\n\t\trecipients.map(async recipient => {\n\t\t\tconst sockets = await redis.getSetMembers(kEntityEventSockets(recipient, localKey));\n\t\t\tif (sockets.length > 0) {\n\t\t\t\tconst instanceSet = new Set<string>();\n\t\t\t\tfor (let i = 0; i < sockets.length; i++) {\n\t\t\t\t\tconst [instanceId] = sockets[i].split('|');\n\t\t\t\t\tif (instanceId) instanceSet.add(instanceId);\n\t\t\t\t}\n\t\t\t\tif (instanceSet.size > 0) {\n\t\t\t\t\tsubscribed.push({ recipient, instances: Array.from(instanceSet) });\n\t\t\t\t} else {\n\t\t\t\t\tunsubscribed.push(recipient);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tunsubscribed.push(recipient);\n\t\t\t}\n\t\t})\n\t);\n\n\treturn { subscribed, unsubscribed };\n}\n\n// Minimal overhead publish - early returns, lazy evaluation\nexport async function publishSocketEvent(\n\tevent: BaseSocketEvent<ZodTypeAny, ZodTypeAny, ZodTypeAny | undefined>,\n\trecipients: EntitySubscription[]\n): Promise<void> {\n\tconst logger = getLibraries().getLogger().logger;\n\tif (recipients.length === 0) return;\n\n\tconst localKey = event.getSubscriptionKey();\n\tconst payload = event.payload();\n\n\tconst { subscribed, unsubscribed } = await getActiveSubscribedRecipients(recipients, localKey);\n\n\tlogger.debug({ subscribed }, '[Socket] Subscribed recipients:');\n\tlogger.debug({ unsubscribed }, '[Socket] Unsubscribed recipients:');\n\n\tif (subscribed.length > 0) publishToInstances(subscribed, localKey, payload);\n\n\tif (unsubscribed.length > 0) {\n\t\tlogger.debug({ unsubscribed }, '[Socket] Processing unsubscribed recipients');\n\t\tif (event.notificationSettings?.isPushNotification) {\n\t\t\tconst pushNotificationPayload = event.getPushNotificationPayload();\n\t\t\tconst settings = event.notificationSettings;\n\t\t\tawait publishEvent(\n\t\t\t\tnew PushNotificationEvent(event.eventType(), pushNotificationPayload, unsubscribed, settings)\n\t\t\t).catch(err => console.error('[Socket] Push notification failed:', err));\n\t\t}\n\n\t\tconst socketNotificationPayload = event.getSocketNotificationEvent();\n\n\t\tlogger.debug({ socketNotificationPayload }, '[Socket] Socket notification payload');\n\n\t\tif (event.getSocketNotificationEvent()) {\n\t\t\tawait publishNotificationSocketEvent(socketNotificationPayload!, unsubscribed);\n\t\t}\n\t}\n}\n\nexport async function publishNotificationSocketEvent(\n\tevent: SocketNotificationEvent,\n\trecipients: EntitySubscription[]\n): Promise<void> {\n\tif (recipients.length === 0) return;\n\n\tconst eventKey = event.getSubscriptionKey();\n\tconst redis = getLibraries().getRedisService();\n\tconst validInstances: Array<{ recipient: EntitySubscription; instances: string[] }> = [];\n\n\t// Parallel direct lookups\n\tawait Promise.all(\n\t\trecipients.map(async recipient => {\n\t\t\tconst sockets = await redis.getSetMembers(kEntityEventSockets(recipient, eventKey));\n\t\t\tif (sockets.length > 0) {\n\t\t\t\tconst instanceSet = new Set<string>();\n\t\t\t\tfor (let i = 0; i < sockets.length; i++) {\n\t\t\t\t\tconst [instanceId] = sockets[i].split('|');\n\t\t\t\t\tif (instanceId) instanceSet.add(instanceId);\n\t\t\t\t}\n\t\t\t\tif (instanceSet.size > 0) {\n\t\t\t\t\tvalidInstances.push({ recipient, instances: Array.from(instanceSet) });\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t);\n\n\tif (validInstances.length > 0) {\n\t\tpublishToInstances(validInstances, eventKey, event.payload());\n\t}\n}\n"]}
@@ -22,7 +22,7 @@ Perfect for sharing types between frontend and backend applications.
22
22
 
23
23
  ## Version
24
24
 
25
- Version: 1.3.76
25
+ Version: 1.3.80
26
26
 
27
27
  ## Dependencies
28
28
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyxa.ai/types",
3
- "version": "1.3.76",
3
+ "version": "1.3.80",
4
4
  "description": "Lyxa type definitions and validation schemas for both frontend and backend",
5
5
  "author": "elie <42282499+Internalizable@users.noreply.github.com>",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyxa.ai/core",
3
- "version": "1.3.76",
3
+ "version": "1.3.80",
4
4
  "description": "The Core system of the Lyxa services.",
5
5
  "author": "elie <42282499+Internalizable@users.noreply.github.com>",
6
6
  "license": "MIT",
@@ -1,36 +0,0 @@
1
- import { AuthEntityType } from '../../auth';
2
- export type EntitySubscription = {
3
- id: string;
4
- type?: AuthEntityType;
5
- };
6
- export interface SocketRedisEventInformation {
7
- eventKey: string;
8
- instanceId: string;
9
- socketId: string;
10
- }
11
- export declare const entityKey: (entity: EntitySubscription) => string;
12
- export declare const getEntityEventSocketsKey: (entity: EntitySubscription, eventKey: string) => string;
13
- export declare function connectEntityToSocketEvent(entity: EntitySubscription, socketRedisEventInformation: SocketRedisEventInformation): Promise<void>;
14
- export declare function getConnectedEntityByType(type: AuthEntityType): Promise<string[]>;
15
- export declare function disconnectEntityFromSocketEvent(entity: EntitySubscription, socketRedisEventInformation: SocketRedisEventInformation): Promise<{
16
- removed: boolean;
17
- socketsRemoved: number;
18
- subscribersRemoved: number;
19
- }>;
20
- export declare function getEntitySubscriptionInfo(entity: EntitySubscription, eventKey: string): Promise<{
21
- isSubscribed: boolean;
22
- instances: string[];
23
- }>;
24
- export declare function getEntitySubscriptionInfoBatch(entities: Array<{
25
- entity: EntitySubscription;
26
- eventKey: string;
27
- }>): Promise<Map<string, {
28
- isSubscribed: boolean;
29
- instances: string[];
30
- }>>;
31
- export declare function isEntityConnected(entity: EntitySubscription, eventKey: string): Promise<boolean>;
32
- export declare function disconnectAllEntitiesFromInstance(entityType?: AuthEntityType): Promise<void>;
33
- export declare function getEventSubscribers(eventKey: string): Promise<EntitySubscription[]>;
34
- export declare function getEventSubscribersBatch(eventKeys: string[]): Promise<Map<string, EntitySubscription[]>>;
35
- export declare function getEventSubscribersByType(eventKey: string, entityType: AuthEntityType): Promise<EntitySubscription[]>;
36
- export declare function getEventSubscriberCount(eventKey: string): Promise<number>;