@lyxa.ai/core 1.3.30 → 1.3.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/libraries/mongo/models/embedded/product-snap.model.d.ts +0 -3
- package/dist/libraries/mongo/models/embedded/product-snap.model.js +0 -6
- package/dist/libraries/mongo/models/embedded/product-snap.model.js.map +1 -1
- package/dist/libraries/mongo/models/embedded/service-order-settings.model.js +1 -1
- package/dist/libraries/mongo/models/embedded/service-order-settings.model.js.map +1 -1
- package/dist/libraries/mongo/models/line-item.model.d.ts +2 -0
- package/dist/libraries/mongo/models/line-item.model.js +6 -0
- package/dist/libraries/mongo/models/line-item.model.js.map +1 -1
- package/dist/libraries/socket/adapters/socket-subscription.d.ts +14 -14
- package/dist/libraries/socket/adapters/socket-subscription.js +11 -5
- package/dist/libraries/socket/adapters/socket-subscription.js.map +1 -1
- package/dist/libraries/socket/core/socket-redis-connections.d.ts +5 -1
- package/dist/libraries/socket/core/socket-redis-connections.js +52 -26
- package/dist/libraries/socket/core/socket-redis-connections.js.map +1 -1
- package/dist/types/README.md +1 -1
- package/dist/types/package.json +1 -1
- package/dist/types/utilities/enum.d.ts +4 -0
- package/dist/types/utilities/enum.js +6 -1
- package/dist/types/utilities/enum.js.map +1 -1
- package/dist/utilities/enum.d.ts +4 -0
- package/dist/utilities/enum.js +6 -1
- package/dist/utilities/enum.js.map +1 -1
- package/dist/utilities/pipelines/product-pipeline-stages.js +0 -1
- package/dist/utilities/pipelines/product-pipeline-stages.js.map +1 -1
- package/package.json +1 -1
- package/dist/utilities/start-end-of-day.d.ts +0 -4
- package/dist/utilities/start-end-of-day.js +0 -12
- package/dist/utilities/start-end-of-day.js.map +0 -1
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { Ref } from '@typegoose/typegoose';
|
|
2
1
|
import { PriceOption, ProductType } from '../../../../utilities/enum';
|
|
3
|
-
import { ProductMarketing } from '../product-marketing.model';
|
|
4
2
|
import { PriceBreakdown } from './price-breakdown.model';
|
|
5
3
|
export declare class ProductSnap {
|
|
6
4
|
name: string;
|
|
@@ -15,5 +13,4 @@ export declare class ProductSnap {
|
|
|
15
13
|
isStockEnabled?: boolean;
|
|
16
14
|
stockQuantity?: number;
|
|
17
15
|
orderQuantityLimit?: number;
|
|
18
|
-
productMarketing?: Ref<ProductMarketing>;
|
|
19
16
|
}
|
|
@@ -12,7 +12,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.ProductSnap = void 0;
|
|
13
13
|
const typegoose_1 = require("@typegoose/typegoose");
|
|
14
14
|
const enum_1 = require("../../../../utilities/enum");
|
|
15
|
-
const product_marketing_model_1 = require("../product-marketing.model");
|
|
16
15
|
const price_breakdown_model_1 = require("./price-breakdown.model");
|
|
17
16
|
class ProductSnap {
|
|
18
17
|
name;
|
|
@@ -27,7 +26,6 @@ class ProductSnap {
|
|
|
27
26
|
isStockEnabled;
|
|
28
27
|
stockQuantity;
|
|
29
28
|
orderQuantityLimit;
|
|
30
|
-
productMarketing;
|
|
31
29
|
}
|
|
32
30
|
exports.ProductSnap = ProductSnap;
|
|
33
31
|
__decorate([
|
|
@@ -78,8 +76,4 @@ __decorate([
|
|
|
78
76
|
(0, typegoose_1.prop)({ type: Number, min: 0, max: 999999999 }),
|
|
79
77
|
__metadata("design:type", Number)
|
|
80
78
|
], ProductSnap.prototype, "orderQuantityLimit", void 0);
|
|
81
|
-
__decorate([
|
|
82
|
-
(0, typegoose_1.prop)({ ref: () => product_marketing_model_1.ProductMarketing }),
|
|
83
|
-
__metadata("design:type", Object)
|
|
84
|
-
], ProductSnap.prototype, "productMarketing", void 0);
|
|
85
79
|
//# sourceMappingURL=product-snap.model.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-snap.model.js","sourceRoot":"/","sources":["libraries/mongo/models/embedded/product-snap.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAAiD;AACjD,qDAAsE;
|
|
1
|
+
{"version":3,"file":"product-snap.model.js","sourceRoot":"/","sources":["libraries/mongo/models/embedded/product-snap.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAAiD;AACjD,qDAAsE;AAEtE,mEAAyD;AAEzD,MAAa,WAAW;IAEhB,IAAI,CAAU;IAGd,OAAO,CAAU;IAGjB,WAAW,CAAe;IAG1B,IAAI,CAAU;IAGd,MAAM,CAAY;IAGlB,WAAW,CAAe;IAG1B,eAAe,CAAoB;IAGnC,WAAW,CAAU;IAGrB,eAAe,CAAW;IAG1B,cAAc,CAAW;IAGzB,aAAa,CAAU;IAGvB,kBAAkB,CAAU;CACnC;AApCD,kCAoCC;AAlCO;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;yCAClB;AAGd;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;4CACC;AAGjB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAW,EAAE,CAAC;;gDACT;AAG1B;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;yCACF;AAGd;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;;2CACb;AAGlB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAW,EAAE,CAAC;;gDACT;AAG1B;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,CAAC,sCAAc,CAAC,EAAE,CAAC;;oDACS;AAGnC;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;gDACK;AAGrB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;;oDACP;AAG1B;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;;mDACR;AAGzB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;kDACO;AAGvB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;;uDACZ","sourcesContent":["import { prop, Ref } from '@typegoose/typegoose';\nimport { PriceOption, ProductType } from '../../../../utilities/enum';\nimport { ProductMarketing } from '../product-marketing.model';\nimport { PriceBreakdown } from './price-breakdown.model';\n\nexport class ProductSnap {\n\t@prop({ required: true, type: String })\n\tpublic name!: string;\n\n\t@prop({ type: String })\n\tpublic barcode?: string;\n\n\t@prop({ type: String, enum: ProductType })\n\tpublic productType?: ProductType;\n\n\t@prop({ type: String })\n\tpublic logo?: string;\n\n\t@prop({ type: [String], default: [] })\n\tpublic images?: string[];\n\n\t@prop({ type: String, enum: PriceOption })\n\tpublic priceOption?: PriceOption;\n\n\t@prop({ type: [PriceBreakdown] })\n\tpublic priceBreakdowns?: PriceBreakdown[];\n\n\t@prop({ type: String })\n\tpublic description?: string;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isDrinkIncluded?: boolean;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isStockEnabled?: boolean;\n\n\t@prop({ type: Number })\n\tpublic stockQuantity?: number;\n\n\t@prop({ type: Number, min: 0, max: 999999999 })\n\tpublic orderQuantityLimit?: number;\n}\n"]}
|
|
@@ -51,7 +51,7 @@ __decorate([
|
|
|
51
51
|
__metadata("design:type", Number)
|
|
52
52
|
], ServiceOrderSettings.prototype, "servicePreparationTime", void 0);
|
|
53
53
|
__decorate([
|
|
54
|
-
(0, typegoose_1.prop)({ type: Number, min: 1, max: 60, default:
|
|
54
|
+
(0, typegoose_1.prop)({ type: Number, min: 1, max: 60, default: 14 }),
|
|
55
55
|
__metadata("design:type", Number)
|
|
56
56
|
], ServiceOrderSettings.prototype, "maxAdvanceOrderDay", void 0);
|
|
57
57
|
__decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-order-settings.model.js","sourceRoot":"/","sources":["libraries/mongo/models/embedded/service-order-settings.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAA0D;AAC1D,mFAAkE;AAG3D,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAEzB,gBAAgB,CAAqB;IAOrC,YAAY,CAAS;IAOrB,UAAU,CAAS;IAQnB,sBAAsB,CAAS;IAG/B,kBAAkB,CAAS;IAQ3B,oBAAoB,CAAS;CAIpC,CAAA;AAvCY,oDAAoB;AAEzB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,+CAAe,CAAC,EAAE,CAAC;;8DACI;AAOrC;IALN,IAAA,gBAAI,EAAC;QACL,GAAG,EAAE,EAAE;QACP,GAAG,EAAE,GAAG;QACR,OAAO,EAAE,EAAE;KACX,CAAC;;0DAC0B;AAOrB;IALN,IAAA,gBAAI,EAAC;QACL,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,EAAE;QACP,OAAO,EAAE,CAAC;KACV,CAAC;;wDACwB;AAQnB;IANN,IAAA,gBAAI,EAAC;QACL,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,KAAK;QACV,OAAO,EAAE,GAAG;KACZ,CAAC;;oEACoC;AAG/B;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"service-order-settings.model.js","sourceRoot":"/","sources":["libraries/mongo/models/embedded/service-order-settings.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAA0D;AAC1D,mFAAkE;AAG3D,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAEzB,gBAAgB,CAAqB;IAOrC,YAAY,CAAS;IAOrB,UAAU,CAAS;IAQnB,sBAAsB,CAAS;IAG/B,kBAAkB,CAAS;IAQ3B,oBAAoB,CAAS;CAIpC,CAAA;AAvCY,oDAAoB;AAEzB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,+CAAe,CAAC,EAAE,CAAC;;8DACI;AAOrC;IALN,IAAA,gBAAI,EAAC;QACL,GAAG,EAAE,EAAE;QACP,GAAG,EAAE,GAAG;QACR,OAAO,EAAE,EAAE;KACX,CAAC;;0DAC0B;AAOrB;IALN,IAAA,gBAAI,EAAC;QACL,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,EAAE;QACP,OAAO,EAAE,CAAC;KACV,CAAC;;wDACwB;AAQnB;IANN,IAAA,gBAAI,EAAC;QACL,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,KAAK;QACV,OAAO,EAAE,GAAG;KACZ,CAAC;;oEACoC;AAG/B;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;;gEACnB;AAQ3B;IANN,IAAA,gBAAI,EAAC;QACL,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,GAAG;QACZ,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,IAAI;KACT,CAAC;;kEACkC;+BAnCxB,oBAAoB;IADhC,IAAA,wBAAY,EAAC,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,sBAAsB,EAAE,EAAE,CAAC;GAC3D,oBAAoB,CAuChC","sourcesContent":["import { modelOptions, prop } from '@typegoose/typegoose';\nimport { FrequencyConfig } from './frequency-configuration.model';\n\n@modelOptions({ schemaOptions: { collection: 'serviceOrderSettings' } })\nexport class ServiceOrderSettings {\n\t@prop({ type: () => [FrequencyConfig] })\n\tpublic frequencyConfigs?: FrequencyConfig[];\n\n\t@prop({\n\t\tmin: 30,\n\t\tmax: 120,\n\t\tdefault: 30,\n\t})\n\tpublic slotInterval: number; // minutes\n\n\t@prop({\n\t\tmin: 0,\n\t\tmax: 60,\n\t\tdefault: 0,\n\t})\n\tpublic bufferTime: number; // minutes\n\n\t@prop({\n\t\ttype: Number,\n\t\tmin: 0,\n\t\tmax: 12000,\n\t\tdefault: 180,\n\t})\n\tpublic servicePreparationTime: number; // minutes\n\n\t@prop({ type: Number, min: 1, max: 60, default: 14 })\n\tpublic maxAdvanceOrderDay: number;\n\n\t@prop({\n\t\ttype: Number,\n\t\tdefault: 360,\n\t\tmin: 0,\n\t\tmax: 4320,\n\t})\n\tpublic autoUrgencyTimeLimit: number; // minutes\n\n\n\n}\n"]}
|
|
@@ -12,6 +12,7 @@ import { Category } from './category.model';
|
|
|
12
12
|
import { Marketing } from './marketing.model';
|
|
13
13
|
import { ProductSnap } from './embedded/product-snap.model';
|
|
14
14
|
import { CartParticipant } from './cart-participant.model';
|
|
15
|
+
import { ProductMarketing } from './product-marketing.model';
|
|
15
16
|
export declare class LineItem extends TimeStamps {
|
|
16
17
|
cart: Ref<Cart>;
|
|
17
18
|
user: Ref<User>;
|
|
@@ -22,6 +23,7 @@ export declare class LineItem extends TimeStamps {
|
|
|
22
23
|
product: Ref<Product>;
|
|
23
24
|
productSnap?: ProductSnap;
|
|
24
25
|
marketings?: Ref<Marketing>[];
|
|
26
|
+
productMarketings?: Ref<ProductMarketing>[];
|
|
25
27
|
quantity: number;
|
|
26
28
|
priceOption?: PriceOption;
|
|
27
29
|
priceBreakdown: OrderPriceBreakdown;
|
|
@@ -24,6 +24,7 @@ const category_model_1 = require("./category.model");
|
|
|
24
24
|
const marketing_model_1 = require("./marketing.model");
|
|
25
25
|
const product_snap_model_1 = require("./embedded/product-snap.model");
|
|
26
26
|
const cart_participant_model_1 = require("./cart-participant.model");
|
|
27
|
+
const product_marketing_model_1 = require("./product-marketing.model");
|
|
27
28
|
let LineItem = class LineItem extends defaultClasses_1.TimeStamps {
|
|
28
29
|
cart;
|
|
29
30
|
user;
|
|
@@ -34,6 +35,7 @@ let LineItem = class LineItem extends defaultClasses_1.TimeStamps {
|
|
|
34
35
|
product;
|
|
35
36
|
productSnap;
|
|
36
37
|
marketings;
|
|
38
|
+
productMarketings;
|
|
37
39
|
quantity;
|
|
38
40
|
priceOption;
|
|
39
41
|
priceBreakdown;
|
|
@@ -87,6 +89,10 @@ __decorate([
|
|
|
87
89
|
(0, typegoose_1.prop)({ ref: () => marketing_model_1.Marketing, default: [] }),
|
|
88
90
|
__metadata("design:type", Array)
|
|
89
91
|
], LineItem.prototype, "marketings", void 0);
|
|
92
|
+
__decorate([
|
|
93
|
+
(0, typegoose_1.prop)({ ref: () => product_marketing_model_1.ProductMarketing, default: [] }),
|
|
94
|
+
__metadata("design:type", Array)
|
|
95
|
+
], LineItem.prototype, "productMarketings", void 0);
|
|
90
96
|
__decorate([
|
|
91
97
|
(0, typegoose_1.prop)({ min: 1, default: 1 }),
|
|
92
98
|
__metadata("design:type", Number)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line-item.model.js","sourceRoot":"/","sources":["libraries/mongo/models/line-item.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAA0F;AAC1F,4EAAqE;AACrE,6CAAoC;AACpC,mDAA0C;AAC1C,4EAAuE;AACvE,kDAAgE;AAChE,oFAAyE;AACzE,6CAAoC;AACpC,6CAAoC;AACpC,iDAAwC;AACxC,qDAA4C;AAC5C,uDAA8C;AAC9C,sEAA4D;
|
|
1
|
+
{"version":3,"file":"line-item.model.js","sourceRoot":"/","sources":["libraries/mongo/models/line-item.model.ts"],"names":[],"mappings":"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","sourcesContent":["import { prop, Ref, index, modelOptions, Severity, mongoose } from '@typegoose/typegoose';\nimport { TimeStamps } from '@typegoose/typegoose/lib/defaultClasses';\nimport { Cart } from './cart.model';\nimport { Product } from './product.model';\nimport { OrderPriceBreakdown } from './embedded/price-breakdown.model';\nimport { ItemType, PriceOption } from '../../../utilities/enum';\nimport { LineItemAttribute } from './embedded/line-item-attribute.model';\nimport { User } from './user.model';\nimport { Shop } from './shop.model';\nimport { Parent } from './parent.model';\nimport { Category } from './category.model';\nimport { Marketing } from './marketing.model';\nimport { ProductSnap } from './embedded/product-snap.model';\nimport { CartParticipant } from './cart-participant.model';\nimport { ProductMarketing } from './product-marketing.model';\n\n/**\n * LineItem model - Represents individual items in a cart\n */\n@modelOptions({\n\tschemaOptions: {\n\t\tcollection: 'lineItems',\n\t\ttoJSON: { virtuals: true },\n\t\ttoObject: { virtuals: true },\n\t},\n\toptions: {\n\t\tallowMixed: Severity.ALLOW,\n\t},\n})\n@index({ cart: 1 })\n@index({ cart: 1, user: 1 })\n@index({ product: 1 })\n@index({ lineItemHash: 1 })\n@index({ shop: 1, deletedAt: 1 })\n@index({ shop: 1, createdAt: 1 })\nexport class LineItem extends TimeStamps {\n\t@prop({ required: true, ref: () => Cart })\n\tpublic cart!: Ref<Cart>;\n\n\t@prop({ required: true, ref: () => User })\n\tpublic user!: Ref<User>;\n\n\t@prop({ required: true, ref: () => Shop })\n\tpublic shop!: Ref<Shop>;\n\n\t@prop({ required: true, ref: () => Parent })\n\tpublic parent: Ref<Parent>;\n\n\t@prop({ required: true, type: String, enum: ItemType })\n\tpublic itemType!: ItemType;\n\n\t@prop({ required: true, ref: () => Category })\n\tpublic category!: Ref<Category>;\n\n\t@prop({ required: true, ref: () => Product })\n\tpublic product!: Ref<Product>;\n\n\t@prop({ type: ProductSnap, _id: false })\n\tpublic productSnap?: ProductSnap;\n\n\t@prop({ ref: () => Marketing, default: [] })\n\tpublic marketings?: Ref<Marketing>[];\n\n\t@prop({ ref: () => ProductMarketing, default: [] })\n\tpublic productMarketings?: Ref<ProductMarketing>[];\n\n\t@prop({ min: 1, default: 1 })\n\tpublic quantity: number;\n\n\t@prop({ type: String, enum: PriceOption, default: PriceOption.SINGLE_PRICE })\n\tpublic priceOption?: PriceOption;\n\n\t@prop({ required: true, type: OrderPriceBreakdown })\n\tpublic priceBreakdown: OrderPriceBreakdown;\n\n\t@prop({ type: () => [[LineItemAttribute]], default: [] })\n\tpublic attributes?: LineItemAttribute[][];\n\n\t@prop({ type: () => [String], default: [] })\n\tpublic removedIngredients?: string[];\n\n\t@prop({ type: String })\n\tpublic specialInstructions?: string;\n\n\t@prop({ type: mongoose.Schema.Types.Mixed })\n\tpublic calculationSnap?: Record<string, unknown>;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isAdjusted: boolean;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isPartialAdjusted: boolean;\n\n\t@prop({ type: Boolean })\n\tpublic isCreatedAfterAdjustment?: boolean;\n\n\t@prop({ default: 0 })\n\tpublic adjustedQuantity: number;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isB1G1: boolean;\n\n\t@prop({ type: String })\n\tpublic adjustReason?: string;\n\n\t@prop({ type: String, select: false })\n\tpublic lineItemHash: string;\n\n\t@prop({\n\t\tref: () => CartParticipant,\n\t\tforeignField: 'cart',\n\t\tlocalField: 'cart',\n\t\tjustOne: true,\n\t\tmatch: (doc: LineItem) => ({ user: doc.user }),\n\t})\n\tpublic cartParticipant?: Ref<CartParticipant>;\n}\n"]}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { SocketEventType } from '../../../utilities/enum';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
export declare function createSocketSubscriptionAdapter<TEventType extends SocketEventType, TInput extends InputFor<TEventType>>(eventType: TEventType): (opts:
|
|
2
|
+
import { InputFor } from '../index';
|
|
3
|
+
import { TokenType } from '../../auth';
|
|
4
|
+
import { ProcedureResolverOptions } from '@trpc/server/unstable-core-do-not-import';
|
|
5
|
+
import { EntityContext, LyxaHTTPContext } from '../../trpc/context';
|
|
6
|
+
type optsType<TEventType extends SocketEventType, TInput extends InputFor<TEventType>> = ProcedureResolverOptions<object, LyxaHTTPContext, {
|
|
7
|
+
res: import('http').ServerResponse<import('http').IncomingMessage>;
|
|
8
|
+
tokenType: TokenType | undefined;
|
|
9
|
+
entity: EntityContext | undefined;
|
|
10
|
+
req: import('http').IncomingMessage;
|
|
11
|
+
requestId: string | undefined;
|
|
12
|
+
usedRefreshToken: boolean | undefined;
|
|
13
|
+
tokenRenewed: boolean | undefined;
|
|
14
|
+
}, TInput>;
|
|
15
|
+
export declare function createSocketSubscriptionAdapter<TEventType extends SocketEventType, TInput extends InputFor<TEventType>>(eventType: TEventType): (opts: optsType<TEventType, TInput>) => AsyncGenerator<any, void, unknown>;
|
|
16
16
|
export {};
|
|
@@ -4,21 +4,27 @@ exports.createSocketSubscriptionAdapter = createSocketSubscriptionAdapter;
|
|
|
4
4
|
const index_1 = require("../index");
|
|
5
5
|
const crypto_1 = require("crypto");
|
|
6
6
|
const instance_utils_1 = require("../../../utilities/instance.utils");
|
|
7
|
-
const
|
|
7
|
+
const events_1 = require("events");
|
|
8
8
|
async function* _createSocketSubscription(eventType, opts) {
|
|
9
|
-
const { ctx
|
|
9
|
+
const { ctx } = opts;
|
|
10
|
+
console.log('Options are: ', opts);
|
|
10
11
|
const entity = { id: ctx.entity.id, type: ctx.entity.type };
|
|
11
|
-
const eventKey = index_1.EventFactory.getSubscriptionKey(eventType, input);
|
|
12
|
+
const eventKey = index_1.EventFactory.getSubscriptionKey(eventType, opts.input);
|
|
12
13
|
const socketId = (0, crypto_1.randomUUID)();
|
|
13
14
|
const socketInfo = { socketId, eventKey, instanceId: (0, instance_utils_1.getInstanceId)() };
|
|
14
15
|
const localEE = new index_1.LocalEventEmitter(socketId);
|
|
15
16
|
await (0, index_1.connectEntityToSocketEvent)(entity, socketInfo);
|
|
16
17
|
index_1.LocalSubs.bind(entity, eventKey, localEE);
|
|
17
|
-
|
|
18
|
+
opts.signal?.addEventListener('abort', () => {
|
|
18
19
|
index_1.LocalSubs.unbind(entity, eventKey, localEE);
|
|
19
20
|
(0, index_1.disconnectEntityFromSocketEvent)(entity, socketInfo).catch(console.error);
|
|
21
|
+
console.log('Unsubscribed from event listener:', entity.id, socketId);
|
|
22
|
+
console.log('Abort signal reason:', opts.signal?.reason);
|
|
23
|
+
console.log('Abort signal reason:', opts.signal);
|
|
20
24
|
});
|
|
21
|
-
|
|
25
|
+
yield { _ready: true };
|
|
26
|
+
for await (const [data] of (0, events_1.on)(localEE.ee, eventKey, { signal: opts.signal })) {
|
|
27
|
+
console.log('Yielding event with signal:', opts.signal);
|
|
22
28
|
yield data;
|
|
23
29
|
}
|
|
24
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket-subscription.js","sourceRoot":"/","sources":["libraries/socket/adapters/socket-subscription.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"socket-subscription.js","sourceRoot":"/","sources":["libraries/socket/adapters/socket-subscription.ts"],"names":[],"mappings":";;AAqFA,0EAKC;AAzFD,oCASkB;AAClB,mCAAoC;AACpC,sEAAkE;AAIlE,mCAA4B;AA8B5B,KAAK,SAAS,CAAC,CAAC,yBAAyB,CAGvC,SAAqB,EAAE,IAAkC;IAC1D,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAErB,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IAEnC,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,IAAI,CAAC,KAAK,CAAC,CAAC;IACxE,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,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;QAC3C,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;QACzE,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,MAAM,EAAE,MAAM,EAAE,IAAI,EAAS,CAAC;IAI9B,IAAI,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,IAAA,WAAE,EAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;QAC9E,OAAO,CAAC,GAAG,CAAC,6BAA6B,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACxD,MAAM,IAAW,CAAC;IACnB,CAAC;AACF,CAAC;AAED,SAAgB,+BAA+B,CAG7C,SAAqB;IACtB,OAAO,CAAC,IAAkC,EAAE,EAAE,CAAC,yBAAyB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAC3F,CAAC","sourcesContent":["import { SocketEventType } from '../../../utilities/enum';\nimport {\n\tconnectEntityToSocketEvent,\n\tdisconnectEntityFromSocketEvent,\n\tEntitySubscription,\n\tEventFactory,\n\tInputFor,\n\tLocalEventEmitter,\n\tLocalSubs,\n\tOutputFor,\n} from '../index';\nimport { randomUUID } from 'crypto';\nimport { getInstanceId } from '../../../utilities/instance.utils';\nimport { AuthEntityType, TokenType } from '../../auth';\nimport { ProcedureResolverOptions } from '@trpc/server/unstable-core-do-not-import';\nimport { EntityContext, LyxaHTTPContext } from '../../trpc/context';\nimport { on } from 'events';\n\ntype optsType<\n\tTEventType extends SocketEventType,\n\tTInput extends InputFor<TEventType>,\n> = ProcedureResolverOptions<\n\tobject,\n\tLyxaHTTPContext,\n\t{\n\t\tres: import('http').ServerResponse<import('http').IncomingMessage>;\n\t\ttokenType: TokenType | undefined;\n\t\tentity: EntityContext | undefined;\n\t\treq: import('http').IncomingMessage;\n\t\trequestId: string | undefined;\n\t\tusedRefreshToken: boolean | undefined;\n\t\ttokenRenewed: boolean | undefined;\n\t},\n\tTInput\n>;\n\ninterface _SubscriptionContext {\n\tentity?: { id: string; type: AuthEntityType };\n\tsignal?: AbortSignal;\n}\n\ninterface _SubscriptionOpts<TEventType extends SocketEventType, TInput extends InputFor<TEventType>> {\n\tctx: _SubscriptionContext;\n\tinput: TInput;\n}\n\nasync function* _createSocketSubscription<\n\tTEventType extends SocketEventType,\n\tTInput extends InputFor<TEventType>,\n>(eventType: TEventType, opts: optsType<TEventType, TInput>) {\n\tconst { ctx } = opts;\n\n\tconsole.log('Options are: ', opts);\n\n\tconst entity: EntitySubscription = { id: ctx.entity!.id, type: ctx.entity!.type };\n\n\tconst eventKey = EventFactory.getSubscriptionKey(eventType, opts.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\topts.signal?.addEventListener('abort', () => {\n\t\tLocalSubs.unbind(entity, eventKey, localEE);\n\t\tdisconnectEntityFromSocketEvent(entity, socketInfo).catch(console.error);\n\t\tconsole.log('Unsubscribed from event listener:', entity.id, socketId);\n\t\tconsole.log('Abort signal reason:', opts.signal?.reason);\n\t\tconsole.log('Abort signal reason:', opts.signal);\n\t});\n\n\tyield { _ready: true } as any;\n\n\t// Stream events\n\ttype Out = OutputFor<TEventType>;\n\tfor await (const [data] of on(localEE.ee, eventKey, { signal: opts.signal })) {\n\t\tconsole.log('Yielding event with signal:', opts.signal);\n\t\tyield data as Out;\n\t}\n}\n\nexport function createSocketSubscriptionAdapter<\n\tTEventType extends SocketEventType,\n\tTInput extends InputFor<TEventType>,\n>(eventType: TEventType) {\n\treturn (opts: optsType<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"]}
|
|
@@ -12,7 +12,11 @@ export declare const entityKey: (entity: EntitySubscription) => string;
|
|
|
12
12
|
export declare const getEntityEventSocketsKey: (entity: EntitySubscription, eventKey: string) => string;
|
|
13
13
|
export declare function connectEntityToSocketEvent(entity: EntitySubscription, socketRedisEventInformation: SocketRedisEventInformation): Promise<void>;
|
|
14
14
|
export declare function getConnectedEntityByType(type: AuthEntityType): Promise<string[]>;
|
|
15
|
-
export declare function disconnectEntityFromSocketEvent(entity: EntitySubscription, socketRedisEventInformation: SocketRedisEventInformation): Promise<
|
|
15
|
+
export declare function disconnectEntityFromSocketEvent(entity: EntitySubscription, socketRedisEventInformation: SocketRedisEventInformation): Promise<{
|
|
16
|
+
removed: boolean;
|
|
17
|
+
socketsRemoved: number;
|
|
18
|
+
subscribersRemoved: number;
|
|
19
|
+
}>;
|
|
16
20
|
export declare function getEntitySubscriptionInfo(entity: EntitySubscription, eventKey: string): Promise<{
|
|
17
21
|
isSubscribed: boolean;
|
|
18
22
|
instances: string[];
|
|
@@ -110,34 +110,60 @@ async function getConnectedEntityByType(type) {
|
|
|
110
110
|
async function disconnectEntityFromSocketEvent(entity, socketRedisEventInformation) {
|
|
111
111
|
const redis = (0, __1.getLibraries)().getRedisService();
|
|
112
112
|
const entityKeyStr = (0, exports.entityKey)(entity);
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
113
|
+
const { instanceId, socketId, eventKey } = socketRedisEventInformation;
|
|
114
|
+
const entityEventKey = kEntityEventSockets(entity, eventKey);
|
|
115
|
+
const eventSubsKey = kEventSubscribers(eventKey);
|
|
116
|
+
try {
|
|
117
|
+
const [entitySockets, eventSubs] = await Promise.all([
|
|
118
|
+
redis.getSetMembers(entityEventKey),
|
|
119
|
+
redis.getSetMembers(eventSubsKey),
|
|
120
|
+
]);
|
|
121
|
+
const cleanupOps = [];
|
|
122
|
+
const socketsToRemove = entitySockets.filter(s => {
|
|
123
|
+
try {
|
|
124
|
+
const parsed = JSON.parse(s);
|
|
125
|
+
return parsed.socketId === socketId && parsed.instanceId === instanceId;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
if (socketsToRemove.length > 0) {
|
|
132
|
+
cleanupOps.push(...socketsToRemove.map(s => redis.removeFromSet(entityEventKey, s)));
|
|
133
|
+
}
|
|
134
|
+
const subscribersToRemove = eventSubs.filter(sub => {
|
|
135
|
+
try {
|
|
136
|
+
const parsed = JSON.parse(sub);
|
|
137
|
+
return (parsed.socketId === socketId && parsed.instanceId === instanceId && parsed.entity === entityKeyStr);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
if (subscribersToRemove.length > 0) {
|
|
144
|
+
cleanupOps.push(...subscribersToRemove.map(s => redis.removeFromSet(eventSubsKey, s)));
|
|
145
|
+
}
|
|
146
|
+
if (cleanupOps.length > 0) {
|
|
147
|
+
await Promise.all(cleanupOps);
|
|
148
|
+
}
|
|
149
|
+
const remainingSockets = entitySockets.length - socketsToRemove.length;
|
|
150
|
+
if (remainingSockets === 0) {
|
|
151
|
+
await redis.deleteCachedObject(entityEventKey);
|
|
152
|
+
}
|
|
153
|
+
const cacheKey = `${entityKeyStr}:${eventKey}`;
|
|
154
|
+
subscriptionCache.delete(cacheKey);
|
|
155
|
+
eventSubscribersCache.delete(eventKey);
|
|
156
|
+
console.log(`Disconnected socket ${socketId} from event ${eventKey} of entity ${entity.id}`);
|
|
157
|
+
return {
|
|
158
|
+
removed: socketsToRemove.length > 0 || subscribersToRemove.length > 0,
|
|
159
|
+
socketsRemoved: socketsToRemove.length,
|
|
160
|
+
subscribersRemoved: subscribersToRemove.length,
|
|
161
|
+
};
|
|
134
162
|
}
|
|
135
|
-
|
|
136
|
-
|
|
163
|
+
catch (error) {
|
|
164
|
+
console.error(`Failed to disconnect socket ${socketId} from entity ${entity.id}:`, error);
|
|
165
|
+
throw error;
|
|
137
166
|
}
|
|
138
|
-
const cacheKey = `${entityKeyStr}:${socketRedisEventInformation.eventKey}`;
|
|
139
|
-
subscriptionCache.delete(cacheKey);
|
|
140
|
-
eventSubscribersCache.delete(socketRedisEventInformation.eventKey);
|
|
141
167
|
}
|
|
142
168
|
async function getEntitySubscriptionInfo(entity, eventKey) {
|
|
143
169
|
const entityKeyStr = (0, exports.entityKey)(entity);
|
|
@@ -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';\nimport type { Redis } from 'ioredis';\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\nexport const 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// Ultra-simplified structure: Direct event lookup, no parsing!\nconst kEntityEventSockets = (entity: EntitySubscription, eventKey: string) =>\n\t`socket:entity:${entityKey(entity)}:${eventKey}`;\nconst kEventSubscribers = (eventKey: string) => `socket:event:${eventKey}`;\n\n// Export for use in publisher (avoid duplication)\nexport const getEntityEventSocketsKey = kEntityEventSockets;\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<\n\tstring,\n\t{ isSubscribed: boolean; instances: string[]; timestamp: number }\n>(10000);\n\n// Cache event subscribers (who's listening to what event)\nconst eventSubscribersCache = new LRUCache<string, { subscribers: EntitySubscription[]; timestamp: number }>(\n\t5000\n);\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\n\t// Simple: just store instanceId and socketId\n\tconst socketData = JSON.stringify({\n\t\tinstanceId: socketRedisEventInformation.instanceId,\n\t\tsocketId: socketRedisEventInformation.socketId,\n\t});\n\n\tconst subscriberData = JSON.stringify({\n\t\tentity: entityKeyStr,\n\t\tsocketId: socketRedisEventInformation.socketId,\n\t\tinstanceId: socketRedisEventInformation.instanceId,\n\t});\n\n\t// 2 Redis operations with event-specific key\n\tawait Promise.all([\n\t\tredis.addToSet(kEntityEventSockets(entity, socketRedisEventInformation.eventKey), socketData),\n\t\tredis.addToSet(kEventSubscribers(socketRedisEventInformation.eventKey), subscriberData),\n\t]);\n\n\t// Lazy cache invalidation\n\tconst cacheKey = `${entityKeyStr}:${socketRedisEventInformation.eventKey}`;\n\tsubscriptionCache.delete(cacheKey);\n\teventSubscribersCache.delete(socketRedisEventInformation.eventKey);\n}\n\n// Helper for non-blocking key scanning\nasync function scanKeys(redis: Redis, pattern: string): Promise<string[]> {\n\tconst keys: string[] = [];\n\tlet cursor = '0';\n\tdo {\n\t\t// Scan with count 100 to avoid blocking\n\t\tconst [newCursor, foundKeys] = await redis.scan(cursor, 'MATCH', pattern, 'COUNT', 100);\n\t\tcursor = newCursor;\n\t\tif (foundKeys.length > 0) {\n\t\t\tkeys.push(...foundKeys);\n\t\t}\n\t} while (cursor !== '0');\n\treturn keys;\n}\n\nexport async function getConnectedEntityByType(type: AuthEntityType): Promise<string[]> {\n\tconst redis = getLibraries().getRedisService();\n\t// Use pattern matching via ioredis directly\n\tconst pattern = `socket:entity:${type}:*`;\n\n\t// Use non-blocking scan instead of keys\n\tconst keys = await scanKeys(redis.redisClient, pattern);\n\n\t// Extract entity IDs from keys: socket:entity:type:id:eventKey\n\t// Get unique IDs (since one entity can have multiple event subscriptions)\n\tconst idSet = new Set<string>();\n\tfor (const key of keys) {\n\t\tconst parts = key.split(':');\n\t\tif (parts.length >= 4) {\n\t\t\tidSet.add(parts[3]); // Extract ID from socket:entity:type:id:eventKey\n\t\t}\n\t}\n\treturn Array.from(idSet);\n}\n\nexport async function disconnectEntityFromSocketEvent(\n\tentity: EntitySubscription,\n\tsocketRedisEventInformation: SocketRedisEventInformation\n) {\n\tconst redis = getLibraries().getRedisService();\n\tconst entityKeyStr = entityKey(entity);\n\n\tconst socketData = JSON.stringify({\n\t\tinstanceId: socketRedisEventInformation.instanceId,\n\t\tsocketId: socketRedisEventInformation.socketId,\n\t});\n\n\tconst entityEventKey = kEntityEventSockets(entity, socketRedisEventInformation.eventKey);\n\tconst eventKey = kEventSubscribers(socketRedisEventInformation.eventKey);\n\n\t// Parallel operations for speed\n\tconst [, eventSubscribers] = await Promise.all([\n\t\tredis.removeFromSet(entityEventKey, socketData),\n\t\tredis.getSetMembers(eventKey),\n\t]);\n\n\t// Check remaining sockets AFTER removal (atomic check)\n\tconst remainingSockets = await redis.getSetMembers(entityEventKey);\n\n\t// Remove from event subscribers\n\tconst toRemove = eventSubscribers.find(s => {\n\t\tconst parsed = JSON.parse(s);\n\t\treturn parsed.entity === entityKeyStr && parsed.socketId === socketRedisEventInformation.socketId;\n\t});\n\n\tconst cleanupOps = [];\n\tif (toRemove) {\n\t\tcleanupOps.push(redis.removeFromSet(eventKey, toRemove));\n\t}\n\n\t// If no more sockets for this event, delete the key (safe after atomic check)\n\tif (remainingSockets.length === 0) {\n\t\tcleanupOps.push(redis.deleteCachedObject(entityEventKey));\n\t}\n\n\tif (cleanupOps.length > 0) {\n\t\tawait Promise.all(cleanupOps);\n\t}\n\n\t// Invalidate caches\n\tconst cacheKey = `${entityKeyStr}:${socketRedisEventInformation.eventKey}`;\n\tsubscriptionCache.delete(cacheKey);\n\teventSubscribersCache.delete(socketRedisEventInformation.eventKey);\n}\n\n// Ultra-simple: Direct key lookup, no parsing!\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\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// Direct lookup - event-specific key!\n\tconst sockets = await redis.getSetMembers(kEntityEventSockets(entity, eventKey));\n\n\tconst isSubscribed = sockets.length > 0;\n\tconst instanceSet = new Set<string>();\n\n\t// Extract instances (no filtering needed!)\n\tfor (let i = 0; i < sockets.length; i++) {\n\t\tconst socketInfo = JSON.parse(sockets[i]);\n\t\tinstanceSet.add(socketInfo.instanceId);\n\t}\n\n\tconst instances = Array.from(instanceSet);\n\tconst result = { isSubscribed, instances };\n\tsubscriptionCache.set(cacheKey, { ...result, timestamp: Date.now() });\n\n\treturn result;\n}\n\n// Batch lookup - parallel direct lookups, no parsing/filtering!\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\tconst uncached: typeof entities = [];\n\n\t// Check cache first\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\tif (uncached.length === 0) return results;\n\n\t// Fetch all uncached in parallel - direct event-specific lookups!\n\tawait Promise.all(\n\t\tuncached.map(async ({ entity, eventKey }) => {\n\t\t\tconst sockets = await redis.getSetMembers(kEntityEventSockets(entity, eventKey));\n\n\t\t\tconst isSubscribed = sockets.length > 0;\n\t\t\tconst instanceSet = new Set<string>();\n\n\t\t\t// Just extract instances, no filtering!\n\t\t\tfor (let i = 0; i < sockets.length; i++) {\n\t\t\t\tconst socketInfo = JSON.parse(sockets[i]);\n\t\t\t\tinstanceSet.add(socketInfo.instanceId);\n\t\t\t}\n\n\t\t\tconst cacheKey = `${entityKey(entity)}:${eventKey}`;\n\t\t\tconst result = { isSubscribed, instances: Array.from(instanceSet) };\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, eventKey: string): Promise<boolean> {\n\tconst redis = getLibraries().getRedisService();\n\tconst sockets = await redis.getSetMembers(kEntityEventSockets(entity, eventKey));\n\treturn sockets.length > 0;\n}\n\nexport async function disconnectAllEntitiesFromInstance(entityType?: AuthEntityType) {\n\tconst instanceId = getInstanceId();\n\tconst redis = getLibraries().getRedisService();\n\n\t// Find all entity-event keys matching the pattern\n\tconst pattern = entityType ? `socket:entity:${entityType}:*` : 'socket:entity:*';\n\tconst entityEventKeys = await scanKeys(redis.redisClient, pattern);\n\tif (!entityEventKeys.length) return;\n\n\tconst affectedEvents = new Set<string>();\n\n\t// Use allSettled for resilience - don't fail all if one fails\n\tconst results = await Promise.allSettled(\n\t\tentityEventKeys.map(async (keyPath: string) => {\n\t\t\tconst sockets = await redis.getSetMembers(keyPath);\n\t\t\tif (!sockets.length) return;\n\n\t\t\t// Extract event from key: socket:entity:type:id:eventKey\n\t\t\tconst keyParts = keyPath.split(':');\n\t\t\tconst eventKey = keyParts.slice(4).join(':'); // Handle eventKeys with colons\n\t\t\tconst entityKeyStr = `${keyParts[2]}:${keyParts[3]}`;\n\n\t\t\t// Find sockets from this instance\n\t\t\tconst socketsToRemove = sockets.filter(s => {\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(s);\n\t\t\t\t\treturn parsed.instanceId === instanceId;\n\t\t\t\t} catch {\n\t\t\t\t\treturn false; // Skip malformed data\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (!socketsToRemove.length) return;\n\n\t\t\taffectedEvents.add(eventKey);\n\n\t\t\t// Remove from entity-event key\n\t\t\tawait Promise.all(socketsToRemove.map(s => redis.removeFromSet(keyPath, s)));\n\n\t\t\t// Remove from event subscribers\n\t\t\tconst eventCleanup = [];\n\t\t\tfor (const socketStr of socketsToRemove) {\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(socketStr);\n\t\t\t\t\tconst eventSubs = await redis.getSetMembers(kEventSubscribers(eventKey));\n\t\t\t\t\tconst toRemove = eventSubs.find(s => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst sub = JSON.parse(s);\n\t\t\t\t\t\t\treturn sub.entity === entityKeyStr && sub.socketId === parsed.socketId;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tif (toRemove) {\n\t\t\t\t\t\teventCleanup.push(redis.removeFromSet(kEventSubscribers(eventKey), toRemove));\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`[Socket] Failed to cleanup subscriber for ${eventKey}:`, err);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if this entity-event has any sockets left\n\t\t\tconst remainingSockets = sockets.length - socketsToRemove.length;\n\t\t\tif (remainingSockets === 0) {\n\t\t\t\teventCleanup.push(redis.deleteCachedObject(keyPath));\n\t\t\t}\n\n\t\t\tif (eventCleanup.length > 0) {\n\t\t\t\tawait Promise.all(eventCleanup);\n\t\t\t}\n\n\t\t\t// Clear cache\n\t\t\tsubscriptionCache.delete(`${entityKeyStr}:${eventKey}`);\n\t\t})\n\t);\n\n\t// Log any failures\n\tconst failures = results.filter(r => r.status === 'rejected');\n\tif (failures.length > 0) {\n\t\tconsole.error(`[Socket] ${failures.length} cleanup operations failed during instance disconnect`);\n\t}\n\n\t// Invalidate affected event caches\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\n\tif (cached && now - cached.timestamp < CACHE_TTL) {\n\t\treturn cached.subscribers;\n\t}\n\n\tconst redis = getLibraries().getRedisService();\n\tconst subscriberData = await redis.getSetMembers(kEventSubscribers(eventKey));\n\n\tif (subscriberData.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// Parse subscriber data and extract unique entities\n\tconst entityMap = new Map<string, EntitySubscription>();\n\tfor (let i = 0; i < subscriberData.length; i++) {\n\t\tconst sub = JSON.parse(subscriberData[i]);\n\t\tconst entityKeyStr = sub.entity;\n\n\t\tif (!entityMap.has(entityKeyStr)) {\n\t\t\tconst colonIndex = entityKeyStr.indexOf(':');\n\t\t\tconst type = entityKeyStr.substring(0, colonIndex);\n\t\t\tconst id = entityKeyStr.substring(colonIndex + 1);\n\n\t\t\tentityMap.set(entityKeyStr, {\n\t\t\t\tid,\n\t\t\t\ttype: type === 'default' ? undefined : (type as AuthEntityType),\n\t\t\t});\n\t\t}\n\t}\n\n\tconst subscribers = Array.from(entityMap.values());\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\tconst now = Date.now();\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 && 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 subscriberData = await redis.getSetMembers(kEventSubscribers(eventKey));\n\n\t\t\t\tconst entityMap = new Map<string, EntitySubscription>();\n\t\t\t\tfor (let i = 0; i < subscriberData.length; i++) {\n\t\t\t\t\tconst sub = JSON.parse(subscriberData[i]);\n\t\t\t\t\tconst entityKeyStr = sub.entity;\n\n\t\t\t\t\tif (!entityMap.has(entityKeyStr)) {\n\t\t\t\t\t\tconst colonIndex = entityKeyStr.indexOf(':');\n\t\t\t\t\t\tconst type = entityKeyStr.substring(0, colonIndex);\n\t\t\t\t\t\tconst id = entityKeyStr.substring(colonIndex + 1);\n\n\t\t\t\t\t\tentityMap.set(entityKeyStr, {\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\ttype: type === 'default' ? undefined : (type as AuthEntityType),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst subscribers = Array.from(entityMap.values());\n\t\t\t\teventSubscribersCache.set(eventKey, { subscribers, timestamp: 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\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 subscriberData = await redis.getSetMembers(kEventSubscribers(eventKey));\n\tconst typePrefix = `${entityType}:`;\n\n\tconst filtered: EntitySubscription[] = [];\n\tconst entityMap = new Map<string, EntitySubscription>();\n\n\tfor (let i = 0; i < subscriberData.length; i++) {\n\t\tconst sub = JSON.parse(subscriberData[i]);\n\t\tconst entityKeyStr = sub.entity;\n\n\t\tif (!entityMap.has(entityKeyStr)) {\n\t\t\tconst colonIndex = entityKeyStr.indexOf(':');\n\t\t\tconst type = entityKeyStr.substring(0, colonIndex);\n\t\t\tconst id = entityKeyStr.substring(colonIndex + 1);\n\n\t\t\tconst entity: EntitySubscription = {\n\t\t\t\tid,\n\t\t\t\ttype: type === 'default' ? undefined : (type as AuthEntityType),\n\t\t\t};\n\n\t\t\tentityMap.set(entityKeyStr, entity);\n\n\t\t\tif (entityKeyStr.startsWith(typePrefix)) {\n\t\t\t\tfiltered.push(entity);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Cache all unique subscribers for future calls\n\tconst all = Array.from(entityMap.values());\n\teventSubscribersCache.set(eventKey, { subscribers: all, timestamp: now });\n\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"]}
|
|
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';\nimport type { Redis } from 'ioredis';\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\nexport const 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// Ultra-simplified structure: Direct event lookup, no parsing!\nconst kEntityEventSockets = (entity: EntitySubscription, eventKey: string) =>\n\t`socket:entity:${entityKey(entity)}:${eventKey}`;\nconst kEventSubscribers = (eventKey: string) => `socket:event:${eventKey}`;\n\n// Export for use in publisher (avoid duplication)\nexport const getEntityEventSocketsKey = kEntityEventSockets;\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<\n\tstring,\n\t{ isSubscribed: boolean; instances: string[]; timestamp: number }\n>(10000);\n\n// Cache event subscribers (who's listening to what event)\nconst eventSubscribersCache = new LRUCache<string, { subscribers: EntitySubscription[]; timestamp: number }>(\n\t5000\n);\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\n\t// Simple: just store instanceId and socketId\n\tconst socketData = JSON.stringify({\n\t\tinstanceId: socketRedisEventInformation.instanceId,\n\t\tsocketId: socketRedisEventInformation.socketId,\n\t});\n\n\tconst subscriberData = JSON.stringify({\n\t\tentity: entityKeyStr,\n\t\tsocketId: socketRedisEventInformation.socketId,\n\t\tinstanceId: socketRedisEventInformation.instanceId,\n\t});\n\n\t// 2 Redis operations with event-specific key\n\tawait Promise.all([\n\t\tredis.addToSet(kEntityEventSockets(entity, socketRedisEventInformation.eventKey), socketData),\n\t\tredis.addToSet(kEventSubscribers(socketRedisEventInformation.eventKey), subscriberData),\n\t]);\n\n\t// Lazy cache invalidation\n\tconst cacheKey = `${entityKeyStr}:${socketRedisEventInformation.eventKey}`;\n\tsubscriptionCache.delete(cacheKey);\n\teventSubscribersCache.delete(socketRedisEventInformation.eventKey);\n}\n\n// Helper for non-blocking key scanning\nasync function scanKeys(redis: Redis, pattern: string): Promise<string[]> {\n\tconst keys: string[] = [];\n\tlet cursor = '0';\n\tdo {\n\t\t// Scan with count 100 to avoid blocking\n\t\tconst [newCursor, foundKeys] = await redis.scan(cursor, 'MATCH', pattern, 'COUNT', 100);\n\t\tcursor = newCursor;\n\t\tif (foundKeys.length > 0) {\n\t\t\tkeys.push(...foundKeys);\n\t\t}\n\t} while (cursor !== '0');\n\treturn keys;\n}\n\nexport async function getConnectedEntityByType(type: AuthEntityType): Promise<string[]> {\n\tconst redis = getLibraries().getRedisService();\n\t// Use pattern matching via ioredis directly\n\tconst pattern = `socket:entity:${type}:*`;\n\n\t// Use non-blocking scan instead of keys\n\tconst keys = await scanKeys(redis.redisClient, pattern);\n\n\t// Extract entity IDs from keys: socket:entity:type:id:eventKey\n\t// Get unique IDs (since one entity can have multiple event subscriptions)\n\tconst idSet = new Set<string>();\n\tfor (const key of keys) {\n\t\tconst parts = key.split(':');\n\t\tif (parts.length >= 4) {\n\t\t\tidSet.add(parts[3]); // Extract ID from socket:entity:type:id:eventKey\n\t\t}\n\t}\n\treturn Array.from(idSet);\n}\n\nexport async function disconnectEntityFromSocketEvent(\n\tentity: EntitySubscription,\n\tsocketRedisEventInformation: SocketRedisEventInformation\n) {\n\tconst redis = getLibraries().getRedisService();\n\tconst entityKeyStr = entityKey(entity);\n\tconst { instanceId, socketId, eventKey } = socketRedisEventInformation;\n\n\t// Build the exact keys we need (no pattern matching!)\n\tconst entityEventKey = kEntityEventSockets(entity, eventKey);\n\tconst eventSubsKey = kEventSubscribers(eventKey);\n\n\ttry {\n\t\t// Fetch both sets in parallel\n\t\tconst [entitySockets, eventSubs] = await Promise.all([\n\t\t\tredis.getSetMembers(entityEventKey),\n\t\t\tredis.getSetMembers(eventSubsKey),\n\t\t]);\n\n\t\tconst cleanupOps: Promise<any>[] = [];\n\n\t\t// Find and remove matching sockets from entity-event key\n\t\tconst socketsToRemove = entitySockets.filter(s => {\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(s);\n\t\t\t\treturn parsed.socketId === socketId && parsed.instanceId === instanceId;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\n\t\tif (socketsToRemove.length > 0) {\n\t\t\t// Remove all matching sockets in parallel\n\t\t\tcleanupOps.push(...socketsToRemove.map(s => redis.removeFromSet(entityEventKey, s)));\n\t\t}\n\n\t\t// Find and remove matching subscribers from event subscribers key\n\t\tconst subscribersToRemove = eventSubs.filter(sub => {\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(sub);\n\t\t\t\treturn (\n\t\t\t\t\tparsed.socketId === socketId && parsed.instanceId === instanceId && parsed.entity === entityKeyStr\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\n\t\tif (subscribersToRemove.length > 0) {\n\t\t\tcleanupOps.push(...subscribersToRemove.map(s => redis.removeFromSet(eventSubsKey, s)));\n\t\t}\n\n\t\t// Execute all removals in parallel\n\t\tif (cleanupOps.length > 0) {\n\t\t\tawait Promise.all(cleanupOps);\n\t\t}\n\n\t\t// Check if entity-event key is now empty and delete if so\n\t\tconst remainingSockets = entitySockets.length - socketsToRemove.length;\n\t\tif (remainingSockets === 0) {\n\t\t\tawait redis.deleteCachedObject(entityEventKey);\n\t\t}\n\n\t\t// Invalidate caches\n\t\tconst cacheKey = `${entityKeyStr}:${eventKey}`;\n\t\tsubscriptionCache.delete(cacheKey);\n\t\teventSubscribersCache.delete(eventKey);\n\n\t\tconsole.log(`Disconnected socket ${socketId} from event ${eventKey} of entity ${entity.id}`);\n\n\t\treturn {\n\t\t\tremoved: socketsToRemove.length > 0 || subscribersToRemove.length > 0,\n\t\t\tsocketsRemoved: socketsToRemove.length,\n\t\t\tsubscribersRemoved: subscribersToRemove.length,\n\t\t};\n\t} catch (error) {\n\t\tconsole.error(`Failed to disconnect socket ${socketId} from entity ${entity.id}:`, error);\n\t\tthrow error;\n\t}\n}\n// Ultra-simple: Direct key lookup, no parsing!\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\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// Direct lookup - event-specific key!\n\tconst sockets = await redis.getSetMembers(kEntityEventSockets(entity, eventKey));\n\n\tconst isSubscribed = sockets.length > 0;\n\tconst instanceSet = new Set<string>();\n\n\t// Extract instances (no filtering needed!)\n\tfor (let i = 0; i < sockets.length; i++) {\n\t\tconst socketInfo = JSON.parse(sockets[i]);\n\t\tinstanceSet.add(socketInfo.instanceId);\n\t}\n\n\tconst instances = Array.from(instanceSet);\n\tconst result = { isSubscribed, instances };\n\tsubscriptionCache.set(cacheKey, { ...result, timestamp: Date.now() });\n\n\treturn result;\n}\n\n// Batch lookup - parallel direct lookups, no parsing/filtering!\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\tconst uncached: typeof entities = [];\n\n\t// Check cache first\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\tif (uncached.length === 0) return results;\n\n\t// Fetch all uncached in parallel - direct event-specific lookups!\n\tawait Promise.all(\n\t\tuncached.map(async ({ entity, eventKey }) => {\n\t\t\tconst sockets = await redis.getSetMembers(kEntityEventSockets(entity, eventKey));\n\n\t\t\tconst isSubscribed = sockets.length > 0;\n\t\t\tconst instanceSet = new Set<string>();\n\n\t\t\t// Just extract instances, no filtering!\n\t\t\tfor (let i = 0; i < sockets.length; i++) {\n\t\t\t\tconst socketInfo = JSON.parse(sockets[i]);\n\t\t\t\tinstanceSet.add(socketInfo.instanceId);\n\t\t\t}\n\n\t\t\tconst cacheKey = `${entityKey(entity)}:${eventKey}`;\n\t\t\tconst result = { isSubscribed, instances: Array.from(instanceSet) };\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, eventKey: string): Promise<boolean> {\n\tconst redis = getLibraries().getRedisService();\n\tconst sockets = await redis.getSetMembers(kEntityEventSockets(entity, eventKey));\n\treturn sockets.length > 0;\n}\n\nexport async function disconnectAllEntitiesFromInstance(entityType?: AuthEntityType) {\n\tconst instanceId = getInstanceId();\n\tconst redis = getLibraries().getRedisService();\n\n\t// Find all entity-event keys matching the pattern\n\tconst pattern = entityType ? `socket:entity:${entityType}:*` : 'socket:entity:*';\n\tconst entityEventKeys = await scanKeys(redis.redisClient, pattern);\n\tif (!entityEventKeys.length) return;\n\n\tconst affectedEvents = new Set<string>();\n\n\t// Use allSettled for resilience - don't fail all if one fails\n\tconst results = await Promise.allSettled(\n\t\tentityEventKeys.map(async (keyPath: string) => {\n\t\t\tconst sockets = await redis.getSetMembers(keyPath);\n\t\t\tif (!sockets.length) return;\n\n\t\t\t// Extract event from key: socket:entity:type:id:eventKey\n\t\t\tconst keyParts = keyPath.split(':');\n\t\t\tconst eventKey = keyParts.slice(4).join(':'); // Handle eventKeys with colons\n\t\t\tconst entityKeyStr = `${keyParts[2]}:${keyParts[3]}`;\n\n\t\t\t// Find sockets from this instance\n\t\t\tconst socketsToRemove = sockets.filter(s => {\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(s);\n\t\t\t\t\treturn parsed.instanceId === instanceId;\n\t\t\t\t} catch {\n\t\t\t\t\treturn false; // Skip malformed data\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (!socketsToRemove.length) return;\n\n\t\t\taffectedEvents.add(eventKey);\n\n\t\t\t// Remove from entity-event key\n\t\t\tawait Promise.all(socketsToRemove.map(s => redis.removeFromSet(keyPath, s)));\n\n\t\t\t// Remove from event subscribers\n\t\t\tconst eventCleanup = [];\n\t\t\tfor (const socketStr of socketsToRemove) {\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(socketStr);\n\t\t\t\t\tconst eventSubs = await redis.getSetMembers(kEventSubscribers(eventKey));\n\t\t\t\t\tconst toRemove = eventSubs.find(s => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst sub = JSON.parse(s);\n\t\t\t\t\t\t\treturn sub.entity === entityKeyStr && sub.socketId === parsed.socketId;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tif (toRemove) {\n\t\t\t\t\t\teventCleanup.push(redis.removeFromSet(kEventSubscribers(eventKey), toRemove));\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`[Socket] Failed to cleanup subscriber for ${eventKey}:`, err);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if this entity-event has any sockets left\n\t\t\tconst remainingSockets = sockets.length - socketsToRemove.length;\n\t\t\tif (remainingSockets === 0) {\n\t\t\t\teventCleanup.push(redis.deleteCachedObject(keyPath));\n\t\t\t}\n\n\t\t\tif (eventCleanup.length > 0) {\n\t\t\t\tawait Promise.all(eventCleanup);\n\t\t\t}\n\n\t\t\t// Clear cache\n\t\t\tsubscriptionCache.delete(`${entityKeyStr}:${eventKey}`);\n\t\t})\n\t);\n\n\t// Log any failures\n\tconst failures = results.filter(r => r.status === 'rejected');\n\tif (failures.length > 0) {\n\t\tconsole.error(`[Socket] ${failures.length} cleanup operations failed during instance disconnect`);\n\t}\n\n\t// Invalidate affected event caches\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\n\tif (cached && now - cached.timestamp < CACHE_TTL) {\n\t\treturn cached.subscribers;\n\t}\n\n\tconst redis = getLibraries().getRedisService();\n\tconst subscriberData = await redis.getSetMembers(kEventSubscribers(eventKey));\n\n\tif (subscriberData.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// Parse subscriber data and extract unique entities\n\tconst entityMap = new Map<string, EntitySubscription>();\n\tfor (let i = 0; i < subscriberData.length; i++) {\n\t\tconst sub = JSON.parse(subscriberData[i]);\n\t\tconst entityKeyStr = sub.entity;\n\n\t\tif (!entityMap.has(entityKeyStr)) {\n\t\t\tconst colonIndex = entityKeyStr.indexOf(':');\n\t\t\tconst type = entityKeyStr.substring(0, colonIndex);\n\t\t\tconst id = entityKeyStr.substring(colonIndex + 1);\n\n\t\t\tentityMap.set(entityKeyStr, {\n\t\t\t\tid,\n\t\t\t\ttype: type === 'default' ? undefined : (type as AuthEntityType),\n\t\t\t});\n\t\t}\n\t}\n\n\tconst subscribers = Array.from(entityMap.values());\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\tconst now = Date.now();\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 && 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 subscriberData = await redis.getSetMembers(kEventSubscribers(eventKey));\n\n\t\t\t\tconst entityMap = new Map<string, EntitySubscription>();\n\t\t\t\tfor (let i = 0; i < subscriberData.length; i++) {\n\t\t\t\t\tconst sub = JSON.parse(subscriberData[i]);\n\t\t\t\t\tconst entityKeyStr = sub.entity;\n\n\t\t\t\t\tif (!entityMap.has(entityKeyStr)) {\n\t\t\t\t\t\tconst colonIndex = entityKeyStr.indexOf(':');\n\t\t\t\t\t\tconst type = entityKeyStr.substring(0, colonIndex);\n\t\t\t\t\t\tconst id = entityKeyStr.substring(colonIndex + 1);\n\n\t\t\t\t\t\tentityMap.set(entityKeyStr, {\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\ttype: type === 'default' ? undefined : (type as AuthEntityType),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst subscribers = Array.from(entityMap.values());\n\t\t\t\teventSubscribersCache.set(eventKey, { subscribers, timestamp: 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\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 subscriberData = await redis.getSetMembers(kEventSubscribers(eventKey));\n\tconst typePrefix = `${entityType}:`;\n\n\tconst filtered: EntitySubscription[] = [];\n\tconst entityMap = new Map<string, EntitySubscription>();\n\n\tfor (let i = 0; i < subscriberData.length; i++) {\n\t\tconst sub = JSON.parse(subscriberData[i]);\n\t\tconst entityKeyStr = sub.entity;\n\n\t\tif (!entityMap.has(entityKeyStr)) {\n\t\t\tconst colonIndex = entityKeyStr.indexOf(':');\n\t\t\tconst type = entityKeyStr.substring(0, colonIndex);\n\t\t\tconst id = entityKeyStr.substring(colonIndex + 1);\n\n\t\t\tconst entity: EntitySubscription = {\n\t\t\t\tid,\n\t\t\t\ttype: type === 'default' ? undefined : (type as AuthEntityType),\n\t\t\t};\n\n\t\t\tentityMap.set(entityKeyStr, entity);\n\n\t\t\tif (entityKeyStr.startsWith(typePrefix)) {\n\t\t\t\tfiltered.push(entity);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Cache all unique subscribers for future calls\n\tconst all = Array.from(entityMap.values());\n\teventSubscribersCache.set(eventKey, { subscribers: all, timestamp: now });\n\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"]}
|
package/dist/types/README.md
CHANGED
package/dist/types/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MarketingType = exports.FavouriteType = exports.CouponExpirationReason = exports.CouponType = exports.BobType = exports.BobChannelType = exports.BobModel = exports.BobSettlementStatus = exports.BobSettlementType = exports.BobAccountType = exports.ZoneStatus = exports.FaqAccountType = exports.CounterType = exports.BannerUserType = exports.BannerLinkType = exports.BannerClickType = exports.VendorRole = exports.ShopRole = exports.OnlineStatus = exports.ShopOnlineStatus = exports.ChargeType = exports.ClickType = exports.NotificationAccountType = exports.DishCategory = exports.ProductDietaryType = exports.ShopDietaryType = exports.PriceOption = exports.ProductType = exports.CoreAuthIdentityType = exports.UserAppSectionItemType = exports.UserAppSectionType = exports.AdminLogsUpdatedFieldsType = exports.UpdatedField = exports.GeoLocationType = exports.RatingAccountType = exports.SubscriptionStatus = exports.SubscriptionPackage = exports.PaidCurrency = exports.PaymentStatus = exports.PaymentMethod = exports.ValueType = exports.HolidayWorkStatus = exports.WorkStatus = exports.WeekDay = exports.GlobalItemType = exports.AdjustmentStatus = exports.ItemType = exports.Status = exports.AccountType = exports.AgentLiveStatus = void 0;
|
|
4
4
|
exports.ServiceCartStatus = exports.ChatroomType = exports.UserRef = exports.TicketStatus = exports.TicketType = exports.RewardedToTypeEnum = exports.ReplacementType = exports.ReplacementReason = exports.OrderCanceledBy = exports.LogUser = exports.PayoutStatus = exports.PayoutType = exports.AddRemoveCreditAccountType = exports.SettingsReasonStatus = exports.CancellationReasonTypeEnum = exports.SupportReasonTypeEnum = exports.PlusSettingsPackageType = exports.AddRemoveCreditSettlementType = exports.SettlementType = exports.MediaType = exports.WorkingHourSettingsType = exports.ZoneGeometryType = exports.RiderAssignmentStatus = exports.CourierServiceType = exports.TripLegStatus = exports.DeliveryStatus = exports.CourierOrderPaymentFrom = exports.ShopCourierOrderStatus = exports.ServiceOrderStatus = exports.CourierOrderStatus = exports.RegularOrderStatus = exports.AdjustmentType = exports.StatusTimelineType = exports.OrderType = exports.Language = exports.OrderSize = exports.RiderBagSize = exports.RiderType = exports.ShiftType = exports.CreatedBy = exports.LiveStatus = exports.AreebaCardStatus = exports.CardUserType = exports.CardType = exports.PaymentPreference = exports.CartStatus = exports.AdminRole = exports.PunchMarketingStatus = exports.MarketingStatus = exports.ServiceMarketingType = void 0;
|
|
5
|
-
exports.CalendarViewType = exports.LyxaTimeZoneEnum = exports.UserOrderCompletionScope = exports.GroupCartNotificationStatus = exports.CurrencyType = exports.RequestFrom = exports.UploadState = exports.ServiceType = exports.ActionType = exports.DeviceType = exports.PushNotificationEventType = exports.SocketEventType = exports.SocketServiceQueue = exports.OtpMethodType = exports.ReviewType = exports.FoodNutritionType = exports.AdjustmentReason = exports.UrgentOrderReasons = exports.FlagReasonType = exports.FlagType = exports.PromotionType = exports.ServiceOrderCanceledBy = exports.TRPCErrorEnum = exports.ShopFilterSortByEnum = exports.BookingStatus = exports.ProfessionalScheduleType = exports.ServiceOrderRecurrencePattern = exports.ProfessionalRecurrencePattern = exports.ServiceOrderPriority = exports.ProfessionalStatus = exports.Service = void 0;
|
|
5
|
+
exports.CalendarEventType = exports.CalendarViewType = exports.LyxaTimeZoneEnum = exports.UserOrderCompletionScope = exports.GroupCartNotificationStatus = exports.CurrencyType = exports.RequestFrom = exports.UploadState = exports.ServiceType = exports.ActionType = exports.DeviceType = exports.PushNotificationEventType = exports.SocketEventType = exports.SocketServiceQueue = exports.OtpMethodType = exports.ReviewType = exports.FoodNutritionType = exports.AdjustmentReason = exports.UrgentOrderReasons = exports.FlagReasonType = exports.FlagType = exports.PromotionType = exports.ServiceOrderCanceledBy = exports.TRPCErrorEnum = exports.ShopFilterSortByEnum = exports.BookingStatus = exports.ProfessionalScheduleType = exports.ServiceOrderRecurrencePattern = exports.ProfessionalRecurrencePattern = exports.ServiceOrderPriority = exports.ProfessionalStatus = exports.Service = void 0;
|
|
6
6
|
var AgentLiveStatus;
|
|
7
7
|
(function (AgentLiveStatus) {
|
|
8
8
|
AgentLiveStatus["ONLINE"] = "online";
|
|
@@ -1014,4 +1014,9 @@ var CalendarViewType;
|
|
|
1014
1014
|
CalendarViewType["WEEK"] = "week";
|
|
1015
1015
|
CalendarViewType["MONTH"] = "month";
|
|
1016
1016
|
})(CalendarViewType || (exports.CalendarViewType = CalendarViewType = {}));
|
|
1017
|
+
var CalendarEventType;
|
|
1018
|
+
(function (CalendarEventType) {
|
|
1019
|
+
CalendarEventType["ORDER"] = "order";
|
|
1020
|
+
CalendarEventType["BLOCK"] = "block";
|
|
1021
|
+
})(CalendarEventType || (exports.CalendarEventType = CalendarEventType = {}));
|
|
1017
1022
|
//# sourceMappingURL=enum.js.map
|