@stigg/node-server-sdk 4.11.0 → 4.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/entitlements/entitlementsApi.d.ts +1 -2
- package/dist/api/entitlements/entitlementsApi.js +1 -6
- package/dist/clientInitialization.js +8 -7
- package/dist/configuration.d.ts +2 -21
- package/dist/configuration.js +1 -1
- package/dist/models.d.ts +4 -14
- package/dist/models.js +1 -1
- package/dist/services/ApiCacheMapper.d.ts +15 -0
- package/dist/services/ApiCacheMapper.js +96 -0
- package/dist/services/LegacyEventPayloadMapper.d.ts +1 -1
- package/dist/services/LegacyEventPayloadMapper.js +1 -3
- package/dist/services/cache/CacheMapper.d.ts +16 -0
- package/dist/services/cache/CacheMapper.js +3 -0
- package/dist/services/cache/RedisSingleExecutionService/RedisSingleExecution.d.ts +3 -3
- package/dist/services/cache/RedisSingleExecutionService/RedisSingleExecution.js +4 -3
- package/dist/services/cache/accessDeniedReasonMapper.d.ts +3 -0
- package/dist/services/cache/accessDeniedReasonMapper.js +16 -0
- package/dist/{utils → services/cache}/cacheKeysHelpers.d.ts +3 -2
- package/dist/services/cache/cacheKeysHelpers.js +55 -0
- package/dist/services/cache/cacheService.d.ts +10 -25
- package/dist/services/cache/entities/cachedEntitlement.d.ts +5 -2
- package/dist/services/cache/entities/cachedEntitlement.js +32 -7
- package/dist/services/cache/entities/calculatedEntitlement.d.ts +16 -15
- package/dist/services/cache/entities/entitlementsMap.d.ts +15 -4
- package/dist/services/cache/entities/entitlementsMap.js +34 -24
- package/dist/services/cache/entities/index.d.ts +1 -1
- package/dist/services/cache/entities/index.js +2 -3
- package/dist/services/cache/entities/usageData.d.ts +8 -4
- package/dist/services/cache/entities/usageData.js +7 -1
- package/dist/services/cache/extractWithDependencies.d.ts +12 -0
- package/dist/services/cache/extractWithDependencies.js +37 -0
- package/dist/services/cache/freshness/EntitlementsFreshener.d.ts +11 -0
- package/dist/services/cache/freshness/EntitlementsFreshener.js +27 -0
- package/dist/services/cache/freshness/transformers/CreditAccessPropagator.d.ts +15 -0
- package/dist/services/cache/freshness/transformers/CreditAccessPropagator.js +67 -0
- package/dist/services/cache/freshness/transformers/UsagePeriodReset.d.ts +11 -0
- package/dist/services/cache/freshness/transformers/UsagePeriodReset.js +45 -0
- package/dist/services/cache/inMemoryCacheService.d.ts +18 -13
- package/dist/services/cache/inMemoryCacheService.js +41 -57
- package/dist/services/cache/index.d.ts +13 -0
- package/dist/services/cache/index.js +38 -0
- package/dist/services/cache/redis/distributedLocks.d.ts +4 -3
- package/dist/services/cache/redis/distributedLocks.js +5 -4
- package/dist/services/cache/redisCacheService.constants.d.ts +1 -1
- package/dist/services/cache/redisCacheService.constants.js +3 -3
- package/dist/services/cache/redisCacheService.d.ts +43 -17
- package/dist/services/cache/redisCacheService.js +233 -169
- package/dist/services/cache/types/cacheInstrumentation.d.ts +37 -0
- package/dist/services/cache/types/cacheInstrumentation.js +3 -0
- package/dist/services/cache/types/cacheResponse.d.ts +26 -0
- package/dist/services/cache/types/cacheResponse.js +19 -0
- package/dist/services/cache/types/cacheServiceParams.d.ts +20 -0
- package/dist/services/cache/types/cacheServiceParams.js +3 -0
- package/dist/services/cache/types/entitlementFeature.d.ts +19 -0
- package/dist/services/cache/types/entitlementFeature.js +3 -0
- package/dist/services/cache/types/entitlementsMapTransformer.d.ts +4 -0
- package/dist/services/cache/types/entitlementsMapTransformer.js +3 -0
- package/dist/services/cache/types/logger.d.ts +6 -0
- package/dist/services/cache/types/logger.js +3 -0
- package/dist/services/cache/types/redisConfiguration.d.ts +39 -0
- package/dist/services/cache/types/redisConfiguration.js +14 -0
- package/dist/services/entitlementDecisionService.d.ts +1 -1
- package/dist/services/entitlementDecisionService.js +5 -5
- package/dist/services/entitlementsService.d.ts +21 -19
- package/dist/services/entitlementsService.js +57 -91
- package/dist/services/entitlementsService.utils.d.ts +0 -26
- package/dist/services/entitlementsService.utils.js +1 -17
- package/dist/services/eventEmitter.d.ts +1 -1
- package/dist/services/eventEmitterCacheInstrumentation.d.ts +9 -0
- package/dist/services/eventEmitterCacheInstrumentation.js +19 -0
- package/dist/services/inMemoryEntitlementsService.d.ts +5 -6
- package/dist/services/inMemoryEntitlementsService.js +36 -53
- package/dist/services/redisEntitlementsService.d.ts +5 -4
- package/dist/services/redisEntitlementsService.js +2 -2
- package/dist/types.d.ts +1 -0
- package/dist/utils/ModelMapper.d.ts +1 -1
- package/dist/{services/cache → utils}/calculateUsagePeriod.js +1 -1
- package/package.json +18 -1
- package/dist/services/cacheInstrumentation.d.ts +0 -18
- package/dist/services/cacheInstrumentation.js +0 -19
- package/dist/utils/CacheMapper.d.ts +0 -13
- package/dist/utils/CacheMapper.js +0 -95
- package/dist/utils/cacheKeysHelpers.js +0 -42
- /package/dist/{services/cache → utils}/calculateUsagePeriod.d.ts +0 -0
|
@@ -7,26 +7,35 @@ exports.RedisCacheService = void 0;
|
|
|
7
7
|
const entities_1 = require("./entities");
|
|
8
8
|
const ioredis_1 = __importDefault(require("ioredis"));
|
|
9
9
|
const lodash_1 = require("lodash");
|
|
10
|
-
const
|
|
10
|
+
const redisConfiguration_1 = require("./types/redisConfiguration");
|
|
11
|
+
const cacheKeysHelpers_1 = require("./cacheKeysHelpers");
|
|
11
12
|
const RedisSingleExecutionService_1 = require("./RedisSingleExecutionService");
|
|
12
|
-
const
|
|
13
|
+
const cacheResponse_1 = require("./types/cacheResponse");
|
|
14
|
+
const extractWithDependencies_1 = require("./extractWithDependencies");
|
|
15
|
+
const EntitlementsFreshener_1 = require("./freshness/EntitlementsFreshener");
|
|
13
16
|
const redisCacheService_constants_1 = require("./redisCacheService.constants");
|
|
14
17
|
const distributedLocks_1 = require("./redis/distributedLocks");
|
|
18
|
+
const accessDeniedReasonMapper_1 = require("./accessDeniedReasonMapper");
|
|
15
19
|
const GRACE_CONNECT_TIMEOUT_MS = 250;
|
|
16
20
|
const READY_STATUSES = ['connect', 'ready'];
|
|
17
21
|
class RedisCacheService {
|
|
18
|
-
constructor(options, loggerService, cacheInstrumentation) {
|
|
22
|
+
constructor(options, loggerService, cacheInstrumentation, cacheMapper) {
|
|
19
23
|
this.loggerService = loggerService;
|
|
20
24
|
this.cacheInstrumentation = cacheInstrumentation;
|
|
21
|
-
|
|
25
|
+
this.cacheMapper = cacheMapper;
|
|
26
|
+
this.freshen = new EntitlementsFreshener_1.EntitlementsFreshener();
|
|
27
|
+
const { redis: redisOptions, entitlementsTimeout = redisCacheService_constants_1.DEFAULT_ENTITLEMENTS_TIMEOUT_MS, cacheUpdatePolicy = redisConfiguration_1.CacheUpdatePolicy.UPSERT, lockSettings, directExecution = false, } = options;
|
|
22
28
|
const { environmentPrefix, ttl = redisCacheService_constants_1.DEFAULT_TTL_SECS, distributedEntitlementsFetching = {} } = redisOptions;
|
|
23
29
|
this.redisClient = new ioredis_1.default(redisOptions);
|
|
24
|
-
this.distributedLocks = new distributedLocks_1.DistributedLocks(this.redisClient, loggerService, cacheInstrumentation);
|
|
30
|
+
this.distributedLocks = new distributedLocks_1.DistributedLocks(this.redisClient, loggerService, cacheInstrumentation, lockSettings);
|
|
31
|
+
this.directExecution = directExecution;
|
|
32
|
+
this.cacheUpdatePolicy = cacheUpdatePolicy;
|
|
25
33
|
this.environmentPrefix = environmentPrefix;
|
|
26
34
|
this.ttl = ttl;
|
|
27
35
|
this.redisClient.on('error', (err) => {
|
|
36
|
+
var _a, _b;
|
|
28
37
|
this.loggerService.error('Redis client error: ', err);
|
|
29
|
-
this.cacheInstrumentation.trackRedisClientError({ error: err, clientName: 'redis' });
|
|
38
|
+
(_b = (_a = this.cacheInstrumentation).trackRedisClientError) === null || _b === void 0 ? void 0 : _b.call(_a, { error: err, clientName: 'redis' });
|
|
30
39
|
});
|
|
31
40
|
this.redisClient.on('connect', () => {
|
|
32
41
|
this.loggerService.log('Redis client connected!');
|
|
@@ -47,7 +56,12 @@ class RedisCacheService {
|
|
|
47
56
|
*/
|
|
48
57
|
waitForInitialization() {
|
|
49
58
|
return new Promise((resolve) => {
|
|
50
|
-
//
|
|
59
|
+
// for trigger connection for lazyConnect option
|
|
60
|
+
if (this.redisClient.status === 'wait') {
|
|
61
|
+
this.redisClient.connect().catch(() => {
|
|
62
|
+
/* no-op: errors are handled in the 'error' event listener */
|
|
63
|
+
});
|
|
64
|
+
}
|
|
51
65
|
if (this.isClientConnected()) {
|
|
52
66
|
resolve();
|
|
53
67
|
return;
|
|
@@ -81,102 +95,106 @@ class RedisCacheService {
|
|
|
81
95
|
isClientConnected() {
|
|
82
96
|
return READY_STATUSES.includes(this.redisClient.status);
|
|
83
97
|
}
|
|
84
|
-
async updateUsage({ customerId, resourceId, entitlementReference, usage, }) {
|
|
85
|
-
return this.executeSafely('updateUsage',
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (!entitlement || !(0, entities_1.isFeatureEntitlement)(entitlement)) {
|
|
97
|
-
return null;
|
|
98
|
+
async updateUsage({ customerId, resourceId, entitlementReference, usage, usageTimestamp, }) {
|
|
99
|
+
return this.executeSafely('updateUsage', undefined, async () => {
|
|
100
|
+
// Only update usage if the customer's entitlements exist in cache
|
|
101
|
+
const { customerKey } = (0, cacheKeysHelpers_1.buildRedisCustomerKey)(this.environmentPrefix, customerId, resourceId);
|
|
102
|
+
const customerExists = await this.keyExists(customerKey);
|
|
103
|
+
if (!customerExists) {
|
|
104
|
+
this.loggerService.debug(`Skipping usage update - customer entitlements not found in cache`, {
|
|
105
|
+
customerId,
|
|
106
|
+
resourceId,
|
|
107
|
+
entitlementReference,
|
|
108
|
+
});
|
|
109
|
+
return;
|
|
98
110
|
}
|
|
99
|
-
const item = this.
|
|
111
|
+
const item = this.getUsageItemToUpdate({
|
|
100
112
|
customerId,
|
|
101
113
|
resourceId,
|
|
102
|
-
|
|
114
|
+
entitlementReference,
|
|
103
115
|
usage,
|
|
116
|
+
usageTimestamp,
|
|
104
117
|
});
|
|
105
118
|
await this.updateCacheItems([item]);
|
|
106
|
-
return this.mergeEntitlementWithUsage(entitlement, usage);
|
|
107
119
|
});
|
|
108
120
|
}
|
|
109
|
-
|
|
110
|
-
const
|
|
121
|
+
async keyExists(key) {
|
|
122
|
+
const result = await this.redisClient.exists(`${key}#${redisCacheService_constants_1.TIMESTAMP_SUFFIX}`);
|
|
123
|
+
return result === 1;
|
|
124
|
+
}
|
|
125
|
+
getUsageItemToUpdate({ customerId, resourceId, entitlementReference, usage, usageTimestamp, }) {
|
|
126
|
+
const { currentUsage, usagePeriodStart, usagePeriodEnd } = usage;
|
|
111
127
|
const value = {
|
|
112
128
|
currentUsage,
|
|
113
129
|
usagePeriodStart,
|
|
114
130
|
usagePeriodEnd,
|
|
115
131
|
};
|
|
116
132
|
return {
|
|
117
|
-
messageTimestamp:
|
|
118
|
-
key: (0, cacheKeysHelpers_1.buildRedisUsageKey)(this.environmentPrefix, customerId,
|
|
133
|
+
messageTimestamp: usageTimestamp,
|
|
134
|
+
key: (0, cacheKeysHelpers_1.buildRedisUsageKey)(this.environmentPrefix, customerId, entitlementReference, resourceId),
|
|
119
135
|
value,
|
|
120
136
|
};
|
|
121
137
|
}
|
|
122
|
-
async setCustomer(customerId,
|
|
123
|
-
|
|
138
|
+
async setCustomer({ customerId, resourceId, entitlements: entitlementsInput, accessDeniedReason, entitlementsTimestamp, }) {
|
|
139
|
+
const { entitlements, usageUpdatedAtMap } = entities_1.EntitlementsMap.fromInput(this.cacheMapper, entitlementsInput);
|
|
140
|
+
const freshenedEntitlements = this.freshen.transform(entitlements);
|
|
141
|
+
return this.executeSafely('setCustomer', freshenedEntitlements, async () => {
|
|
142
|
+
const { customerKey, metadataKey } = (0, cacheKeysHelpers_1.buildRedisCustomerKey)(this.environmentPrefix, customerId, resourceId);
|
|
124
143
|
const lockKey = (0, cacheKeysHelpers_1.buildLockKey)(this.environmentPrefix, customerId, resourceId);
|
|
125
144
|
await this.distributedLocks.using(lockKey, async () => {
|
|
126
|
-
const { customerKey, metadataKey } = (0, cacheKeysHelpers_1.buildRedisCustomerKey)(this.environmentPrefix, customerId, resourceId);
|
|
127
145
|
const entitlementsItem = {
|
|
128
146
|
messageTimestamp: new Date(entitlementsTimestamp),
|
|
129
147
|
key: customerKey,
|
|
130
|
-
value:
|
|
148
|
+
value: entitlements.toJSON(),
|
|
149
|
+
};
|
|
150
|
+
const metadata = {
|
|
151
|
+
accessDeniedReason: (0, accessDeniedReasonMapper_1.mapAccessDeniedReason)(accessDeniedReason),
|
|
131
152
|
};
|
|
132
|
-
const metadata = { accessDeniedReason };
|
|
133
153
|
const metadataItem = {
|
|
134
154
|
messageTimestamp: new Date(entitlementsTimestamp),
|
|
135
155
|
key: metadataKey,
|
|
136
156
|
value: metadata,
|
|
137
157
|
};
|
|
138
|
-
const
|
|
158
|
+
const usagesItems = this.extractUsagesToUpdate({
|
|
139
159
|
customerId,
|
|
140
160
|
resourceId,
|
|
141
|
-
|
|
161
|
+
entitlements,
|
|
162
|
+
usageUpdatedAtMap,
|
|
142
163
|
});
|
|
143
|
-
await this.updateCacheItems([entitlementsItem, metadataItem, ...
|
|
164
|
+
await this.updateCacheItems([entitlementsItem, metadataItem, ...usagesItems]);
|
|
144
165
|
});
|
|
166
|
+
return freshenedEntitlements;
|
|
145
167
|
});
|
|
146
168
|
}
|
|
147
|
-
|
|
148
|
-
return (0, lodash_1.compact)(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
const featureId = feature.id;
|
|
158
|
-
if (!featureUsageTimestamp) {
|
|
159
|
-
this.loggerService.error(`Usage timestamp for feature is missing`, {
|
|
160
|
-
customerId,
|
|
161
|
-
resourceId,
|
|
162
|
-
featureId,
|
|
163
|
-
});
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
return this.getFeatureUsageItemToUpdate({
|
|
169
|
+
extractUsagesToUpdate({ customerId, resourceId, entitlements, usageUpdatedAtMap, }) {
|
|
170
|
+
return (0, lodash_1.compact)(entitlements
|
|
171
|
+
.values()
|
|
172
|
+
.filter((entitlement) => entitlement.isUsageTrackable())
|
|
173
|
+
.map((entitlement) => {
|
|
174
|
+
const entitlementReference = entitlement.getEntitlementQuery();
|
|
175
|
+
const usageTimestamp = this.getUsageTimestamp(usageUpdatedAtMap, entitlementReference);
|
|
176
|
+
return this.getUsageItemToUpdate({
|
|
167
177
|
customerId,
|
|
168
178
|
resourceId,
|
|
169
|
-
|
|
170
|
-
usage:
|
|
171
|
-
|
|
172
|
-
usagePeriodStart,
|
|
173
|
-
usagePeriodEnd,
|
|
174
|
-
updatedAt: featureUsageTimestamp,
|
|
175
|
-
},
|
|
179
|
+
entitlementReference,
|
|
180
|
+
usage: entitlement.usageData,
|
|
181
|
+
usageTimestamp,
|
|
176
182
|
});
|
|
177
183
|
}));
|
|
178
184
|
}
|
|
185
|
+
getUsageTimestamp(usageUpdatedAtMap, entitlementReference) {
|
|
186
|
+
const key = entities_1.EntitlementsMap.getUniqueKey(entitlementReference);
|
|
187
|
+
const usageTimestamp = usageUpdatedAtMap.get(key);
|
|
188
|
+
if (!usageTimestamp) {
|
|
189
|
+
this.loggerService.error('Usage timestamp not found for entitlement, using current time', {
|
|
190
|
+
entitlementReference,
|
|
191
|
+
});
|
|
192
|
+
return new Date();
|
|
193
|
+
}
|
|
194
|
+
return usageTimestamp;
|
|
195
|
+
}
|
|
179
196
|
async getCustomerEntitlementsWithoutUsage(customerId, resourceId) {
|
|
197
|
+
var _a, _b, _c, _d;
|
|
180
198
|
const { customerKey, metadataKey } = (0, cacheKeysHelpers_1.buildRedisCustomerKey)(this.environmentPrefix, customerId, resourceId);
|
|
181
199
|
const keysToFetch = [customerKey, metadataKey];
|
|
182
200
|
if (resourceId) {
|
|
@@ -197,12 +215,12 @@ class RedisCacheService {
|
|
|
197
215
|
const globalEntitlementsTimestamp = this.parseTimestamp(globalEntitlementsTimestampValue);
|
|
198
216
|
const globalCustomerMissing = this.isGlobalCustomerMissingInCache(customerId, resourceId, entitlements, entitlementsTimestamp, globalEntitlementsTimestamp);
|
|
199
217
|
if (!entitlements || globalCustomerMissing) {
|
|
200
|
-
this.cacheInstrumentation.trackMiss({ customerId, resourceId, globalCustomerMissing });
|
|
201
|
-
return
|
|
218
|
+
(_b = (_a = this.cacheInstrumentation).trackMiss) === null || _b === void 0 ? void 0 : _b.call(_a, { customerId, resourceId, globalCustomerMissing });
|
|
219
|
+
return cacheResponse_1.entitlementsResponseMapper.cacheMiss(globalCustomerMissing);
|
|
202
220
|
}
|
|
203
221
|
this.loggerService.debug(`Found entitlements in persisted cache for customer`, { customerId, resourceId });
|
|
204
|
-
this.cacheInstrumentation.trackHit({ customerId, resourceId });
|
|
205
|
-
return
|
|
222
|
+
(_d = (_c = this.cacheInstrumentation).trackHit) === null || _d === void 0 ? void 0 : _d.call(_c, { customerId, resourceId });
|
|
223
|
+
return cacheResponse_1.entitlementsResponseMapper.cacheHit(entitlements, accessDeniedReason);
|
|
206
224
|
}
|
|
207
225
|
// resource entitlements are affected by global entitlements, so if global
|
|
208
226
|
// entitlements are missing or newer, we should refetch since the cache is stale
|
|
@@ -227,99 +245,140 @@ class RedisCacheService {
|
|
|
227
245
|
});
|
|
228
246
|
return true;
|
|
229
247
|
}
|
|
230
|
-
async getCustomerEntitlements(
|
|
231
|
-
return this.
|
|
248
|
+
async getCustomerEntitlements(params) {
|
|
249
|
+
return this.getCached('getCustomerEntitlements', params);
|
|
250
|
+
}
|
|
251
|
+
async getCached(operationName, { customerId, resourceId }, extract) {
|
|
252
|
+
return this.executeSafely(operationName, cacheResponse_1.entitlementsResponseMapper.cacheMiss(), async () => {
|
|
253
|
+
var _a, _b, _c, _d;
|
|
232
254
|
const response = await this.getCustomerEntitlementsWithoutUsage(customerId, resourceId);
|
|
233
255
|
if (response.cacheMiss) {
|
|
234
256
|
return response;
|
|
235
257
|
}
|
|
236
|
-
const { entitlements, accessDeniedReason } = response;
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
258
|
+
const { entitlements: entitlementsWithoutUsage, accessDeniedReason } = response;
|
|
259
|
+
const extracted = extract ? extract.transform(entitlementsWithoutUsage) : entitlementsWithoutUsage;
|
|
260
|
+
const withUsage = await this.fetchAndMergeUsage(customerId, resourceId, extracted);
|
|
261
|
+
if (!withUsage) {
|
|
262
|
+
(_b = (_a = this.cacheInstrumentation).trackMiss) === null || _b === void 0 ? void 0 : _b.call(_a, { customerId, resourceId });
|
|
263
|
+
return cacheResponse_1.entitlementsResponseMapper.cacheMiss();
|
|
264
|
+
}
|
|
265
|
+
const entitlements = this.freshen.transform(withUsage);
|
|
266
|
+
(_d = (_c = this.cacheInstrumentation).trackHit) === null || _d === void 0 ? void 0 : _d.call(_c, { customerId, resourceId });
|
|
267
|
+
return cacheResponse_1.entitlementsResponseMapper.cacheHit(entitlements, accessDeniedReason);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Fetches usage for all trackable entitlements and merges it into the map.
|
|
272
|
+
* Returns null if any trackable entitlement is missing usage (cache miss).
|
|
273
|
+
*/
|
|
274
|
+
async fetchAndMergeUsage(customerId, resourceId, entitlements) {
|
|
275
|
+
const usageTrackableRefs = entitlements
|
|
276
|
+
.values()
|
|
277
|
+
.filter((ent) => ent.isUsageTrackable())
|
|
278
|
+
.map((ent) => ent.getEntitlementQuery());
|
|
279
|
+
if (!(0, lodash_1.isEmpty)(usageTrackableRefs)) {
|
|
280
|
+
const usageByKey = await this.getUsages(this.environmentPrefix, customerId, resourceId, usageTrackableRefs);
|
|
281
|
+
const missingRefs = usageTrackableRefs.filter((ref) => !usageByKey.has(entities_1.EntitlementsMap.getUniqueKey(ref)));
|
|
282
|
+
if (!(0, lodash_1.isEmpty)(missingRefs)) {
|
|
283
|
+
this.loggerService.error(`Failed to find usage - considering it as cache miss`, {
|
|
284
|
+
customerId,
|
|
285
|
+
resourceId,
|
|
286
|
+
missingRefs,
|
|
287
|
+
});
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
usageTrackableRefs.forEach((entitlementRef) => {
|
|
291
|
+
const usageValue = usageByKey.get(entities_1.EntitlementsMap.getUniqueKey(entitlementRef));
|
|
292
|
+
if (!usageValue) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
const cachedEntitlement = entitlements.get(entitlementRef);
|
|
296
|
+
if (cachedEntitlement) {
|
|
297
|
+
entitlements.set(this.mergeEntitlementWithUsage(cachedEntitlement, usageValue));
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
this.loggerService.log(`Found usage for an entitlement the customer is not entitled to.`, {
|
|
247
301
|
customerId,
|
|
248
|
-
|
|
249
|
-
missingFeatureIds,
|
|
302
|
+
entitlementRef,
|
|
250
303
|
});
|
|
251
|
-
this.cacheInstrumentation.trackMiss({ customerId, resourceId });
|
|
252
|
-
return entitlementsService_utils_1.entitlementsResponseMapper.cacheMiss();
|
|
253
304
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
id: featureId,
|
|
258
|
-
});
|
|
259
|
-
if (cachedEntitlement && (0, entities_1.isFeatureEntitlement)(cachedEntitlement)) {
|
|
260
|
-
entitlements.set(this.mergeEntitlementWithUsage(cachedEntitlement, usageValue));
|
|
261
|
-
}
|
|
262
|
-
else if (!cachedEntitlement) {
|
|
263
|
-
this.loggerService.log(`Found usage for a feature the customer is not entitled to.`, {
|
|
264
|
-
customerId,
|
|
265
|
-
featureId,
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
this.cacheInstrumentation.trackHit({ customerId, resourceId });
|
|
271
|
-
return entitlementsService_utils_1.entitlementsResponseMapper.cacheHit(entitlements, accessDeniedReason);
|
|
272
|
-
});
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
return entitlements;
|
|
273
308
|
}
|
|
274
|
-
async
|
|
275
|
-
const keysToFetch =
|
|
309
|
+
async getUsages(environmentPrefix, customerId, resourceId, entitlementReferences) {
|
|
310
|
+
const keysToFetch = entitlementReferences.map((ref) => (0, cacheKeysHelpers_1.buildRedisUsageKey)(environmentPrefix, customerId, ref, resourceId));
|
|
276
311
|
const usageValues = await this.redisClient.mget(keysToFetch);
|
|
277
|
-
const
|
|
312
|
+
const usageByEntitlementKey = new Map();
|
|
278
313
|
// Redis guarantees returning values in the same order of the keys so this is legit!
|
|
279
|
-
|
|
280
|
-
const
|
|
281
|
-
if (
|
|
282
|
-
this.loggerService.log(`Failed to find usage for
|
|
314
|
+
entitlementReferences.forEach((ref, index) => {
|
|
315
|
+
const usageValue = usageValues[index];
|
|
316
|
+
if (usageValue === null) {
|
|
317
|
+
this.loggerService.log(`Failed to find usage for entitlement: ${ref.type}:${ref.id}`);
|
|
283
318
|
return;
|
|
284
319
|
}
|
|
285
|
-
|
|
320
|
+
usageByEntitlementKey.set(entities_1.EntitlementsMap.getUniqueKey(ref), this.migrateUsageData(JSON.parse(usageValue)));
|
|
286
321
|
});
|
|
287
|
-
return
|
|
322
|
+
return usageByEntitlementKey;
|
|
288
323
|
}
|
|
289
324
|
clearCache() {
|
|
290
325
|
return;
|
|
291
326
|
}
|
|
292
327
|
async updateCacheItems(items) {
|
|
328
|
+
var _a, _b, _c, _d;
|
|
293
329
|
if ((0, lodash_1.isEmpty)(items)) {
|
|
294
330
|
return;
|
|
295
331
|
}
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
const writeableValue = typeof value === 'string' ? value : JSON.stringify(value);
|
|
304
|
-
itemsToUpdate.push({ key, value: writeableValue });
|
|
305
|
-
itemsToUpdate.push({ key: `${key}#${redisCacheService_constants_1.TIMESTAMP_SUFFIX}`, value: messageTimestamp.getTime() });
|
|
306
|
-
}
|
|
307
|
-
else {
|
|
308
|
-
this.loggerService.log('Cache data timestamp is after message timestamp, skipping key update', {
|
|
309
|
-
messageTimestamp,
|
|
310
|
-
latestTimestamp,
|
|
311
|
-
key,
|
|
332
|
+
const startTime = Date.now();
|
|
333
|
+
try {
|
|
334
|
+
const latestTimestampByKey = await this.getKeysLatestTimestamp(items.map((item) => item.key));
|
|
335
|
+
// Check if we should skip writing based on cache policy
|
|
336
|
+
if (this.shouldSkipWriting(items, latestTimestampByKey)) {
|
|
337
|
+
this.loggerService.log(`Cache data does not exist - skipping according to cache policy (${this.cacheUpdatePolicy})`, {
|
|
338
|
+
keys: items.map((item) => item.key),
|
|
312
339
|
});
|
|
340
|
+
return;
|
|
313
341
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
342
|
+
const itemsToUpdate = [];
|
|
343
|
+
items.forEach(({ messageTimestamp, key, value }) => {
|
|
344
|
+
const latestTimestamp = latestTimestampByKey.get(key);
|
|
345
|
+
if (!latestTimestamp ||
|
|
346
|
+
messageTimestamp.getTime() === cacheResponse_1.DATE_IN_FAR_PAST.getTime() ||
|
|
347
|
+
latestTimestamp.getTime() <= messageTimestamp.getTime()) {
|
|
348
|
+
const writeableValue = typeof value === 'string' ? value : JSON.stringify(value);
|
|
349
|
+
itemsToUpdate.push({ key, value: writeableValue });
|
|
350
|
+
itemsToUpdate.push({ key: `${key}#${redisCacheService_constants_1.TIMESTAMP_SUFFIX}`, value: messageTimestamp.getTime() });
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
this.loggerService.log('Cache data timestamp is after message timestamp, skipping key update', {
|
|
354
|
+
messageTimestamp,
|
|
355
|
+
latestTimestamp,
|
|
356
|
+
key,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
if ((0, lodash_1.isEmpty)(itemsToUpdate)) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
const batch = this.redisClient.multi();
|
|
364
|
+
itemsToUpdate.forEach(({ key, value }) => {
|
|
365
|
+
batch.set(key, value, 'EX', this.ttl);
|
|
366
|
+
});
|
|
367
|
+
await batch.exec();
|
|
368
|
+
// Track write duration
|
|
369
|
+
const durationSeconds = (Date.now() - startTime) / 1000;
|
|
370
|
+
(_b = (_a = this.cacheInstrumentation).trackWriteDuration) === null || _b === void 0 ? void 0 : _b.call(_a, 'updateCacheItems', durationSeconds);
|
|
317
371
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
|
|
372
|
+
catch (error) {
|
|
373
|
+
(_d = (_c = this.cacheInstrumentation).trackWriteError) === null || _d === void 0 ? void 0 : _d.call(_c, 'updateCacheItems');
|
|
374
|
+
throw error;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
shouldSkipWriting(items, latestTimestampByKey) {
|
|
378
|
+
if (this.cacheUpdatePolicy === redisConfiguration_1.CacheUpdatePolicy.UPSERT) {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
return !items.some(({ key }) => latestTimestampByKey.get(key) !== undefined);
|
|
323
382
|
}
|
|
324
383
|
async getKeysLatestTimestamp(keys) {
|
|
325
384
|
const timestampKeys = keys.map((key) => `${key}#${redisCacheService_constants_1.TIMESTAMP_SUFFIX}`);
|
|
@@ -345,43 +404,38 @@ class RedisCacheService {
|
|
|
345
404
|
await this.distributedLocks.cleanup();
|
|
346
405
|
await ((_a = this.distributedRefetchEntitlementsService) === null || _a === void 0 ? void 0 : _a.cleanup());
|
|
347
406
|
}
|
|
348
|
-
async
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
const entitlement = !cacheMiss ? (entitlements === null || entitlements === void 0 ? void 0 : entitlements.get(query)) || null : null;
|
|
357
|
-
const result = { cacheMiss, accessDeniedReason, entitlement, globalCustomerMissing };
|
|
358
|
-
if (!entitlement || !(0, entities_1.isMeteredFeatureEntitlement)(entitlement)) {
|
|
359
|
-
return result;
|
|
360
|
-
}
|
|
361
|
-
const featureId = query.id;
|
|
362
|
-
const featuresUsageByFeatureKey = await this.getFeaturesUsage(this.environmentPrefix, customerId, resourceId, [
|
|
363
|
-
featureId,
|
|
364
|
-
]);
|
|
365
|
-
const cachedFeatureUsage = featuresUsageByFeatureKey.get(featureId);
|
|
366
|
-
if ((0, lodash_1.isNil)(cachedFeatureUsage)) {
|
|
367
|
-
this.loggerService.error('Failed to find metered feature usage - considering it as cache miss', {
|
|
368
|
-
customerId,
|
|
369
|
-
resourceId,
|
|
370
|
-
featureId,
|
|
407
|
+
async purge(customers) {
|
|
408
|
+
const customersArray = Array.isArray(customers) ? customers : [customers];
|
|
409
|
+
return this.executeSafely('purge', undefined, async () => {
|
|
410
|
+
for (const customerChunk of (0, lodash_1.chunk)(customersArray, RedisCacheService.DELETE_CHUNK_SIZE)) {
|
|
411
|
+
const keysToDelete = customerChunk.flatMap(({ customerId, resourceId }) => {
|
|
412
|
+
this.loggerService.log(`Invalidating entitlements cache`, { customerId, resourceId });
|
|
413
|
+
const { customerKey, metadataKey } = (0, cacheKeysHelpers_1.buildRedisCustomerKey)(this.environmentPrefix, customerId, resourceId);
|
|
414
|
+
return [customerKey, `${customerKey}#${redisCacheService_constants_1.TIMESTAMP_SUFFIX}`, metadataKey, `${metadataKey}#${redisCacheService_constants_1.TIMESTAMP_SUFFIX}`];
|
|
371
415
|
});
|
|
372
|
-
|
|
373
|
-
cacheMiss: true,
|
|
374
|
-
accessDeniedReason: undefined,
|
|
375
|
-
entitlement: null,
|
|
376
|
-
globalCustomerMissing: false,
|
|
377
|
-
};
|
|
416
|
+
await this.redisClient.del(keysToDelete);
|
|
378
417
|
}
|
|
379
|
-
return Object.assign(Object.assign({}, result), { entitlement: this.mergeEntitlementWithUsage(entitlement, cachedFeatureUsage) });
|
|
380
418
|
});
|
|
381
419
|
}
|
|
420
|
+
async getCustomerEntitlement(params) {
|
|
421
|
+
const { query } = params;
|
|
422
|
+
const extractor = new extractWithDependencies_1.ExtractWithDependencies(query);
|
|
423
|
+
const { entitlements, accessDeniedReason, cacheMiss, globalCustomerMissing } = await this.getCached('getCustomerEntitlement', params, extractor);
|
|
424
|
+
const entitlement = !cacheMiss ? (entitlements === null || entitlements === void 0 ? void 0 : entitlements.get(query)) || null : null;
|
|
425
|
+
return { cacheMiss, accessDeniedReason, entitlement, globalCustomerMissing };
|
|
426
|
+
}
|
|
382
427
|
mergeEntitlementWithUsage(entitlement, cachedUsage) {
|
|
383
|
-
|
|
384
|
-
|
|
428
|
+
return new entities_1.CachedEntitlement(entitlement.calculatedEntitlement, cachedUsage);
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Returns Redis server info for the specified section (e.g., 'memory', 'stats').
|
|
432
|
+
* Throws if the client is not connected.
|
|
433
|
+
*/
|
|
434
|
+
async getServerInfo(section) {
|
|
435
|
+
if (!this.isClientConnected()) {
|
|
436
|
+
throw new Error('Redis client is not connected');
|
|
437
|
+
}
|
|
438
|
+
return this.redisClient.info(section);
|
|
385
439
|
}
|
|
386
440
|
/**
|
|
387
441
|
* Migrates old cache format to new format.
|
|
@@ -400,6 +454,11 @@ class RedisCacheService {
|
|
|
400
454
|
}
|
|
401
455
|
// 2. Add type discriminator if missing (old cache only had Feature entitlements)
|
|
402
456
|
if (!entry.calculatedEntitlement.type) {
|
|
457
|
+
// Skip malformed entries that don't have a feature object - they can't be valid Feature entitlements
|
|
458
|
+
if (!entry.calculatedEntitlement.feature) {
|
|
459
|
+
delete cacheData[key];
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
403
462
|
entry.calculatedEntitlement.type = entities_1.EntitlementType.Feature;
|
|
404
463
|
}
|
|
405
464
|
// 3. Move fields from usageData to calculatedEntitlement (for Feature type)
|
|
@@ -439,6 +498,10 @@ class RedisCacheService {
|
|
|
439
498
|
return usageData;
|
|
440
499
|
}
|
|
441
500
|
async executeSafely(operationName, defaultValue, operation) {
|
|
501
|
+
// When directExecution is enabled, run operations directly without safety wrapper
|
|
502
|
+
if (this.directExecution) {
|
|
503
|
+
return operation();
|
|
504
|
+
}
|
|
442
505
|
if (!this.isClientConnected()) {
|
|
443
506
|
return defaultValue;
|
|
444
507
|
}
|
|
@@ -452,4 +515,5 @@ class RedisCacheService {
|
|
|
452
515
|
}
|
|
453
516
|
}
|
|
454
517
|
exports.RedisCacheService = RedisCacheService;
|
|
455
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkaXNDYWNoZVNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvY2FjaGUvcmVkaXNDYWNoZVNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQ0EseUNBUW9CO0FBQ3BCLHNEQUE0QjtBQUM1QixtQ0FBNkU7QUFHN0UsbUVBQXVHO0FBQ3ZHLCtFQUE0RTtBQUM1RSw0RUFLc0M7QUFDdEMsK0VBS3VDO0FBRXZDLCtEQUE0RDtBQW1CNUQsTUFBTSx3QkFBd0IsR0FBRyxHQUFHLENBQUM7QUFFckMsTUFBTSxjQUFjLEdBQWEsQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFFdEQsTUFBYSxpQkFBaUI7SUFRNUIsWUFDRSxPQUFzQyxFQUNyQixhQUE0QixFQUM1QixvQkFBMEM7UUFEMUMsa0JBQWEsR0FBYixhQUFhLENBQWU7UUFDNUIseUJBQW9CLEdBQXBCLG9CQUFvQixDQUFzQjtRQUUzRCxNQUFNLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxtQkFBbUIsRUFBRSxHQUFHLE9BQU8sQ0FBQztRQUM3RCxNQUFNLEVBQUUsaUJBQWlCLEVBQUUsR0FBRyxHQUFHLDhDQUFnQixFQUFFLCtCQUErQixHQUFHLEVBQUUsRUFBRSxHQUFHLFlBQVksQ0FBQztRQUV6RyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksaUJBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUMzQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxtQ0FBZ0IsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLGFBQWEsRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO1FBQ3BHLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxpQkFBaUIsQ0FBQztRQUMzQyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUVmLElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO1lB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
|
|
518
|
+
RedisCacheService.DELETE_CHUNK_SIZE = 1000;
|
|
519
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkaXNDYWNoZVNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvY2FjaGUvcmVkaXNDYWNoZVNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBUUEseUNBQThHO0FBRTlHLHNEQUE0QjtBQUM1QixtQ0FBd0U7QUFFeEUsbUVBQXdGO0FBQ3hGLHlEQUE2RjtBQUM3RiwrRUFBNEU7QUFDNUUseURBSytCO0FBQy9CLHVFQUFvRTtBQUVwRSw2RUFBMEU7QUFDMUUsK0VBTXVDO0FBQ3ZDLCtEQUE0RDtBQUc1RCx5RUFBbUU7QUFpQm5FLE1BQU0sd0JBQXdCLEdBQUcsR0FBRyxDQUFDO0FBRXJDLE1BQU0sY0FBYyxHQUFhLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBRXRELE1BQWEsaUJBQWlCO0lBYTVCLFlBQ0UsT0FBZ0MsRUFDZixhQUF5QixFQUN6QixvQkFBMEMsRUFDMUMsV0FBK0I7UUFGL0Isa0JBQWEsR0FBYixhQUFhLENBQVk7UUFDekIseUJBQW9CLEdBQXBCLG9CQUFvQixDQUFzQjtRQUMxQyxnQkFBVyxHQUFYLFdBQVcsQ0FBb0I7UUFSakMsWUFBTyxHQUFHLElBQUksNkNBQXFCLEVBQUUsQ0FBQztRQVVyRCxNQUFNLEVBQ0osS0FBSyxFQUFFLFlBQVksRUFDbkIsbUJBQW1CLEdBQUcsNkRBQStCLEVBQ3JELGlCQUFpQixHQUFHLHNDQUFpQixDQUFDLE1BQU0sRUFDNUMsWUFBWSxFQUNaLGVBQWUsR0FBRyxLQUFLLEdBQ3hCLEdBQUcsT0FBTyxDQUFDO1FBQ1osTUFBTSxFQUFFLGlCQUFpQixFQUFFLEdBQUcsR0FBRyw4Q0FBZ0IsRUFBRSwrQkFBK0IsR0FBRyxFQUFFLEVBQUUsR0FBRyxZQUFZLENBQUM7UUFFekcsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLGlCQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLGdCQUFnQixHQUFH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
|