@lyxa.ai/core 1.2.20 → 1.2.22

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.
@@ -21,6 +21,7 @@ export declare class Order extends TimeStamps {
21
21
  note?: string;
22
22
  scheduledFor?: Date;
23
23
  triggerAt?: Date;
24
+ placedAt?: Date;
24
25
  orderCancel?: OrderCancel;
25
26
  isLateOrder?: boolean;
26
27
  isUrgentOrder?: boolean;
@@ -43,6 +43,7 @@ let Order = class Order extends defaultClasses_1.TimeStamps {
43
43
  note;
44
44
  scheduledFor;
45
45
  triggerAt;
46
+ placedAt;
46
47
  orderCancel;
47
48
  isLateOrder;
48
49
  isUrgentOrder;
@@ -120,6 +121,10 @@ __decorate([
120
121
  (0, typegoose_1.prop)({ type: Date }),
121
122
  __metadata("design:type", Date)
122
123
  ], Order.prototype, "triggerAt", void 0);
124
+ __decorate([
125
+ (0, typegoose_1.prop)({ type: Date }),
126
+ __metadata("design:type", Date)
127
+ ], Order.prototype, "placedAt", void 0);
123
128
  __decorate([
124
129
  (0, typegoose_1.prop)({ type: () => order_cancel_model_1.OrderCancel }),
125
130
  __metadata("design:type", order_cancel_model_1.OrderCancel)
@@ -1 +1 @@
1
- {"version":3,"file":"order.model.js","sourceRoot":"/","sources":["libraries/mongo/models/order.model.ts"],"names":[],"mappings":"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","sourcesContent":["import { index, modelOptions, pre, prop, Ref, Severity } from '@typegoose/typegoose';\nimport { TimeStamps } from '@typegoose/typegoose/lib/defaultClasses';\nimport { CounterType, FlagType, OrderType, UrgentOrderReasons } from '../../../utilities/enum';\nimport { OrderCancel } from './embedded/order-cancel.model';\nimport { Rider } from './rider.model';\nimport { DeliveryFeeInformation } from './embedded/order-delivery-information.model';\nimport { RiderAssignment } from './embedded/rider-assignment-model';\nimport { Flag } from './flag.model';\nimport { Review } from './review.model';\nimport { TripLeg } from './embedded/trip-leg.mode';\nimport { CounterModel } from '.';\nimport { LyxaTimezone } from '../../../utilities/time';\nimport dayjs from 'dayjs';\nimport utc from 'dayjs/plugin/utc';\nimport timezone from 'dayjs/plugin/timezone';\n\ndayjs.extend(utc);\ndayjs.extend(timezone);\n\n@modelOptions({\n\tschemaOptions: {\n\t\tcollection: 'orders',\n\t\tdiscriminatorKey: 'orderType',\n\t\ttoJSON: { virtuals: true },\n\t\ttoObject: { virtuals: true },\n\t},\n\toptions: { allowMixed: Severity.ALLOW },\n})\n@index({ 'deliveryAddress.location': '2dsphere' })\n@index({ user: 1, status: 1, processedAt: -1 })\n@index({ shop: 1, status: 1, processedAt: -1 })\n@index({ parent: 1, status: 1, processedAt: -1 })\n@index({ orderType: 1, status: 1, processedAt: -1 })\n@index({ orderType: 1, status: 1, isEndorseLossApplied: 1, processedAt: -1 })\n@index({ itemType: 1, status: 1, isEndorseLossApplied: 1, processedAt: -1 })\n@index({ shop: 1, status: 1, isEndorseLossApplied: 1, processedAt: -1 })\n@index({ parent: 1, status: 1, isEndorseLossApplied: 1, processedAt: -1 })\n@index({ rider: 1, status: 1, isEndorseLossApplied: 1, processedAt: -1 })\n@pre<Order>('validate', async function (next) {\n\tif (this.isNew) {\n\t\tconst today = dayjs().tz(LyxaTimezone).format('DDMMYY');\n\n\t\tconst counter = await CounterModel.findOneAndUpdate(\n\t\t\t{ counterType: CounterType.ORDER },\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\t$set: {\n\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\t$cond: [{ $eq: ['$today', today] }, { $add: ['$value', 1] }, 1],\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttoday: today,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\t{ new: true, upsert: true }\n\t\t);\n\n\t\tthis.orderId = `${today}${counter.value.toString().padStart(6, '0')}`;\n\t}\n\tnext();\n})\nexport class Order extends TimeStamps {\n\t@prop({ required: true, type: String, unique: true })\n\tpublic orderId: string;\n\n\t@prop({ type: String, enum: OrderType, default: OrderType.REGULAR })\n\tpublic orderType?: OrderType;\n\n\t@prop({ ref: () => Rider, index: true })\n\tpublic rider?: Ref<Rider>;\n\n\t@prop({ type: () => DeliveryFeeInformation })\n\tpublic deliveryFeeInformation?: DeliveryFeeInformation;\n\n\t@prop({ type: Date })\n\tpublic estimatedDeliveredTime: Date;\n\n\t@prop({ type: Number })\n\tpublic estimatedDeliveredTimeInMinutes: number;\n\n\t@prop({ type: Date })\n\tpublic deliveredAt: Date;\n\n\t@prop({ type: Number })\n\tpublic deliveredTimeInMinutes: number;\n\n\t@prop({ type: String })\n\tpublic instruction?: string;\n\n\t@prop({ type: String })\n\tpublic note?: string;\n\n\t@prop({ type: Date })\n\tpublic scheduledFor?: Date;\n\n\t@prop({ type: Date })\n\tpublic triggerAt?: Date;\n\n\t@prop({ type: () => OrderCancel })\n\tpublic orderCancel?: OrderCancel;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isLateOrder?: boolean;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isUrgentOrder?: boolean;\n\n\t@prop({ type: () => [String], enum: UrgentOrderReasons, default: [] })\n\tpublic urgentOrderReason?: UrgentOrderReasons[];\n\n\t@prop({ type: Date, default: new Date() })\n\tpublic processedAt?: Date;\n\n\t@prop({\n\t\ttype: Number,\n\t\trequired: true,\n\t\tmin: 1000,\n\t\tmax: 9999,\n\t\tvalidate: {\n\t\t\tvalidator: (v: number) => Number.isInteger(v),\n\t\t\tmessage: 'Pin code must be an integer',\n\t\t},\n\t})\n\tpublic pinCode!: number;\n\n\t// Review feature\n\t@prop({ type: Boolean, default: false })\n\tpublic isOrderReviewed?: boolean;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isReviewNotificationSent?: boolean;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isLowRated?: boolean;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isResolved?: boolean;\n\n\t@prop({\n\t\tref: () => Review,\n\t\tforeignField: 'order',\n\t\tlocalField: '_id',\n\t})\n\tpublic reviews: Ref<Review>[];\n\n\t// Flag feature\n\t@prop({ type: Boolean, default: false })\n\tpublic isFlagged?: boolean;\n\n\t@prop({ type: [String], enum: FlagType, default: [] })\n\tpublic flagTypes?: FlagType[];\n\n\t@prop({ type: Date })\n\tpublic flaggedAt?: Date;\n\n\t@prop({\n\t\tref: () => Flag,\n\t\tforeignField: 'order',\n\t\tlocalField: '_id',\n\t})\n\tpublic flags: Ref<Flag>[];\n\n\t@prop({ type: () => [RiderAssignment], default: [] })\n\triderAssignments: RiderAssignment[];\n\n\t@prop()\n\testimatedPickupTime?: Date;\n\n\t@prop()\n\tactualPickupTime?: Date;\n\n\t@prop()\n\testimatedPickupArrivalTime?: Date;\n\n\t@prop()\n\testimatedPickupArrivalTimeInMinutes?: Number;\n\n\t@prop()\n\tactualPickupArrivalTime?: Date;\n\n\t@prop()\n\tactualPickupArrivalTimeInMinutes?: Number;\n\n\t@prop({ type: Date })\n\triderSearchingStartTime?: Date;\n\n\t@prop({ type: Number, default: 0 })\n\ttotalSearchAttempts?: number;\n\n\t@prop({ type: Number, default: 0 })\n\tlastSearchRadiusInKm?: number;\n\n\t@prop({ type: () => [TripLeg], default: [] })\n\ttripSummary: TripLeg[];\n\n\t@prop({ type: String })\n\timage?: string;\n}\n"]}
1
+ {"version":3,"file":"order.model.js","sourceRoot":"/","sources":["libraries/mongo/models/order.model.ts"],"names":[],"mappings":"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","sourcesContent":["import { index, modelOptions, pre, prop, Ref, Severity } from '@typegoose/typegoose';\nimport { TimeStamps } from '@typegoose/typegoose/lib/defaultClasses';\nimport { CounterType, FlagType, OrderType, UrgentOrderReasons } from '../../../utilities/enum';\nimport { OrderCancel } from './embedded/order-cancel.model';\nimport { Rider } from './rider.model';\nimport { DeliveryFeeInformation } from './embedded/order-delivery-information.model';\nimport { RiderAssignment } from './embedded/rider-assignment-model';\nimport { Flag } from './flag.model';\nimport { Review } from './review.model';\nimport { TripLeg } from './embedded/trip-leg.mode';\nimport { CounterModel } from '.';\nimport { LyxaTimezone } from '../../../utilities/time';\nimport dayjs from 'dayjs';\nimport utc from 'dayjs/plugin/utc';\nimport timezone from 'dayjs/plugin/timezone';\n\ndayjs.extend(utc);\ndayjs.extend(timezone);\n\n@modelOptions({\n\tschemaOptions: {\n\t\tcollection: 'orders',\n\t\tdiscriminatorKey: 'orderType',\n\t\ttoJSON: { virtuals: true },\n\t\ttoObject: { virtuals: true },\n\t},\n\toptions: { allowMixed: Severity.ALLOW },\n})\n@index({ 'deliveryAddress.location': '2dsphere' })\n@index({ user: 1, status: 1, processedAt: -1 })\n@index({ shop: 1, status: 1, processedAt: -1 })\n@index({ parent: 1, status: 1, processedAt: -1 })\n@index({ orderType: 1, status: 1, processedAt: -1 })\n@index({ orderType: 1, status: 1, isEndorseLossApplied: 1, processedAt: -1 })\n@index({ itemType: 1, status: 1, isEndorseLossApplied: 1, processedAt: -1 })\n@index({ shop: 1, status: 1, isEndorseLossApplied: 1, processedAt: -1 })\n@index({ parent: 1, status: 1, isEndorseLossApplied: 1, processedAt: -1 })\n@index({ rider: 1, status: 1, isEndorseLossApplied: 1, processedAt: -1 })\n@pre<Order>('validate', async function (next) {\n\tif (this.isNew) {\n\t\tconst today = dayjs().tz(LyxaTimezone).format('DDMMYY');\n\n\t\tconst counter = await CounterModel.findOneAndUpdate(\n\t\t\t{ counterType: CounterType.ORDER },\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\t$set: {\n\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\t$cond: [{ $eq: ['$today', today] }, { $add: ['$value', 1] }, 1],\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttoday: today,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\t{ new: true, upsert: true }\n\t\t);\n\n\t\tthis.orderId = `${today}${counter.value.toString().padStart(6, '0')}`;\n\t}\n\tnext();\n})\nexport class Order extends TimeStamps {\n\t@prop({ required: true, type: String, unique: true })\n\tpublic orderId: string;\n\n\t@prop({ type: String, enum: OrderType, default: OrderType.REGULAR })\n\tpublic orderType?: OrderType;\n\n\t@prop({ ref: () => Rider, index: true })\n\tpublic rider?: Ref<Rider>;\n\n\t@prop({ type: () => DeliveryFeeInformation })\n\tpublic deliveryFeeInformation?: DeliveryFeeInformation;\n\n\t@prop({ type: Date })\n\tpublic estimatedDeliveredTime: Date;\n\n\t@prop({ type: Number })\n\tpublic estimatedDeliveredTimeInMinutes: number;\n\n\t@prop({ type: Date })\n\tpublic deliveredAt: Date;\n\n\t@prop({ type: Number })\n\tpublic deliveredTimeInMinutes: number;\n\n\t@prop({ type: String })\n\tpublic instruction?: string;\n\n\t@prop({ type: String })\n\tpublic note?: string;\n\n\t@prop({ type: Date })\n\tpublic scheduledFor?: Date;\n\n\t@prop({ type: Date })\n\tpublic triggerAt?: Date;\n\n\t@prop({ type: Date })\n\tpublic placedAt?: Date;\n\n\t@prop({ type: () => OrderCancel })\n\tpublic orderCancel?: OrderCancel;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isLateOrder?: boolean;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isUrgentOrder?: boolean;\n\n\t@prop({ type: () => [String], enum: UrgentOrderReasons, default: [] })\n\tpublic urgentOrderReason?: UrgentOrderReasons[];\n\n\t@prop({ type: Date, default: new Date() })\n\tpublic processedAt?: Date;\n\n\t@prop({\n\t\ttype: Number,\n\t\trequired: true,\n\t\tmin: 1000,\n\t\tmax: 9999,\n\t\tvalidate: {\n\t\t\tvalidator: (v: number) => Number.isInteger(v),\n\t\t\tmessage: 'Pin code must be an integer',\n\t\t},\n\t})\n\tpublic pinCode!: number;\n\n\t// Review feature\n\t@prop({ type: Boolean, default: false })\n\tpublic isOrderReviewed?: boolean;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isReviewNotificationSent?: boolean;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isLowRated?: boolean;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isResolved?: boolean;\n\n\t@prop({\n\t\tref: () => Review,\n\t\tforeignField: 'order',\n\t\tlocalField: '_id',\n\t})\n\tpublic reviews: Ref<Review>[];\n\n\t// Flag feature\n\t@prop({ type: Boolean, default: false })\n\tpublic isFlagged?: boolean;\n\n\t@prop({ type: [String], enum: FlagType, default: [] })\n\tpublic flagTypes?: FlagType[];\n\n\t@prop({ type: Date })\n\tpublic flaggedAt?: Date;\n\n\t@prop({\n\t\tref: () => Flag,\n\t\tforeignField: 'order',\n\t\tlocalField: '_id',\n\t})\n\tpublic flags: Ref<Flag>[];\n\n\t@prop({ type: () => [RiderAssignment], default: [] })\n\triderAssignments: RiderAssignment[];\n\n\t@prop()\n\testimatedPickupTime?: Date;\n\n\t@prop()\n\tactualPickupTime?: Date;\n\n\t@prop()\n\testimatedPickupArrivalTime?: Date;\n\n\t@prop()\n\testimatedPickupArrivalTimeInMinutes?: Number;\n\n\t@prop()\n\tactualPickupArrivalTime?: Date;\n\n\t@prop()\n\tactualPickupArrivalTimeInMinutes?: Number;\n\n\t@prop({ type: Date })\n\triderSearchingStartTime?: Date;\n\n\t@prop({ type: Number, default: 0 })\n\ttotalSearchAttempts?: number;\n\n\t@prop({ type: Number, default: 0 })\n\tlastSearchRadiusInKm?: number;\n\n\t@prop({ type: () => [TripLeg], default: [] })\n\ttripSummary: TripLeg[];\n\n\t@prop({ type: String })\n\timage?: string;\n}\n"]}
@@ -5,33 +5,24 @@ const index_1 = require("../index");
5
5
  const crypto_1 = require("crypto");
6
6
  const instance_utils_1 = require("../../../utilities/instance.utils");
7
7
  const ws_1 = require("ws");
8
- async function* _createSocketSubscription(options) {
9
- const { eventType, ctx, input } = options;
10
- const registration = index_1.EventFactory.getRegistration(eventType);
8
+ async function* _createSocketSubscription(eventType, opts) {
9
+ const { ctx, input } = opts;
10
+ const entity = { id: ctx.entity.id, type: ctx.entity.type };
11
+ const eventKey = index_1.EventFactory.getSubscriptionKey(eventType, input);
11
12
  const socketId = (0, crypto_1.randomUUID)();
13
+ const socketInfo = { socketId, eventKey, instanceId: (0, instance_utils_1.getInstanceId)() };
12
14
  const localEE = new index_1.LocalEventEmitter(socketId);
13
- const entityId = ctx.entity.id;
14
- const entityType = ctx.entity.type;
15
- const entity = { id: entityId, type: entityType };
16
- const eventKey = index_1.EventFactory.getSubscriptionKey(eventType, input);
17
- const instanceId = (0, instance_utils_1.getInstanceId)();
18
- const socketInfo = { socketId, eventKey, instanceId };
19
- await (0, index_1.connectEntityToSocketEvent)(ctx.entity, socketInfo);
15
+ await (0, index_1.connectEntityToSocketEvent)(entity, socketInfo);
20
16
  index_1.LocalSubs.bind(entity, eventKey, localEE);
21
17
  ctx.signal?.addEventListener('abort', () => {
22
18
  index_1.LocalSubs.unbind(entity, eventKey, localEE);
23
- (0, index_1.disconnectEntityFromSocketEvent)(ctx.entity, socketInfo).catch(console.error);
19
+ (0, index_1.disconnectEntityFromSocketEvent)(entity, socketInfo).catch(console.error);
24
20
  });
25
21
  for await (const [data] of (0, ws_1.on)(localEE.ee, eventKey, { signal: ctx.signal })) {
26
- const payload = data;
27
- yield payload;
22
+ yield data;
28
23
  }
29
24
  }
30
25
  function createSocketSubscriptionAdapter(eventType) {
31
- return (opts) => _createSocketSubscription({
32
- eventType,
33
- ctx: opts.ctx,
34
- input: opts.input,
35
- });
26
+ return (opts) => _createSocketSubscription(eventType, opts);
36
27
  }
37
28
  //# sourceMappingURL=socket-subscription.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"socket-subscription.js","sourceRoot":"/","sources":["libraries/socket/adapters/socket-subscription.ts"],"names":[],"mappings":";;AAiEA,0EAOC;AAvED,oCAQkB;AAClB,mCAAoC;AACpC,sEAAkE;AAClE,2BAAwB;AAmBxB,KAAK,SAAS,CAAC,CAAC,yBAAyB,CACxC,OAAuD;IAEvD,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAE1C,MAAM,YAAY,GAAG,oBAAY,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,IAAA,mBAAU,GAAE,CAAC;IAC9B,MAAM,OAAO,GAAG,IAAI,yBAAiB,CAAC,QAAQ,CAAC,CAAC;IAEhD,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAO,CAAC,EAAE,CAAC;IAChC,MAAM,UAAU,GAAG,GAAG,CAAC,MAAO,CAAC,IAAI,CAAC;IAEpC,MAAM,MAAM,GAAuB,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAEtE,MAAM,QAAQ,GAAG,oBAAY,CAAC,kBAAkB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAEnE,MAAM,UAAU,GAAG,IAAA,8BAAa,GAAE,CAAC;IACnC,MAAM,UAAU,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IAEtD,MAAM,IAAA,kCAA0B,EAAC,GAAG,CAAC,MAAO,EAAE,UAAU,CAAC,CAAC;IAC1D,iBAAS,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAE1C,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;QAC1C,iBAAS,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5C,IAAA,uCAA+B,EAAC,GAAG,CAAC,MAAO,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAGH,IAAI,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,IAAA,OAAE,EAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;QAC7E,MAAM,OAAO,GAAG,IAAW,CAAC;QAC5B,MAAM,OAAO,CAAC;IACf,CAAC;AACF,CAAC;AAED,SAAgB,+BAA+B,CAA6C,SAAqB;IAChH,OAAO,CAAC,IAA2C,EAAE,EAAE,CACtD,yBAAyB,CAAC;QACzB,SAAS;QACT,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,KAAK,EAAE,IAAI,CAAC,KAAK;KACjB,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { SocketEventType } from '../../../utilities/enum';\nimport {\n\tconnectEntityToSocketEvent,\n\tdisconnectEntityFromSocketEvent,\n\tEntitySubscription,\n\tEventFactory,\n\tLocalEventEmitter,\n\tLocalSubs,\n\tOutputFor,\n} from '../index';\nimport { randomUUID } from 'crypto';\nimport { getInstanceId } from '../../../utilities/instance.utils';\nimport { on } from 'ws';\nimport { AuthEntityType } from '../../auth';\n\ninterface _SubscriptionContext {\n\tentity?: { id: string; type: AuthEntityType };\n\tsignal?: AbortSignal;\n}\n\ninterface _SubscriptionOpts<TEventType extends SocketEventType, TInput> {\n\tctx: _SubscriptionContext;\n\tinput: TInput;\n}\n\ninterface _CreateSubscriptionOptions<TEventType extends SocketEventType, TInput> {\n\teventType: TEventType;\n\tctx: _SubscriptionContext;\n\tinput: TInput;\n}\n\nasync function* _createSocketSubscription<TEventType extends SocketEventType, TInput>(\n\toptions: _CreateSubscriptionOptions<TEventType, TInput>\n) {\n\tconst { eventType, ctx, input } = options;\n\n\tconst registration = EventFactory.getRegistration(eventType);\n\tconst socketId = randomUUID();\n\tconst localEE = new LocalEventEmitter(socketId);\n\n\tconst entityId = ctx.entity!.id;\n\tconst entityType = ctx.entity!.type;\n\n\tconst entity: EntitySubscription = { id: entityId, type: entityType };\n\n\tconst eventKey = EventFactory.getSubscriptionKey(eventType, input);\n\n\tconst instanceId = getInstanceId();\n\tconst socketInfo = { socketId, eventKey, instanceId };\n\n\tawait connectEntityToSocketEvent(ctx.entity!, socketInfo);\n\tLocalSubs.bind(entity, eventKey, localEE);\n\n\tctx.signal?.addEventListener('abort', () => {\n\t\tLocalSubs.unbind(entity, eventKey, localEE);\n\t\tdisconnectEntityFromSocketEvent(ctx.entity!, socketInfo).catch(console.error);\n\t});\n\n\ttype Out = OutputFor<TEventType>;\n\tfor await (const [data] of on(localEE.ee, eventKey, { signal: ctx.signal })) {\n\t\tconst payload = data as Out;\n\t\tyield payload;\n\t}\n}\n\nexport function createSocketSubscriptionAdapter<TEventType extends SocketEventType, TInput>(eventType: TEventType) {\n\treturn (opts: _SubscriptionOpts<TEventType, TInput>) =>\n\t\t_createSocketSubscription({\n\t\t\teventType,\n\t\t\tctx: opts.ctx,\n\t\t\tinput: opts.input,\n\t\t});\n}\n\n/**\n * @Example\n * const socketRouterTwo = createTRPCRouter({\n * \tonMessage: createAuthenticatedProcedure({ entityTypes: [AuthEntityType.CRM] })\n * \t\t.input(ChatroomMessageSendSocketInputSchema)\n * \t\t.output(\n * \t\t\tzAsyncIterable({\n * \t\t\t\tyield: ChatroomMessageSendOutputSchema,\n * \t\t\t})\n * \t\t)\n * \t\t.subscription(createSocketSubscriptionAdapter(SocketEventType.CHATROOM_MESSAGE_SEND)),\n * });\n */\n"]}
1
+ {"version":3,"file":"socket-subscription.js","sourceRoot":"/","sources":["libraries/socket/adapters/socket-subscription.ts"],"names":[],"mappings":";;AAuDA,0EAEC;AAxDD,oCAQkB;AAClB,mCAAoC;AACpC,sEAAkE;AAClE,2BAAwB;AAaxB,KAAK,SAAS,CAAC,CAAC,yBAAyB,CACxC,SAAqB,EACrB,IAA2C;IAE3C,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IAC5B,MAAM,MAAM,GAAuB,EAAE,EAAE,EAAE,GAAG,CAAC,MAAO,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,MAAO,CAAC,IAAI,EAAE,CAAC;IAElF,MAAM,QAAQ,GAAG,oBAAY,CAAC,kBAAkB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,IAAA,mBAAU,GAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAA,8BAAa,GAAE,EAAE,CAAC;IAEvE,MAAM,OAAO,GAAG,IAAI,yBAAiB,CAAC,QAAQ,CAAC,CAAC;IAGhD,MAAM,IAAA,kCAA0B,EAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACrD,iBAAS,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAG1C,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;QAC1C,iBAAS,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5C,IAAA,uCAA+B,EAAC,MAAM,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAIH,IAAI,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,IAAA,OAAE,EAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;QAC7E,MAAM,IAAW,CAAC;IACnB,CAAC;AACF,CAAC;AAED,SAAgB,+BAA+B,CAA6C,SAAqB;IAChH,OAAO,CAAC,IAA2C,EAAE,EAAE,CAAC,yBAAyB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AACpG,CAAC","sourcesContent":["import { SocketEventType } from '../../../utilities/enum';\nimport {\n\tconnectEntityToSocketEvent,\n\tdisconnectEntityFromSocketEvent,\n\tEntitySubscription,\n\tEventFactory,\n\tLocalEventEmitter,\n\tLocalSubs,\n\tOutputFor,\n} from '../index';\nimport { randomUUID } from 'crypto';\nimport { getInstanceId } from '../../../utilities/instance.utils';\nimport { on } from 'ws';\nimport { AuthEntityType } from '../../auth';\n\ninterface _SubscriptionContext {\n\tentity?: { id: string; type: AuthEntityType };\n\tsignal?: AbortSignal;\n}\n\ninterface _SubscriptionOpts<TEventType extends SocketEventType, TInput> {\n\tctx: _SubscriptionContext;\n\tinput: TInput;\n}\n\nasync function* _createSocketSubscription<TEventType extends SocketEventType, TInput>(\n\teventType: TEventType,\n\topts: _SubscriptionOpts<TEventType, TInput>\n) {\n\tconst { ctx, input } = opts;\n\tconst entity: EntitySubscription = { id: ctx.entity!.id, type: ctx.entity!.type };\n\n\tconst eventKey = EventFactory.getSubscriptionKey(eventType, input);\n\tconst socketId = randomUUID();\n\tconst socketInfo = { socketId, eventKey, instanceId: getInstanceId() };\n\n\tconst localEE = new LocalEventEmitter(socketId);\n\n\t// Setup: connect to Redis and local registry\n\tawait connectEntityToSocketEvent(entity, socketInfo);\n\tLocalSubs.bind(entity, eventKey, localEE);\n\n\t// Cleanup on abort\n\tctx.signal?.addEventListener('abort', () => {\n\t\tLocalSubs.unbind(entity, eventKey, localEE);\n\t\tdisconnectEntityFromSocketEvent(entity, socketInfo).catch(console.error);\n\t});\n\n\t// Stream events\n\ttype Out = OutputFor<TEventType>;\n\tfor await (const [data] of on(localEE.ee, eventKey, { signal: ctx.signal })) {\n\t\tyield data as Out;\n\t}\n}\n\nexport function createSocketSubscriptionAdapter<TEventType extends SocketEventType, TInput>(eventType: TEventType) {\n\treturn (opts: _SubscriptionOpts<TEventType, TInput>) => _createSocketSubscription(eventType, opts);\n}\n\n/**\n * @Example\n * const socketRouterTwo = createTRPCRouter({\n * \tonMessage: createAuthenticatedProcedure({ entityTypes: [AuthEntityType.CRM] })\n * \t\t.input(ChatroomMessageSendSocketInputSchema)\n * \t\t.output(zAsyncIterable({ yield: ChatroomMessageSendOutputSchema }))\n * \t\t.subscription(createSocketSubscriptionAdapter(SocketEventType.CHATROOM_MESSAGE_SEND)),\n * });\n */\n"]}
@@ -3,3 +3,5 @@ export * from './local-subscription-registry';
3
3
  export * from './socket-event-registry';
4
4
  export * from './zAsyncIterable';
5
5
  export * from './socket-redis-connections';
6
+ export * from './socket-event-publisher';
7
+ export * from './socket-event-consumer';
@@ -19,4 +19,6 @@ __exportStar(require("./local-subscription-registry"), exports);
19
19
  __exportStar(require("./socket-event-registry"), exports);
20
20
  __exportStar(require("./zAsyncIterable"), exports);
21
21
  __exportStar(require("./socket-redis-connections"), exports);
22
+ __exportStar(require("./socket-event-publisher"), exports);
23
+ __exportStar(require("./socket-event-consumer"), exports);
22
24
  //# 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","sourcesContent":["export * from '../BaseSocketEvent';\nexport * from './local-subscription-registry';\nexport * from './socket-event-registry';\nexport * from './zAsyncIterable';\nexport * from './socket-redis-connections';\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,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"]}
@@ -3,14 +3,12 @@ import { EntitySubscription } from './socket-redis-connections';
3
3
  type EventKey = string;
4
4
  type SocketId = string;
5
5
  export declare class LocalEventEmitter {
6
- private _ee;
7
- private _socketId;
6
+ readonly ee: EventEmitter;
7
+ readonly socketId: SocketId;
8
8
  constructor(socketId: SocketId);
9
- get socketId(): string;
10
- get ee(): EventEmitter<[never]>;
11
9
  }
12
10
  declare class LocalSubscriptionRegistry {
13
- private byEntity;
11
+ private listeners;
14
12
  bind(entity: EntitySubscription, eventKey: EventKey, ee: LocalEventEmitter): void;
15
13
  unbind(entity: EntitySubscription, eventKey: EventKey, ee: LocalEventEmitter): void;
16
14
  emit(entity: EntitySubscription, eventKey: EventKey, payload: unknown): void;
@@ -5,63 +5,50 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.LocalSubs = exports.LocalEventEmitter = void 0;
7
7
  const events_1 = __importDefault(require("events"));
8
- function entityKey(entity) {
9
- return entity.type ? `${entity.type}:${entity.id}` : entity.id;
10
- }
8
+ const keyCache = new Map();
9
+ const entityKey = (entity) => {
10
+ const raw = `${entity.type ?? 'default'}:${entity.id}`;
11
+ let cached = keyCache.get(raw);
12
+ if (!cached) {
13
+ cached = raw;
14
+ keyCache.set(raw, cached);
15
+ }
16
+ return cached;
17
+ };
11
18
  class LocalEventEmitter {
12
- _ee;
13
- _socketId;
19
+ ee;
20
+ socketId;
14
21
  constructor(socketId) {
15
- this._ee = new events_1.default();
16
- this._socketId = socketId;
17
- }
18
- get socketId() {
19
- return this._socketId;
20
- }
21
- get ee() {
22
- return this._ee;
22
+ this.ee = new events_1.default();
23
+ this.ee.setMaxListeners(0);
24
+ this.socketId = socketId;
23
25
  }
24
26
  }
25
27
  exports.LocalEventEmitter = LocalEventEmitter;
26
28
  class LocalSubscriptionRegistry {
27
- byEntity = new Map();
29
+ listeners = new Map();
28
30
  bind(entity, eventKey, ee) {
29
- const key = entityKey(entity);
30
- let eventMap = this.byEntity.get(key);
31
- if (!eventMap) {
32
- eventMap = new Map();
33
- this.byEntity.set(key, eventMap);
34
- }
35
- let listenerSet = eventMap.get(eventKey);
31
+ const key = `${entityKey(entity)}:${eventKey}`;
32
+ let listenerSet = this.listeners.get(key);
36
33
  if (!listenerSet) {
37
34
  listenerSet = new Set();
38
- eventMap.set(eventKey, listenerSet);
35
+ this.listeners.set(key, listenerSet);
39
36
  }
40
37
  listenerSet.add(ee);
41
- console.log(`[LocalSubs] Bound ${key} -> ${eventKey}, socket=${ee.socketId}`);
42
38
  }
43
39
  unbind(entity, eventKey, ee) {
44
- const key = entityKey(entity);
45
- const eventMap = this.byEntity.get(key);
46
- if (!eventMap)
47
- return;
48
- const listenerSet = eventMap.get(eventKey);
40
+ const key = `${entityKey(entity)}:${eventKey}`;
41
+ const listenerSet = this.listeners.get(key);
49
42
  if (listenerSet) {
50
43
  listenerSet.delete(ee);
51
- if (listenerSet.size === 0)
52
- eventMap.delete(eventKey);
44
+ if (listenerSet.size === 0) {
45
+ this.listeners.delete(key);
46
+ }
53
47
  }
54
- if (eventMap.size === 0)
55
- this.byEntity.delete(key);
56
- console.log(`[LocalSubs] Unbound ${key} -> ${eventKey}, socket=${ee.socketId}`);
57
48
  }
58
49
  emit(entity, eventKey, payload) {
59
- const key = entityKey(entity);
60
- const eventMap = this.byEntity.get(key);
61
- const listeners = eventMap?.get(eventKey);
62
- console.log('LocalSubs emit called', {
63
- payload,
64
- });
50
+ const key = `${entityKey(entity)}:${eventKey}`;
51
+ const listeners = this.listeners.get(key);
65
52
  if (!listeners)
66
53
  return;
67
54
  for (const listener of listeners) {
@@ -1 +1 @@
1
- {"version":3,"file":"local-subscription-registry.js","sourceRoot":"/","sources":["libraries/socket/core/local-subscription-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import EventEmitter from 'events';\nimport { EntitySubscription } from './socket-redis-connections';\n\ntype EventKey = string;\ntype SocketId = string;\n\n// Utility: create a unique key for each EntitySubscription\nfunction entityKey(entity: EntitySubscription): string {\n\treturn entity.type ? `${entity.type}:${entity.id}` : entity.id;\n}\n\nexport class LocalEventEmitter {\n\tprivate _ee: EventEmitter;\n\tprivate _socketId: SocketId;\n\n\tconstructor(socketId: SocketId) {\n\t\tthis._ee = new EventEmitter();\n\t\tthis._socketId = socketId;\n\t}\n\n\tget socketId() {\n\t\treturn this._socketId;\n\t}\n\n\tget ee() {\n\t\treturn this._ee;\n\t}\n}\n\nclass LocalSubscriptionRegistry {\n\tprivate byEntity = new Map<string, Map<EventKey, Set<LocalEventEmitter>>>();\n\n\tbind(entity: EntitySubscription, eventKey: EventKey, ee: LocalEventEmitter) {\n\t\tconst key = entityKey(entity);\n\t\tlet eventMap = this.byEntity.get(key);\n\t\tif (!eventMap) {\n\t\t\teventMap = new Map();\n\t\t\tthis.byEntity.set(key, eventMap);\n\t\t}\n\n\t\tlet listenerSet = eventMap.get(eventKey);\n\t\tif (!listenerSet) {\n\t\t\tlistenerSet = new Set();\n\t\t\teventMap.set(eventKey, listenerSet);\n\t\t}\n\n\t\tlistenerSet.add(ee);\n\n\t\tconsole.log(`[LocalSubs] Bound ${key} -> ${eventKey}, socket=${ee.socketId}`);\n\t}\n\n\tunbind(entity: EntitySubscription, eventKey: EventKey, ee: LocalEventEmitter) {\n\t\tconst key = entityKey(entity);\n\t\tconst eventMap = this.byEntity.get(key);\n\t\tif (!eventMap) return;\n\n\t\tconst listenerSet = eventMap.get(eventKey);\n\t\tif (listenerSet) {\n\t\t\tlistenerSet.delete(ee);\n\t\t\tif (listenerSet.size === 0) eventMap.delete(eventKey);\n\t\t}\n\t\tif (eventMap.size === 0) this.byEntity.delete(key);\n\n\t\tconsole.log(`[LocalSubs] Unbound ${key} -> ${eventKey}, socket=${ee.socketId}`);\n\t}\n\n\temit(entity: EntitySubscription, eventKey: EventKey, payload: unknown) {\n\t\tconst key = entityKey(entity);\n\t\tconst eventMap = this.byEntity.get(key);\n\t\tconst listeners = eventMap?.get(eventKey);\n\n\t\tconsole.log('LocalSubs emit called', {\n\t\t\tpayload,\n\t\t});\n\n\t\tif (!listeners) return;\n\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 './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"]}
@@ -2,40 +2,49 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.publishSocketEvent = publishSocketEvent;
4
4
  exports.publishNotificationSocketEvent = publishNotificationSocketEvent;
5
- const __1 = require("../../..");
6
5
  const socket_redis_connections_1 = require("./socket-redis-connections");
7
6
  const event_1 = require("../../event");
8
7
  const PushNotificationEvent_1 = require("../PushNotificationEvent");
9
8
  const enum_1 = require("../../../utilities/enum");
10
- async function publishToInstances(recipients, localKey, payload) {
9
+ const PUBLISH_OPTIONS = {
10
+ contentType: 'application/json',
11
+ persistent: true,
12
+ };
13
+ function publishToInstances(recipientsWithInstances, localKey, payload) {
14
+ if (recipientsWithInstances.length === 0)
15
+ return;
11
16
  const channel = (0, event_1.getChannel)();
12
- const redisService = (0, __1.getLibraries)().getRedisService();
13
- const publishOptions = {
14
- contentType: 'application/json',
15
- persistent: true,
16
- };
17
- for (const recipient of recipients) {
18
- const instanceNames = await redisService.getSetMembers((0, socket_redis_connections_1.kEntityInstances)(recipient));
19
- if (!instanceNames.length)
20
- continue;
21
- const messageBuffer = Buffer.from(JSON.stringify({ localKey, payload, recipient }), 'utf8');
22
- for (const instanceName of instanceNames) {
23
- const routingKey = `${event_1.INSTANCE_ROUTE_PREFIX}.${instanceName}`;
24
- channel.publish(event_1.EXCHANGE_NAME, routingKey, messageBuffer, publishOptions);
17
+ const message = { localKey, payload, recipient: null };
18
+ for (let i = 0; i < recipientsWithInstances.length; i++) {
19
+ const { recipient, instances } = recipientsWithInstances[i];
20
+ message.recipient = recipient;
21
+ const messageStr = JSON.stringify(message);
22
+ for (let j = 0; j < instances.length; j++) {
23
+ const routingKey = `${event_1.INSTANCE_ROUTE_PREFIX}.${instances[j]}`;
24
+ try {
25
+ channel.publish(event_1.EXCHANGE_NAME, routingKey, Buffer.from(messageStr, 'utf8'), PUBLISH_OPTIONS);
26
+ }
27
+ catch (error) {
28
+ console.error(`[Socket] Publish failed: ${routingKey}`, error);
29
+ }
25
30
  }
26
31
  }
27
32
  }
28
33
  async function getActiveSubscribedRecipients(recipients, localKey) {
29
- const redisService = (0, __1.getLibraries)().getRedisService();
34
+ if (recipients.length === 0) {
35
+ return { subscribed: [], unsubscribed: [] };
36
+ }
37
+ const batchInput = recipients.map(recipient => ({ entity: recipient, eventKey: localKey }));
38
+ const resultsMap = await (0, socket_redis_connections_1.getEntitySubscriptionInfoBatch)(batchInput);
30
39
  const subscribed = [];
31
40
  const unsubscribed = [];
32
- for (const recipient of recipients) {
33
- const [instanceNames, isSub] = await Promise.all([
34
- redisService.getSetMembers((0, socket_redis_connections_1.kEntityInstances)(recipient)),
35
- (0, socket_redis_connections_1.isEntitySubscribed)(recipient, localKey),
36
- ]);
37
- if (instanceNames.length && isSub) {
38
- subscribed.push(recipient);
41
+ for (let i = 0; i < recipients.length; i++) {
42
+ const recipient = recipients[i];
43
+ const entityKeyStr = `${recipient.type ?? 'default'}:${recipient.id}`;
44
+ const cacheKey = `${entityKeyStr}:${localKey}`;
45
+ const info = resultsMap.get(cacheKey);
46
+ if (info && info.isSubscribed && info.instances.length > 0) {
47
+ subscribed.push({ recipient, instances: info.instances });
39
48
  }
40
49
  else {
41
50
  unsubscribed.push(recipient);
@@ -44,25 +53,43 @@ async function getActiveSubscribedRecipients(recipients, localKey) {
44
53
  return { subscribed, unsubscribed };
45
54
  }
46
55
  async function publishSocketEvent(event, recipients) {
56
+ if (recipients.length === 0)
57
+ return;
47
58
  const localKey = event.getSubscriptionKey();
48
59
  const payload = event.payload();
49
60
  const { subscribed, unsubscribed } = await getActiveSubscribedRecipients(recipients, localKey);
50
61
  if (subscribed.length > 0) {
51
- await publishToInstances(subscribed, localKey, payload);
62
+ publishToInstances(subscribed, localKey, payload);
52
63
  }
53
64
  if (unsubscribed.length > 0) {
54
65
  const notificationEvent = event.notification?.();
55
66
  const pushNotificationEvent = event.pushNotification?.();
56
67
  if (pushNotificationEvent) {
57
- const pushNotificationEvent = new PushNotificationEvent_1.PushNotificationEvent(enum_1.PushNotificationEventType.CHATROOM_MESSAGE_SEND, payload);
58
- await (0, event_1.publishEvent)(pushNotificationEvent);
68
+ (0, event_1.publishEvent)(new PushNotificationEvent_1.PushNotificationEvent(enum_1.PushNotificationEventType.CHATROOM_MESSAGE_SEND, payload)).catch(err => console.error('[Socket] Push failed:', err));
59
69
  }
60
70
  if (notificationEvent) {
61
- await publishNotificationSocketEvent(notificationEvent, unsubscribed);
71
+ publishNotificationSocketEvent(notificationEvent, unsubscribed).catch(err => console.error('[Socket] Notification failed:', err));
62
72
  }
63
73
  }
64
74
  }
65
75
  async function publishNotificationSocketEvent(event, recipients) {
66
- await publishToInstances(recipients, event.getSubscriptionKey(), event.payload());
76
+ if (recipients.length === 0)
77
+ return;
78
+ const eventKey = event.getSubscriptionKey();
79
+ const batchInput = recipients.map(recipient => ({ entity: recipient, eventKey }));
80
+ const resultsMap = await (0, socket_redis_connections_1.getEntitySubscriptionInfoBatch)(batchInput);
81
+ const validInstances = [];
82
+ for (let i = 0; i < recipients.length; i++) {
83
+ const recipient = recipients[i];
84
+ const entityKeyStr = `${recipient.type ?? 'default'}:${recipient.id}`;
85
+ const cacheKey = `${entityKeyStr}:${eventKey}`;
86
+ const info = resultsMap.get(cacheKey);
87
+ if (info && info.instances.length > 0) {
88
+ validInstances.push({ recipient, instances: info.instances });
89
+ }
90
+ }
91
+ if (validInstances.length > 0) {
92
+ publishToInstances(validInstances, eventKey, event.payload());
93
+ }
67
94
  }
68
95
  //# sourceMappingURL=socket-event-publisher.js.map
@@ -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, isEntitySubscribed, kEntityInstances } from './socket-redis-connections';\nimport { NotificationSocketEvent } from '../events/notification.socket.event';\nimport { EXCHANGE_NAME, getChannel, INSTANCE_ROUTE_PREFIX, publishEvent } from '../../event';\nimport { PushNotificationEvent } from '../PushNotificationEvent';\nimport { PushNotificationEventType } from '../../../utilities/enum';\n\nasync function publishToInstances(\n\trecipients: EntitySubscription[],\n\tlocalKey: string,\n\tpayload: any\n): Promise<void> {\n\tconst channel = getChannel();\n\tconst redisService = getLibraries().getRedisService();\n\n\tconst publishOptions = {\n\t\tcontentType: 'application/json',\n\t\tpersistent: true,\n\t};\n\n\tfor (const recipient of recipients) {\n\t\tconst instanceNames = await redisService.getSetMembers(kEntityInstances(recipient));\n\t\tif (!instanceNames.length) continue;\n\n\t\tconst messageBuffer = Buffer.from(JSON.stringify({ localKey, payload, recipient }), 'utf8');\n\n\t\tfor (const instanceName of instanceNames) {\n\t\t\tconst routingKey = `${INSTANCE_ROUTE_PREFIX}.${instanceName}`;\n\t\t\tchannel.publish(EXCHANGE_NAME, routingKey, messageBuffer, publishOptions);\n\t\t}\n\t}\n}\n\nasync function getActiveSubscribedRecipients(\n\trecipients: EntitySubscription[],\n\tlocalKey: string\n): Promise<{ subscribed: EntitySubscription[]; unsubscribed: EntitySubscription[] }> {\n\tconst redisService = getLibraries().getRedisService();\n\tconst subscribed: EntitySubscription[] = [];\n\tconst unsubscribed: EntitySubscription[] = [];\n\n\tfor (const recipient of recipients) {\n\t\tconst [instanceNames, isSub] = await Promise.all([\n\t\t\tredisService.getSetMembers(kEntityInstances(recipient)),\n\t\t\tisEntitySubscribed(recipient, localKey),\n\t\t]);\n\n\t\tif (instanceNames.length && isSub) {\n\t\t\tsubscribed.push(recipient);\n\t\t} else {\n\t\t\tunsubscribed.push(recipient);\n\t\t}\n\t}\n\n\treturn { subscribed, unsubscribed };\n}\n\nexport async function publishSocketEvent(\n\tevent: BaseSocketEvent<any, any>,\n\trecipients: EntitySubscription[]\n): Promise<void> {\n\tconst localKey = event.getSubscriptionKey();\n\tconst payload = event.payload();\n\n\tconst { subscribed, unsubscribed } = await getActiveSubscribedRecipients(recipients, localKey);\n\n\tif (subscribed.length > 0) {\n\t\tawait publishToInstances(subscribed, localKey, payload);\n\t}\n\n\tif (unsubscribed.length > 0) {\n\t\tconst notificationEvent = event.notification?.();\n\t\tconst pushNotificationEvent = event.pushNotification?.();\n\n\t\tif (pushNotificationEvent) {\n\t\t\tconst pushNotificationEvent = new PushNotificationEvent(\n\t\t\t\tPushNotificationEventType.CHATROOM_MESSAGE_SEND,\n\t\t\t\tpayload\n\t\t\t);\n\n\t\t\tawait publishEvent(pushNotificationEvent);\n\t\t}\n\t\tif (notificationEvent) {\n\t\t\tawait publishNotificationSocketEvent(notificationEvent, unsubscribed);\n\t\t}\n\t}\n}\n\nexport async function publishNotificationSocketEvent(\n\tevent: NotificationSocketEvent,\n\trecipients: EntitySubscription[]\n): Promise<void> {\n\tawait publishToInstances(recipients, event.getSubscriptionKey(), event.payload());\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 { EntitySubscription, getEntitySubscriptionInfo, getEntitySubscriptionInfoBatch } from './socket-redis-connections';\nimport { NotificationSocketEvent } from '../events/notification.socket.event';\nimport { EXCHANGE_NAME, getChannel, INSTANCE_ROUTE_PREFIX, publishEvent } from '../../event';\nimport { PushNotificationEvent } from '../PushNotificationEvent';\nimport { PushNotificationEventType } from '../../../utilities/enum';\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: any\n): void {\n\tif (recipientsWithInstances.length === 0) return;\n\n\tconst channel = getChannel();\n\n\t// Pre-serialize message once\n\tconst message = { localKey, payload, recipient: null as any };\n\t\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\t\t\t\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// Zero-allocation recipient filtering\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\t// Use batch API\n\tconst batchInput = recipients.map(recipient => ({ entity: recipient, eventKey: localKey }));\n\tconst resultsMap = await getEntitySubscriptionInfoBatch(batchInput);\n\n\t// Pre-allocate arrays\n\tconst subscribed: Array<{ recipient: EntitySubscription; instances: string[] }> = [];\n\tconst unsubscribed: EntitySubscription[] = [];\n\n\t// Single pass with minimal allocations\n\tfor (let i = 0; i < recipients.length; i++) {\n\t\tconst recipient = recipients[i];\n\t\tconst entityKeyStr = `${recipient.type ?? 'default'}:${recipient.id}`;\n\t\tconst cacheKey = `${entityKeyStr}:${localKey}`;\n\t\tconst info = resultsMap.get(cacheKey);\n\n\t\tif (info && info.isSubscribed && info.instances.length > 0) {\n\t\t\tsubscribed.push({ recipient, instances: info.instances });\n\t\t} else {\n\t\t\tunsubscribed.push(recipient);\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<any, any>,\n\trecipients: EntitySubscription[]\n): Promise<void> {\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\t// Fire-and-forget: zero blocking\n\tif (subscribed.length > 0) {\n\t\tpublishToInstances(subscribed, localKey, payload);\n\t}\n\n\t// Lazy fallback evaluation - only if needed\n\tif (unsubscribed.length > 0) {\n\t\tconst notificationEvent = event.notification?.();\n\t\tconst pushNotificationEvent = event.pushNotification?.();\n\n\t\t// Fire without awaiting - true fire-and-forget\n\t\tif (pushNotificationEvent) {\n\t\t\tpublishEvent(new PushNotificationEvent(PushNotificationEventType.CHATROOM_MESSAGE_SEND, payload)).catch(\n\t\t\t\terr => console.error('[Socket] Push failed:', err)\n\t\t\t);\n\t\t}\n\n\t\tif (notificationEvent) {\n\t\t\tpublishNotificationSocketEvent(notificationEvent, unsubscribed).catch(err =>\n\t\t\t\tconsole.error('[Socket] Notification failed:', err)\n\t\t\t);\n\t\t}\n\t}\n}\n\n// Zero-overhead notification publish\nexport async function publishNotificationSocketEvent(\n\tevent: NotificationSocketEvent,\n\trecipients: EntitySubscription[]\n): Promise<void> {\n\tif (recipients.length === 0) return;\n\n\tconst eventKey = event.getSubscriptionKey();\n\tconst batchInput = recipients.map(recipient => ({ entity: recipient, eventKey }));\n\tconst resultsMap = await getEntitySubscriptionInfoBatch(batchInput);\n\n\t// Pre-allocate for valid instances\n\tconst validInstances: Array<{ recipient: EntitySubscription; instances: string[] }> = [];\n\n\tfor (let i = 0; i < recipients.length; i++) {\n\t\tconst recipient = recipients[i];\n\t\tconst entityKeyStr = `${recipient.type ?? 'default'}:${recipient.id}`;\n\t\tconst cacheKey = `${entityKeyStr}:${eventKey}`;\n\t\tconst info = resultsMap.get(cacheKey);\n\n\t\tif (info && info.instances.length > 0) {\n\t\t\tvalidInstances.push({ recipient, instances: info.instances });\n\t\t}\n\t}\n\n\tif (validInstances.length > 0) {\n\t\tpublishToInstances(validInstances, eventKey, event.payload());\n\t}\n}\n"]}
@@ -3,18 +3,28 @@ export type EntitySubscription = {
3
3
  id: string;
4
4
  type?: AuthEntityType;
5
5
  };
6
- export declare const kEntityEvents: (entity: EntitySubscription) => string;
7
- export declare const kEntityInstances: (entity: EntitySubscription) => string;
8
- export declare const kEntityConnection: (entityType?: AuthEntityType) => string;
9
6
  export interface SocketRedisEventInformation {
10
7
  eventKey: string;
11
8
  instanceId: string;
12
9
  socketId: string;
13
10
  }
14
11
  export declare function connectEntityToSocketEvent(entity: EntitySubscription, socketRedisEventInformation: SocketRedisEventInformation): Promise<void>;
15
- export declare function getConnectedEntityByType(type: AuthEntityType): Promise<String[]>;
12
+ export declare function getConnectedEntityByType(type: AuthEntityType): Promise<string[]>;
16
13
  export declare function disconnectEntityFromSocketEvent(entity: EntitySubscription, socketRedisEventInformation: SocketRedisEventInformation): Promise<void>;
17
- export declare function isEntitySubscribed(entity: EntitySubscription, eventKey: string): Promise<boolean>;
14
+ export declare function getEntitySubscriptionInfo(entity: EntitySubscription, eventKey: string): Promise<{
15
+ isSubscribed: boolean;
16
+ instances: string[];
17
+ }>;
18
+ export declare function getEntitySubscriptionInfoBatch(entities: Array<{
19
+ entity: EntitySubscription;
20
+ eventKey: string;
21
+ }>): Promise<Map<string, {
22
+ isSubscribed: boolean;
23
+ instances: string[];
24
+ }>>;
18
25
  export declare function isEntityConnected(entity: EntitySubscription): Promise<boolean>;
19
- export declare function getEntitiesSubscribedToEvent(eventKey: string): Promise<EntitySubscription[]>;
20
26
  export declare function disconnectAllEntitiesFromInstance(entityType?: AuthEntityType): Promise<void>;
27
+ export declare function getEventSubscribers(eventKey: string): Promise<EntitySubscription[]>;
28
+ export declare function getEventSubscribersBatch(eventKeys: string[]): Promise<Map<string, EntitySubscription[]>>;
29
+ export declare function getEventSubscribersByType(eventKey: string, entityType: AuthEntityType): Promise<EntitySubscription[]>;
30
+ export declare function getEventSubscriberCount(eventKey: string): Promise<number>;
@@ -1,101 +1,318 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.kEntityConnection = exports.kEntityInstances = exports.kEntityEvents = void 0;
4
3
  exports.connectEntityToSocketEvent = connectEntityToSocketEvent;
5
4
  exports.getConnectedEntityByType = getConnectedEntityByType;
6
5
  exports.disconnectEntityFromSocketEvent = disconnectEntityFromSocketEvent;
7
- exports.isEntitySubscribed = isEntitySubscribed;
6
+ exports.getEntitySubscriptionInfo = getEntitySubscriptionInfo;
7
+ exports.getEntitySubscriptionInfoBatch = getEntitySubscriptionInfoBatch;
8
8
  exports.isEntityConnected = isEntityConnected;
9
- exports.getEntitiesSubscribedToEvent = getEntitiesSubscribedToEvent;
10
9
  exports.disconnectAllEntitiesFromInstance = disconnectAllEntitiesFromInstance;
10
+ exports.getEventSubscribers = getEventSubscribers;
11
+ exports.getEventSubscribersBatch = getEventSubscribersBatch;
12
+ exports.getEventSubscribersByType = getEventSubscribersByType;
13
+ exports.getEventSubscriberCount = getEventSubscriberCount;
11
14
  const __1 = require("../../..");
12
15
  const instance_utils_1 = require("../../../utilities/instance.utils");
13
- const auth_1 = require("../../auth");
14
- const kEntityEvents = (entity) => entity.type ? `socket:events:${entity.type}:${entity.id}` : `socket:events:entity:${entity.id}`;
15
- exports.kEntityEvents = kEntityEvents;
16
- const kEntityInstances = (entity) => entity.type ? `socket:instances:${entity.type}:${entity.id}` : `socket:instances:entity:${entity.id}`;
17
- exports.kEntityInstances = kEntityInstances;
18
- const kEntityConnection = (entityType) => entityType ? `socket:connections:${entityType}` : `socket:connections:all`;
19
- exports.kEntityConnection = kEntityConnection;
16
+ const keyCache = new Map();
17
+ const entityKey = (entity) => {
18
+ const cacheKey = `${entity.type}:${entity.id}`;
19
+ let key = keyCache.get(cacheKey);
20
+ if (!key) {
21
+ key = `${entity.type ?? 'default'}:${entity.id}`;
22
+ keyCache.set(cacheKey, key);
23
+ }
24
+ return key;
25
+ };
26
+ const kEntityEvents = (entity) => `socket:events:${entityKey(entity)}`;
27
+ const kEntityInstances = (entity) => `socket:instances:${entityKey(entity)}`;
28
+ const kEntityConnection = (entityType) => `socket:conn:${entityType ?? 'all'}`;
29
+ const kEventSubscribers = (eventKey) => `socket:event_subs:${eventKey}`;
30
+ class LRUCache {
31
+ cache = new Map();
32
+ maxSize;
33
+ constructor(maxSize = 10000) {
34
+ this.maxSize = maxSize;
35
+ }
36
+ get(key) {
37
+ const value = this.cache.get(key);
38
+ if (value !== undefined) {
39
+ this.cache.delete(key);
40
+ this.cache.set(key, value);
41
+ }
42
+ return value;
43
+ }
44
+ set(key, value) {
45
+ this.cache.delete(key);
46
+ if (this.cache.size >= this.maxSize) {
47
+ const firstKey = this.cache.keys().next().value;
48
+ if (firstKey !== undefined) {
49
+ this.cache.delete(firstKey);
50
+ }
51
+ }
52
+ this.cache.set(key, value);
53
+ }
54
+ delete(key) {
55
+ this.cache.delete(key);
56
+ }
57
+ clear() {
58
+ this.cache.clear();
59
+ }
60
+ }
61
+ const subscriptionCache = new LRUCache(10000);
62
+ const eventSubscribersCache = new LRUCache(5000);
63
+ const CACHE_TTL = 5000;
20
64
  async function connectEntityToSocketEvent(entity, socketRedisEventInformation) {
21
65
  const redis = (0, __1.getLibraries)().getRedisService();
22
- await redis.addToSet((0, exports.kEntityEvents)(entity), JSON.stringify(socketRedisEventInformation));
23
- await redis.addToSet((0, exports.kEntityInstances)(entity), socketRedisEventInformation.instanceId);
24
- await redis.addToSet((0, exports.kEntityConnection)(entity.type), entity.id);
66
+ const entityKeyStr = entityKey(entity);
67
+ const eventData = JSON.stringify(socketRedisEventInformation);
68
+ await Promise.all([
69
+ redis.addToSet(kEntityEvents(entity), eventData),
70
+ redis.addToSet(kEntityInstances(entity), socketRedisEventInformation.instanceId),
71
+ redis.addToSet(kEntityConnection(entity.type), entity.id),
72
+ redis.addToSet(kEventSubscribers(socketRedisEventInformation.eventKey), entityKeyStr),
73
+ ]);
74
+ const cacheKey = `${entityKeyStr}:${socketRedisEventInformation.eventKey}`;
75
+ subscriptionCache.delete(cacheKey);
76
+ eventSubscribersCache.delete(socketRedisEventInformation.eventKey);
25
77
  }
26
78
  async function getConnectedEntityByType(type) {
27
79
  const redis = (0, __1.getLibraries)().getRedisService();
28
- return redis.getSetMembers((0, exports.kEntityConnection)(type));
80
+ return redis.getSetMembers(kEntityConnection(type));
29
81
  }
30
82
  async function disconnectEntityFromSocketEvent(entity, socketRedisEventInformation) {
31
83
  const redis = (0, __1.getLibraries)().getRedisService();
32
- await redis.removeFromSet((0, exports.kEntityEvents)(entity), JSON.stringify(socketRedisEventInformation));
33
- const remainingEvents = (await redis.getSetMembers((0, exports.kEntityEvents)(entity))).map(r => JSON.parse(r));
34
- if (remainingEvents.filter(e => e.instanceId === socketRedisEventInformation.instanceId).length === 0) {
35
- await redis.removeFromSet((0, exports.kEntityInstances)(entity), socketRedisEventInformation.instanceId);
84
+ const eventData = JSON.stringify(socketRedisEventInformation);
85
+ const entityKeyStr = entityKey(entity);
86
+ await redis.removeFromSet(kEntityEvents(entity), eventData);
87
+ const remainingEvents = (await redis.getSetMembers(kEntityEvents(entity))).map(r => JSON.parse(r));
88
+ const hasInstanceEvents = remainingEvents.some(e => e.instanceId === socketRedisEventInformation.instanceId);
89
+ const hasAnyEvents = remainingEvents.length > 0;
90
+ const stillSubscribedToEvent = remainingEvents.some(e => e.eventKey === socketRedisEventInformation.eventKey);
91
+ const cleanupOps = [];
92
+ if (!hasInstanceEvents) {
93
+ cleanupOps.push(redis.removeFromSet(kEntityInstances(entity), socketRedisEventInformation.instanceId));
36
94
  }
37
- if (remainingEvents.length === 0) {
38
- await redis.removeFromSet((0, exports.kEntityConnection)(entity.type), entity.id);
95
+ if (!hasAnyEvents) {
96
+ cleanupOps.push(redis.removeFromSet(kEntityConnection(entity.type), entity.id));
39
97
  }
98
+ if (!stillSubscribedToEvent) {
99
+ cleanupOps.push(redis.removeFromSet(kEventSubscribers(socketRedisEventInformation.eventKey), entityKeyStr));
100
+ }
101
+ if (cleanupOps.length > 0) {
102
+ await Promise.all(cleanupOps);
103
+ }
104
+ const cacheKey = `${entityKeyStr}:${socketRedisEventInformation.eventKey}`;
105
+ subscriptionCache.delete(cacheKey);
106
+ eventSubscribersCache.delete(socketRedisEventInformation.eventKey);
40
107
  }
41
- async function isEntitySubscribed(entity, eventKey) {
42
- const redis = (0, __1.getLibraries)().getRedisService();
43
- const events = await redis.getSetMembers((0, exports.kEntityEvents)(entity));
44
- return events.map(e => JSON.parse(e)).some(e => e.eventKey === eventKey);
45
- }
46
- async function isEntityConnected(entity) {
108
+ async function getEntitySubscriptionInfo(entity, eventKey) {
109
+ const entityKeyStr = entityKey(entity);
110
+ const cacheKey = `${entityKeyStr}:${eventKey}`;
111
+ const cached = subscriptionCache.get(cacheKey);
112
+ if (cached) {
113
+ const age = Date.now() - cached.timestamp;
114
+ if (age < CACHE_TTL) {
115
+ return { isSubscribed: cached.isSubscribed, instances: cached.instances };
116
+ }
117
+ }
47
118
  const redis = (0, __1.getLibraries)().getRedisService();
48
- return redis.isMemberOfSet((0, exports.kEntityConnection)(entity.type), entity.id);
119
+ const [events, instances] = await Promise.all([
120
+ redis.getSetMembers(kEntityEvents(entity)),
121
+ redis.getSetMembers(kEntityInstances(entity)),
122
+ ]);
123
+ let isSubscribed = false;
124
+ for (let i = 0; i < events.length; i++) {
125
+ if (events[i].includes(eventKey)) {
126
+ isSubscribed = true;
127
+ break;
128
+ }
129
+ }
130
+ const result = { isSubscribed, instances };
131
+ subscriptionCache.set(cacheKey, { ...result, timestamp: Date.now() });
132
+ return result;
49
133
  }
50
- async function getEntitiesSubscribedToEvent(eventKey) {
134
+ async function getEntitySubscriptionInfoBatch(entities) {
135
+ if (entities.length === 0)
136
+ return new Map();
51
137
  const redis = (0, __1.getLibraries)().getRedisService();
52
- const subscribers = [];
53
- const allEntityTypes = [
54
- auth_1.AuthEntityType.USER,
55
- auth_1.AuthEntityType.SELLER,
56
- auth_1.AuthEntityType.DELIVERY_BOY,
57
- auth_1.AuthEntityType.CRM,
58
- auth_1.AuthEntityType.VENDOR_PARENT,
59
- auth_1.AuthEntityType.PROFESSIONAL,
60
- undefined,
61
- ];
62
- for (const entityType of allEntityTypes) {
63
- const connectedEntityIds = await redis.getSetMembers((0, exports.kEntityConnection)(entityType));
64
- for (const entityId of connectedEntityIds) {
65
- const entity = { id: entityId, type: entityType };
66
- const isSubscribed = await isEntitySubscribed(entity, eventKey);
67
- if (isSubscribed) {
68
- subscribers.push(entity);
69
- }
138
+ const results = new Map();
139
+ const now = Date.now();
140
+ const uncached = [];
141
+ for (let i = 0; i < entities.length; i++) {
142
+ const { entity, eventKey } = entities[i];
143
+ const cacheKey = `${entityKey(entity)}:${eventKey}`;
144
+ const cached = subscriptionCache.get(cacheKey);
145
+ if (cached && now - cached.timestamp < CACHE_TTL) {
146
+ results.set(cacheKey, { isSubscribed: cached.isSubscribed, instances: cached.instances });
147
+ }
148
+ else {
149
+ uncached.push(entities[i]);
70
150
  }
71
151
  }
72
- return subscribers;
152
+ if (uncached.length === 0)
153
+ return results;
154
+ await Promise.all(uncached.map(async ({ entity, eventKey }) => {
155
+ const [events, instances] = await Promise.all([
156
+ redis.getSetMembers(kEntityEvents(entity)),
157
+ redis.getSetMembers(kEntityInstances(entity)),
158
+ ]);
159
+ let isSubscribed = false;
160
+ for (let i = 0; i < events.length; i++) {
161
+ if (events[i].includes(eventKey)) {
162
+ isSubscribed = true;
163
+ break;
164
+ }
165
+ }
166
+ const cacheKey = `${entityKey(entity)}:${eventKey}`;
167
+ const result = { isSubscribed, instances };
168
+ subscriptionCache.set(cacheKey, { ...result, timestamp: now });
169
+ results.set(cacheKey, result);
170
+ }));
171
+ return results;
172
+ }
173
+ async function isEntityConnected(entity) {
174
+ const redis = (0, __1.getLibraries)().getRedisService();
175
+ return redis.isMemberOfSet(kEntityConnection(entity.type), entity.id);
73
176
  }
74
177
  async function disconnectAllEntitiesFromInstance(entityType) {
75
178
  const instanceId = (0, instance_utils_1.getInstanceId)();
76
179
  const redis = (0, __1.getLibraries)().getRedisService();
77
- const connectedEntities = await redis.getSetMembers((0, exports.kEntityConnection)(entityType));
180
+ const connectedEntities = await redis.getSetMembers(kEntityConnection(entityType));
78
181
  if (!connectedEntities.length)
79
182
  return;
80
- for (const entityId of connectedEntities) {
183
+ const affectedEvents = new Set();
184
+ await Promise.all(connectedEntities.map(async (entityId) => {
81
185
  const entity = { id: entityId, type: entityType };
82
- const allEvents = await redis.getSetMembers((0, exports.kEntityEvents)(entity));
186
+ const allEvents = await redis.getSetMembers(kEntityEvents(entity));
83
187
  if (!allEvents.length)
84
- continue;
85
- const eventsToKeep = allEvents.filter(e => {
86
- const parsed = JSON.parse(e);
87
- return parsed.instanceId !== instanceId;
188
+ return;
189
+ const parsedEvents = allEvents.map(e => ({
190
+ raw: e,
191
+ parsed: JSON.parse(e),
192
+ }));
193
+ const eventsToRemove = parsedEvents.filter(e => e.parsed.instanceId === instanceId);
194
+ if (!eventsToRemove.length)
195
+ return;
196
+ eventsToRemove.forEach(e => affectedEvents.add(e.parsed.eventKey));
197
+ await Promise.all(eventsToRemove.map(e => redis.removeFromSet(kEntityEvents(entity), e.raw)));
198
+ const remainingEvents = parsedEvents.filter(e => !eventsToRemove.includes(e));
199
+ const cleanupOps = [];
200
+ if (!remainingEvents.some(e => e.parsed.instanceId === instanceId)) {
201
+ cleanupOps.push(redis.removeFromSet(kEntityInstances(entity), instanceId));
202
+ }
203
+ if (remainingEvents.length === 0) {
204
+ cleanupOps.push(redis.removeFromSet(kEntityConnection(entityType), entityId));
205
+ }
206
+ const remainingEventKeys = new Set(remainingEvents.map(e => e.parsed.eventKey));
207
+ const removedEventKeys = eventsToRemove
208
+ .map(e => e.parsed.eventKey)
209
+ .filter(key => !remainingEventKeys.has(key));
210
+ removedEventKeys.forEach(eventKey => {
211
+ cleanupOps.push(redis.removeFromSet(kEventSubscribers(eventKey), entityKey(entity)));
88
212
  });
89
- const eventsToRemove = allEvents.filter(e => !eventsToKeep.includes(e));
90
- for (const e of eventsToRemove) {
91
- await redis.removeFromSet((0, exports.kEntityEvents)(entity), e);
213
+ if (cleanupOps.length > 0) {
214
+ await Promise.all(cleanupOps);
215
+ }
216
+ subscriptionCache.delete(entityKey(entity));
217
+ }));
218
+ affectedEvents.forEach(eventKey => eventSubscribersCache.delete(eventKey));
219
+ }
220
+ async function getEventSubscribers(eventKey) {
221
+ const cached = eventSubscribersCache.get(eventKey);
222
+ const now = Date.now();
223
+ if (cached && now - cached.timestamp < CACHE_TTL) {
224
+ return cached.subscribers;
225
+ }
226
+ const redis = (0, __1.getLibraries)().getRedisService();
227
+ const entityKeys = await redis.getSetMembers(kEventSubscribers(eventKey));
228
+ if (entityKeys.length === 0) {
229
+ const empty = [];
230
+ eventSubscribersCache.set(eventKey, { subscribers: empty, timestamp: now });
231
+ return empty;
232
+ }
233
+ const subscribers = new Array(entityKeys.length);
234
+ for (let i = 0; i < entityKeys.length; i++) {
235
+ const colonIndex = entityKeys[i].indexOf(':');
236
+ const type = entityKeys[i].substring(0, colonIndex);
237
+ const id = entityKeys[i].substring(colonIndex + 1);
238
+ subscribers[i] = {
239
+ id,
240
+ type: type === 'default' ? undefined : type,
241
+ };
242
+ }
243
+ eventSubscribersCache.set(eventKey, { subscribers, timestamp: now });
244
+ return subscribers;
245
+ }
246
+ async function getEventSubscribersBatch(eventKeys) {
247
+ const redis = (0, __1.getLibraries)().getRedisService();
248
+ const results = new Map();
249
+ const uncached = [];
250
+ for (const eventKey of eventKeys) {
251
+ const cached = eventSubscribersCache.get(eventKey);
252
+ if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
253
+ results.set(eventKey, cached.subscribers);
254
+ }
255
+ else {
256
+ uncached.push(eventKey);
92
257
  }
93
- if (!eventsToKeep.some(e => JSON.parse(e).instanceId === instanceId)) {
94
- await redis.removeFromSet((0, exports.kEntityInstances)(entity), instanceId);
258
+ }
259
+ if (uncached.length > 0) {
260
+ await Promise.all(uncached.map(async (eventKey) => {
261
+ const entityKeys = await redis.getSetMembers(kEventSubscribers(eventKey));
262
+ const subscribers = entityKeys.map(key => {
263
+ const [type, id] = key.split(':');
264
+ return {
265
+ id,
266
+ type: type === 'default' ? undefined : type,
267
+ };
268
+ });
269
+ eventSubscribersCache.set(eventKey, { subscribers, timestamp: Date.now() });
270
+ results.set(eventKey, subscribers);
271
+ }));
272
+ }
273
+ return results;
274
+ }
275
+ async function getEventSubscribersByType(eventKey, entityType) {
276
+ const cached = eventSubscribersCache.get(eventKey);
277
+ const now = Date.now();
278
+ if (cached && now - cached.timestamp < CACHE_TTL) {
279
+ const filtered = [];
280
+ for (let i = 0; i < cached.subscribers.length; i++) {
281
+ if (cached.subscribers[i].type === entityType) {
282
+ filtered.push(cached.subscribers[i]);
283
+ }
95
284
  }
96
- if (eventsToKeep.length === 0) {
97
- await redis.removeFromSet((0, exports.kEntityConnection)(entityType), entityId);
285
+ return filtered;
286
+ }
287
+ const redis = (0, __1.getLibraries)().getRedisService();
288
+ const entityKeys = await redis.getSetMembers(kEventSubscribers(eventKey));
289
+ const typePrefix = `${entityType}:`;
290
+ const filtered = [];
291
+ const all = [];
292
+ for (let i = 0; i < entityKeys.length; i++) {
293
+ const key = entityKeys[i];
294
+ const colonIndex = key.indexOf(':');
295
+ const type = key.substring(0, colonIndex);
296
+ const id = key.substring(colonIndex + 1);
297
+ const sub = {
298
+ id,
299
+ type: type === 'default' ? undefined : type,
300
+ };
301
+ all.push(sub);
302
+ if (key.startsWith(typePrefix)) {
303
+ filtered.push(sub);
98
304
  }
99
305
  }
306
+ eventSubscribersCache.set(eventKey, { subscribers: all, timestamp: now });
307
+ return filtered;
308
+ }
309
+ async function getEventSubscriberCount(eventKey) {
310
+ const cached = eventSubscribersCache.get(eventKey);
311
+ if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
312
+ return cached.subscribers.length;
313
+ }
314
+ const redis = (0, __1.getLibraries)().getRedisService();
315
+ const members = await redis.getSetMembers(kEventSubscribers(eventKey));
316
+ return members.length;
100
317
  }
101
318
  //# sourceMappingURL=socket-redis-connections.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"socket-redis-connections.js","sourceRoot":"/","sources":["libraries/socket/core/socket-redis-connections.ts"],"names":[],"mappings":"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","sourcesContent":["import { getLibraries } from '../../..';\nimport { getInstanceId } from '../../../utilities/instance.utils';\nimport { AuthEntityType } from '../../auth';\n\nexport type EntitySubscription = {\n\tid: string;\n\ttype?: AuthEntityType;\n};\n\nexport const kEntityEvents = (entity: EntitySubscription) =>\n\tentity.type ? `socket:events:${entity.type}:${entity.id}` : `socket:events:entity:${entity.id}`;\nexport const kEntityInstances = (entity: EntitySubscription) =>\n\tentity.type ? `socket:instances:${entity.type}:${entity.id}` : `socket:instances:entity:${entity.id}`;\nexport const kEntityConnection = (entityType?: AuthEntityType) =>\n\tentityType ? `socket:connections:${entityType}` : `socket:connections:all`;\n\nexport interface SocketRedisEventInformation {\n\teventKey: string;\n\tinstanceId: string;\n\tsocketId: string;\n}\n\nexport async function connectEntityToSocketEvent(\n\tentity: EntitySubscription,\n\tsocketRedisEventInformation: SocketRedisEventInformation\n) {\n\tconst redis = getLibraries().getRedisService();\n\n\tawait redis.addToSet(kEntityEvents(entity), JSON.stringify(socketRedisEventInformation));\n\tawait redis.addToSet(kEntityInstances(entity), socketRedisEventInformation.instanceId);\n\tawait redis.addToSet(kEntityConnection(entity.type), entity.id);\n}\n\nexport async function getConnectedEntityByType(type: AuthEntityType): Promise<String[]> {\n\tconst redis = getLibraries().getRedisService();\n\treturn redis.getSetMembers(kEntityConnection(type));\n}\n\nexport async function disconnectEntityFromSocketEvent(\n\tentity: EntitySubscription,\n\tsocketRedisEventInformation: SocketRedisEventInformation\n) {\n\tconst redis = getLibraries().getRedisService();\n\n\tawait redis.removeFromSet(kEntityEvents(entity), JSON.stringify(socketRedisEventInformation));\n\n\tconst remainingEvents = (await redis.getSetMembers(kEntityEvents(entity))).map(\n\t\tr => JSON.parse(r) as SocketRedisEventInformation\n\t);\n\n\tif (remainingEvents.filter(e => e.instanceId === socketRedisEventInformation.instanceId).length === 0) {\n\t\tawait redis.removeFromSet(kEntityInstances(entity), socketRedisEventInformation.instanceId);\n\t}\n\n\tif (remainingEvents.length === 0) {\n\t\tawait redis.removeFromSet(kEntityConnection(entity.type), entity.id);\n\t}\n}\n\nexport async function isEntitySubscribed(entity: EntitySubscription, eventKey: string): Promise<boolean> {\n\tconst redis = getLibraries().getRedisService();\n\tconst events = await redis.getSetMembers(kEntityEvents(entity));\n\treturn events.map(e => JSON.parse(e) as SocketRedisEventInformation).some(e => e.eventKey === eventKey);\n}\n\nexport async function isEntityConnected(entity: EntitySubscription): Promise<boolean> {\n\tconst redis = getLibraries().getRedisService();\n\treturn redis.isMemberOfSet(kEntityConnection(entity.type), entity.id);\n}\n\nexport async function getEntitiesSubscribedToEvent(eventKey: string): Promise<EntitySubscription[]> {\n\tconst redis = getLibraries().getRedisService();\n\tconst subscribers: EntitySubscription[] = [];\n\n\tconst allEntityTypes = [\n\t\tAuthEntityType.USER,\n\t\tAuthEntityType.SELLER,\n\t\tAuthEntityType.DELIVERY_BOY,\n\t\tAuthEntityType.CRM,\n\t\tAuthEntityType.VENDOR_PARENT,\n\t\tAuthEntityType.PROFESSIONAL,\n\t\tundefined,\n\t];\n\n\tfor (const entityType of allEntityTypes) {\n\t\tconst connectedEntityIds = await redis.getSetMembers(kEntityConnection(entityType));\n\n\t\tfor (const entityId of connectedEntityIds) {\n\t\t\tconst entity: EntitySubscription = { id: entityId, type: entityType };\n\t\t\tconst isSubscribed = await isEntitySubscribed(entity, eventKey);\n\t\t\tif (isSubscribed) {\n\t\t\t\tsubscribers.push(entity);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn subscribers;\n}\n\nexport async function disconnectAllEntitiesFromInstance(entityType?: AuthEntityType) {\n\tconst instanceId = getInstanceId();\n\tconst redis = getLibraries().getRedisService();\n\n\tconst connectedEntities = await redis.getSetMembers(kEntityConnection(entityType));\n\tif (!connectedEntities.length) return;\n\n\tfor (const entityId of connectedEntities) {\n\t\tconst entity: EntitySubscription = { id: entityId, type: entityType };\n\t\tconst allEvents = await redis.getSetMembers(kEntityEvents(entity));\n\t\tif (!allEvents.length) continue;\n\n\t\tconst eventsToKeep = allEvents.filter(e => {\n\t\t\tconst parsed = JSON.parse(e) as SocketRedisEventInformation;\n\t\t\treturn parsed.instanceId !== instanceId;\n\t\t});\n\n\t\tconst eventsToRemove = allEvents.filter(e => !eventsToKeep.includes(e));\n\t\tfor (const e of eventsToRemove) {\n\t\t\tawait redis.removeFromSet(kEntityEvents(entity), e);\n\t\t}\n\n\t\tif (!eventsToKeep.some(e => (JSON.parse(e) as SocketRedisEventInformation).instanceId === instanceId)) {\n\t\t\tawait redis.removeFromSet(kEntityInstances(entity), instanceId);\n\t\t}\n\n\t\tif (eventsToKeep.length === 0) {\n\t\t\tawait redis.removeFromSet(kEntityConnection(entityType), entityId);\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"socket-redis-connections.js","sourceRoot":"/","sources":["libraries/socket/core/socket-redis-connections.ts"],"names":[],"mappings":"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","sourcesContent":["import { getLibraries } from '../../..';\nimport { getInstanceId } from '../../../utilities/instance.utils';\nimport { AuthEntityType } from '../../auth';\n\nexport type EntitySubscription = {\n\tid: string;\n\ttype?: AuthEntityType;\n};\n\nexport interface SocketRedisEventInformation {\n\teventKey: string;\n\tinstanceId: string;\n\tsocketId: string;\n}\n\n// Zero-overhead key generation with memoization\nconst keyCache = new Map<string, string>();\n\nconst entityKey = (entity: EntitySubscription): string => {\n\tconst cacheKey = `${entity.type}:${entity.id}`;\n\tlet key = keyCache.get(cacheKey);\n\tif (!key) {\n\t\tkey = `${entity.type ?? 'default'}:${entity.id}`;\n\t\tkeyCache.set(cacheKey, key);\n\t}\n\treturn key;\n};\n\n// Pre-built key patterns (avoid string concatenation overhead)\nconst kEntityEvents = (entity: EntitySubscription) => `socket:events:${entityKey(entity)}`;\nconst kEntityInstances = (entity: EntitySubscription) => `socket:instances:${entityKey(entity)}`;\nconst kEntityConnection = (entityType?: AuthEntityType) => `socket:conn:${entityType ?? 'all'}`;\nconst kEventSubscribers = (eventKey: string) => `socket:event_subs:${eventKey}`;\n\n// LRU Cache for hot entities (reduces Redis load by 80-90%)\nclass LRUCache<K, V> {\n\tprivate cache = new Map<K, V>();\n\tprivate maxSize: number;\n\n\tconstructor(maxSize = 10000) {\n\t\tthis.maxSize = maxSize;\n\t}\n\n\tget(key: K): V | undefined {\n\t\tconst value = this.cache.get(key);\n\t\tif (value !== undefined) {\n\t\t\t// Move to end (most recently used)\n\t\t\tthis.cache.delete(key);\n\t\t\tthis.cache.set(key, value);\n\t\t}\n\t\treturn value;\n\t}\n\n\tset(key: K, value: V): void {\n\t\t// Remove if exists (will re-add at end)\n\t\tthis.cache.delete(key);\n\n\t\t// Evict oldest if at capacity\n\t\tif (this.cache.size >= this.maxSize) {\n\t\t\tconst firstKey = this.cache.keys().next().value;\n\t\t\tif (firstKey !== undefined) {\n\t\t\t\tthis.cache.delete(firstKey);\n\t\t\t}\n\t\t}\n\n\t\tthis.cache.set(key, value);\n\t}\n\n\tdelete(key: K): void {\n\t\tthis.cache.delete(key);\n\t}\n\n\tclear(): void {\n\t\tthis.cache.clear();\n\t}\n}\n\n// Cache subscription info for 5 seconds (hot path optimization)\nconst subscriptionCache = new LRUCache<string, { isSubscribed: boolean; instances: string[]; timestamp: number }>(\n\t10000\n);\n\n// Cache event subscribers (who's listening to what event)\nconst eventSubscribersCache = new LRUCache<string, { subscribers: EntitySubscription[]; timestamp: number }>(5000);\n\nconst CACHE_TTL = 5000; // 5 seconds\n\nexport async function connectEntityToSocketEvent(\n\tentity: EntitySubscription,\n\tsocketRedisEventInformation: SocketRedisEventInformation\n) {\n\tconst redis = getLibraries().getRedisService();\n\tconst entityKeyStr = entityKey(entity);\n\tconst eventData = JSON.stringify(socketRedisEventInformation);\n\n\t// Single Redis pipeline - all ops in one round-trip\n\tawait Promise.all([\n\t\tredis.addToSet(kEntityEvents(entity), eventData),\n\t\tredis.addToSet(kEntityInstances(entity), socketRedisEventInformation.instanceId),\n\t\tredis.addToSet(kEntityConnection(entity.type), entity.id),\n\t\tredis.addToSet(kEventSubscribers(socketRedisEventInformation.eventKey), entityKeyStr),\n\t]);\n\n\t// Lazy cache invalidation (only if cached)\n\tconst cacheKey = `${entityKeyStr}:${socketRedisEventInformation.eventKey}`;\n\tsubscriptionCache.delete(cacheKey);\n\teventSubscribersCache.delete(socketRedisEventInformation.eventKey);\n}\n\nexport async function getConnectedEntityByType(type: AuthEntityType): Promise<string[]> {\n\tconst redis = getLibraries().getRedisService();\n\treturn redis.getSetMembers(kEntityConnection(type));\n}\n\nexport async function disconnectEntityFromSocketEvent(\n\tentity: EntitySubscription,\n\tsocketRedisEventInformation: SocketRedisEventInformation\n) {\n\tconst redis = getLibraries().getRedisService();\n\tconst eventData = JSON.stringify(socketRedisEventInformation);\n\tconst entityKeyStr = entityKey(entity);\n\n\tawait redis.removeFromSet(kEntityEvents(entity), eventData);\n\n\t// Check remaining events in parallel with removal\n\tconst remainingEvents = (await redis.getSetMembers(kEntityEvents(entity))).map(\n\t\tr => JSON.parse(r) as SocketRedisEventInformation\n\t);\n\n\tconst hasInstanceEvents = remainingEvents.some(e => e.instanceId === socketRedisEventInformation.instanceId);\n\tconst hasAnyEvents = remainingEvents.length > 0;\n\t\n\t// Check if entity still subscribed to this specific event\n\tconst stillSubscribedToEvent = remainingEvents.some(e => e.eventKey === socketRedisEventInformation.eventKey);\n\n\t// Batch cleanup operations\n\tconst cleanupOps = [];\n\tif (!hasInstanceEvents) {\n\t\tcleanupOps.push(redis.removeFromSet(kEntityInstances(entity), socketRedisEventInformation.instanceId));\n\t}\n\tif (!hasAnyEvents) {\n\t\tcleanupOps.push(redis.removeFromSet(kEntityConnection(entity.type), entity.id));\n\t}\n\t// Remove from reverse index if no longer subscribed to this event\n\tif (!stillSubscribedToEvent) {\n\t\tcleanupOps.push(redis.removeFromSet(kEventSubscribers(socketRedisEventInformation.eventKey), entityKeyStr));\n\t}\n\n\tif (cleanupOps.length > 0) {\n\t\tawait Promise.all(cleanupOps);\n\t}\n\n\t// Invalidate caches on disconnection\n\tconst cacheKey = `${entityKeyStr}:${socketRedisEventInformation.eventKey}`;\n\tsubscriptionCache.delete(cacheKey);\n\teventSubscribersCache.delete(socketRedisEventInformation.eventKey);\n}\n\n// Zero-overhead hot path with inline cache check\nexport async function getEntitySubscriptionInfo(\n\tentity: EntitySubscription,\n\teventKey: string\n): Promise<{ isSubscribed: boolean; instances: string[] }> {\n\tconst entityKeyStr = entityKey(entity);\n\tconst cacheKey = `${entityKeyStr}:${eventKey}`;\n\n\t// Inline cache check (avoid function call overhead)\n\tconst cached = subscriptionCache.get(cacheKey);\n\tif (cached) {\n\t\tconst age = Date.now() - cached.timestamp;\n\t\tif (age < CACHE_TTL) {\n\t\t\treturn { isSubscribed: cached.isSubscribed, instances: cached.instances };\n\t\t}\n\t}\n\n\tconst redis = getLibraries().getRedisService();\n\n\t// Single parallel fetch\n\tconst [events, instances] = await Promise.all([\n\t\tredis.getSetMembers(kEntityEvents(entity)),\n\t\tredis.getSetMembers(kEntityInstances(entity)),\n\t]);\n\n\t// Optimized check - early return on first match\n\tlet isSubscribed = false;\n\tfor (let i = 0; i < events.length; i++) {\n\t\tif (events[i].includes(eventKey)) {\n\t\t\tisSubscribed = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Cache for next time\n\tconst result = { isSubscribed, instances };\n\tsubscriptionCache.set(cacheKey, { ...result, timestamp: Date.now() });\n\n\treturn result;\n}\n\n// Ultra-optimized batch with minimal allocations\nexport async function getEntitySubscriptionInfoBatch(\n\tentities: Array<{ entity: EntitySubscription; eventKey: string }>\n): Promise<Map<string, { isSubscribed: boolean; instances: string[] }>> {\n\tif (entities.length === 0) return new Map();\n\n\tconst redis = getLibraries().getRedisService();\n\tconst results = new Map<string, { isSubscribed: boolean; instances: string[] }>();\n\tconst now = Date.now();\n\t\n\t// Pre-allocate uncached array\n\tconst uncached: typeof entities = [];\n\t\n\t// Single pass: check cache and separate\n\tfor (let i = 0; i < entities.length; i++) {\n\t\tconst { entity, eventKey } = entities[i];\n\t\tconst cacheKey = `${entityKey(entity)}:${eventKey}`;\n\t\tconst cached = subscriptionCache.get(cacheKey);\n\n\t\tif (cached && now - cached.timestamp < CACHE_TTL) {\n\t\t\tresults.set(cacheKey, { isSubscribed: cached.isSubscribed, instances: cached.instances });\n\t\t} else {\n\t\t\tuncached.push(entities[i]);\n\t\t}\n\t}\n\n\t// Early return if all cached\n\tif (uncached.length === 0) return results;\n\n\t// Fetch all uncached in parallel\n\tawait Promise.all(\n\t\tuncached.map(async ({ entity, eventKey }) => {\n\t\t\tconst [events, instances] = await Promise.all([\n\t\t\t\tredis.getSetMembers(kEntityEvents(entity)),\n\t\t\t\tredis.getSetMembers(kEntityInstances(entity)),\n\t\t\t]);\n\n\t\t\t// Fast string search instead of JSON parse\n\t\t\tlet isSubscribed = false;\n\t\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\t\tif (events[i].includes(eventKey)) {\n\t\t\t\t\tisSubscribed = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst cacheKey = `${entityKey(entity)}:${eventKey}`;\n\t\t\tconst result = { isSubscribed, instances };\n\n\t\t\tsubscriptionCache.set(cacheKey, { ...result, timestamp: now });\n\t\t\tresults.set(cacheKey, result);\n\t\t})\n\t);\n\n\treturn results;\n}\n\nexport async function isEntityConnected(entity: EntitySubscription): Promise<boolean> {\n\tconst redis = getLibraries().getRedisService();\n\treturn redis.isMemberOfSet(kEntityConnection(entity.type), entity.id);\n}\n\nexport async function disconnectAllEntitiesFromInstance(entityType?: AuthEntityType) {\n\tconst instanceId = getInstanceId();\n\tconst redis = getLibraries().getRedisService();\n\n\tconst connectedEntities = await redis.getSetMembers(kEntityConnection(entityType));\n\tif (!connectedEntities.length) return;\n\n\tconst affectedEvents = new Set<string>();\n\n\t// Process all entities in parallel\n\tawait Promise.all(\n\t\tconnectedEntities.map(async entityId => {\n\t\t\tconst entity: EntitySubscription = { id: entityId, type: entityType };\n\t\t\tconst allEvents = await redis.getSetMembers(kEntityEvents(entity));\n\t\t\tif (!allEvents.length) return;\n\n\t\t\t// Parse once, use many times\n\t\t\tconst parsedEvents = allEvents.map(e => ({\n\t\t\t\traw: e,\n\t\t\t\tparsed: JSON.parse(e) as SocketRedisEventInformation,\n\t\t\t}));\n\n\t\t\tconst eventsToRemove = parsedEvents.filter(e => e.parsed.instanceId === instanceId);\n\t\t\tif (!eventsToRemove.length) return;\n\n\t\t\t// Track events that will be affected\n\t\t\teventsToRemove.forEach(e => affectedEvents.add(e.parsed.eventKey));\n\n\t\t\t// Batch remove events\n\t\t\tawait Promise.all(eventsToRemove.map(e => redis.removeFromSet(kEntityEvents(entity), e.raw)));\n\n\t\t\t// Check if cleanup needed (reuse parsed data)\n\t\t\tconst remainingEvents = parsedEvents.filter(e => !eventsToRemove.includes(e));\n\t\t\tconst cleanupOps = [];\n\n\t\t\tif (!remainingEvents.some(e => e.parsed.instanceId === instanceId)) {\n\t\t\t\tcleanupOps.push(redis.removeFromSet(kEntityInstances(entity), instanceId));\n\t\t\t}\n\n\t\t\tif (remainingEvents.length === 0) {\n\t\t\t\tcleanupOps.push(redis.removeFromSet(kEntityConnection(entityType), entityId));\n\t\t\t}\n\n\t\t\t// Check which events this entity is no longer subscribed to\n\t\t\tconst remainingEventKeys = new Set(remainingEvents.map(e => e.parsed.eventKey));\n\t\t\tconst removedEventKeys = eventsToRemove\n\t\t\t\t.map(e => e.parsed.eventKey)\n\t\t\t\t.filter(key => !remainingEventKeys.has(key));\n\n\t\t\t// Remove from reverse index for events no longer subscribed\n\t\t\tremovedEventKeys.forEach(eventKey => {\n\t\t\t\tcleanupOps.push(redis.removeFromSet(kEventSubscribers(eventKey), entityKey(entity)));\n\t\t\t});\n\n\t\t\tif (cleanupOps.length > 0) {\n\t\t\t\tawait Promise.all(cleanupOps);\n\t\t\t}\n\n\t\t\t// Clear cache for this entity\n\t\t\tsubscriptionCache.delete(entityKey(entity));\n\t\t})\n\t);\n\n\t// Invalidate event subscriber caches for affected events\n\taffectedEvents.forEach(eventKey => eventSubscribersCache.delete(eventKey));\n}\n\n// Zero-allocation hot path for event subscribers\nexport async function getEventSubscribers(eventKey: string): Promise<EntitySubscription[]> {\n\tconst cached = eventSubscribersCache.get(eventKey);\n\tconst now = Date.now();\n\t\n\tif (cached && now - cached.timestamp < CACHE_TTL) {\n\t\treturn cached.subscribers;\n\t}\n\n\tconst redis = getLibraries().getRedisService();\n\tconst entityKeys = await redis.getSetMembers(kEventSubscribers(eventKey));\n\n\tif (entityKeys.length === 0) {\n\t\tconst empty: EntitySubscription[] = [];\n\t\teventSubscribersCache.set(eventKey, { subscribers: empty, timestamp: now });\n\t\treturn empty;\n\t}\n\n\t// Optimized parsing - single pass, no intermediate arrays\n\tconst subscribers: EntitySubscription[] = new Array(entityKeys.length);\n\tfor (let i = 0; i < entityKeys.length; i++) {\n\t\tconst colonIndex = entityKeys[i].indexOf(':');\n\t\tconst type = entityKeys[i].substring(0, colonIndex);\n\t\tconst id = entityKeys[i].substring(colonIndex + 1);\n\t\t\n\t\tsubscribers[i] = {\n\t\t\tid,\n\t\t\ttype: type === 'default' ? undefined : (type as AuthEntityType),\n\t\t};\n\t}\n\n\teventSubscribersCache.set(eventKey, { subscribers, timestamp: now });\n\treturn subscribers;\n}\n\n// ⚡ Batch variant: Get subscribers for multiple events at once\nexport async function getEventSubscribersBatch(\n\teventKeys: string[]\n): Promise<Map<string, EntitySubscription[]>> {\n\tconst redis = getLibraries().getRedisService();\n\tconst results = new Map<string, EntitySubscription[]>();\n\n\t// Separate cached vs uncached\n\tconst uncached: string[] = [];\n\tfor (const eventKey of eventKeys) {\n\t\tconst cached = eventSubscribersCache.get(eventKey);\n\t\tif (cached && Date.now() - cached.timestamp < CACHE_TTL) {\n\t\t\tresults.set(eventKey, cached.subscribers);\n\t\t} else {\n\t\t\tuncached.push(eventKey);\n\t\t}\n\t}\n\n\t// Fetch uncached in parallel\n\tif (uncached.length > 0) {\n\t\tawait Promise.all(\n\t\t\tuncached.map(async eventKey => {\n\t\t\t\tconst entityKeys = await redis.getSetMembers(kEventSubscribers(eventKey));\n\n\t\t\t\tconst subscribers: EntitySubscription[] = entityKeys.map(key => {\n\t\t\t\t\tconst [type, id] = key.split(':');\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid,\n\t\t\t\t\t\ttype: type === 'default' ? undefined : (type as AuthEntityType),\n\t\t\t\t\t};\n\t\t\t\t});\n\n\t\t\t\teventSubscribersCache.set(eventKey, { subscribers, timestamp: Date.now() });\n\t\t\t\tresults.set(eventKey, subscribers);\n\t\t\t})\n\t\t);\n\t}\n\n\treturn results;\n}\n\n// Zero-copy filtered query - inline filtering to avoid double allocation\nexport async function getEventSubscribersByType(\n\teventKey: string,\n\tentityType: AuthEntityType\n): Promise<EntitySubscription[]> {\n\tconst cached = eventSubscribersCache.get(eventKey);\n\tconst now = Date.now();\n\t\n\tif (cached && now - cached.timestamp < CACHE_TTL) {\n\t\t// Fast filter on cached data\n\t\tconst filtered: EntitySubscription[] = [];\n\t\tfor (let i = 0; i < cached.subscribers.length; i++) {\n\t\t\tif (cached.subscribers[i].type === entityType) {\n\t\t\t\tfiltered.push(cached.subscribers[i]);\n\t\t\t}\n\t\t}\n\t\treturn filtered;\n\t}\n\n\t// Fetch and filter in one pass\n\tconst redis = getLibraries().getRedisService();\n\tconst entityKeys = await redis.getSetMembers(kEventSubscribers(eventKey));\n\tconst typePrefix = `${entityType}:`;\n\t\n\tconst filtered: EntitySubscription[] = [];\n\tconst all: EntitySubscription[] = [];\n\t\n\tfor (let i = 0; i < entityKeys.length; i++) {\n\t\tconst key = entityKeys[i];\n\t\tconst colonIndex = key.indexOf(':');\n\t\tconst type = key.substring(0, colonIndex);\n\t\tconst id = key.substring(colonIndex + 1);\n\t\t\n\t\tconst sub: EntitySubscription = {\n\t\t\tid,\n\t\t\ttype: type === 'default' ? undefined : (type as AuthEntityType),\n\t\t};\n\t\t\n\t\tall.push(sub);\n\t\tif (key.startsWith(typePrefix)) {\n\t\t\tfiltered.push(sub);\n\t\t}\n\t}\n\n\t// Cache all subscribers for future calls\n\teventSubscribersCache.set(eventKey, { subscribers: all, timestamp: now });\n\t\n\treturn filtered;\n}\n\n// ⚡ Get subscriber count (fast, check cache or count)\nexport async function getEventSubscriberCount(eventKey: string): Promise<number> {\n\t// Check cache first\n\tconst cached = eventSubscribersCache.get(eventKey);\n\tif (cached && Date.now() - cached.timestamp < CACHE_TTL) {\n\t\treturn cached.subscribers.length;\n\t}\n\n\t// Otherwise fetch and count\n\tconst redis = getLibraries().getRedisService();\n\tconst members = await redis.getSetMembers(kEventSubscribers(eventKey));\n\treturn members.length;\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.2.20
25
+ Version: 1.2.22
26
26
 
27
27
  ## Dependencies
28
28
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyxa.ai/types",
3
- "version": "1.2.20",
3
+ "version": "1.2.22",
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.2.20",
3
+ "version": "1.2.22",
4
4
  "description": "The Core system of the Lyxa services.",
5
5
  "author": "elie <42282499+Internalizable@users.noreply.github.com>",
6
6
  "license": "MIT",