@stigg/node-server-sdk 4.10.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 +3 -4
- package/dist/api/entitlements/entitlementsApi.js +3 -8
- package/dist/client.d.ts +11 -1
- package/dist/client.js +26 -4
- package/dist/clientInitialization.js +8 -7
- package/dist/configuration.d.ts +2 -21
- package/dist/configuration.js +1 -1
- package/dist/models.d.ts +30 -6
- package/dist/models.js +12 -2
- package/dist/services/ApiCacheMapper.d.ts +15 -0
- package/dist/services/ApiCacheMapper.js +96 -0
- package/dist/services/EdgeApiClient.d.ts +1 -2
- package/dist/services/EdgeApiClient.js +1 -7
- package/dist/services/LegacyEventPayloadMapper.d.ts +15 -0
- package/dist/services/LegacyEventPayloadMapper.js +102 -0
- 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/services/cache/cacheKeysHelpers.d.ts +9 -0
- package/dist/services/cache/cacheKeysHelpers.js +55 -0
- package/dist/services/cache/cacheService.d.ts +10 -28
- package/dist/services/cache/entities/cachedEntitlement.d.ts +20 -0
- package/dist/services/cache/entities/cachedEntitlement.js +53 -0
- package/dist/services/cache/entities/calculatedEntitlement.d.ts +34 -0
- package/dist/services/cache/entities/calculatedEntitlement.js +3 -0
- package/dist/services/cache/entities/entitlementQuery.d.ts +8 -0
- package/dist/services/cache/entities/entitlementQuery.js +3 -0
- package/dist/services/cache/entities/entitlementsMap.d.ts +33 -0
- package/dist/services/cache/entities/entitlementsMap.js +92 -0
- package/dist/services/cache/entities/index.d.ts +6 -0
- package/dist/services/cache/entities/index.js +12 -0
- package/dist/services/cache/entities/usageData.d.ts +11 -0
- package/dist/services/cache/entities/usageData.js +9 -0
- 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 +19 -14
- package/dist/services/cache/inMemoryCacheService.js +44 -69
- 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 +54 -17
- package/dist/services/cache/redisCacheService.js +293 -159
- 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 +14 -2
- package/dist/services/entitlementDecisionService.js +41 -14
- package/dist/services/entitlementsService.d.ts +26 -23
- package/dist/services/entitlementsService.js +126 -110
- package/dist/services/entitlementsService.utils.d.ts +1 -28
- 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 +52 -59
- package/dist/services/redisEntitlementsService.d.ts +5 -4
- package/dist/services/redisEntitlementsService.js +2 -2
- package/dist/types.d.ts +2 -0
- package/dist/utils/ModelMapper.d.ts +8 -7
- package/dist/utils/ModelMapper.js +17 -3
- package/dist/{services/cache → utils}/calculateUsagePeriod.js +1 -1
- package/package.json +18 -1
- package/dist/services/cache/cachedEntitlement.d.ts +0 -29
- package/dist/services/cache/cachedEntitlement.js +0 -10
- package/dist/services/cacheInstrumentation.d.ts +0 -18
- package/dist/services/cacheInstrumentation.js +0 -19
- package/dist/utils/CacheMapper.d.ts +0 -6
- package/dist/utils/CacheMapper.js +0 -57
- package/dist/utils/cacheKeysHelpers.d.ts +0 -7
- package/dist/utils/cacheKeysHelpers.js +0 -42
- /package/dist/{services/cache → utils}/calculateUsagePeriod.d.ts +0 -0
|
@@ -4,30 +4,38 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.RedisCacheService = void 0;
|
|
7
|
-
const
|
|
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
|
-
const featureTypes_1 = require("../../utils/featureTypes");
|
|
15
17
|
const distributedLocks_1 = require("./redis/distributedLocks");
|
|
18
|
+
const accessDeniedReasonMapper_1 = require("./accessDeniedReasonMapper");
|
|
16
19
|
const GRACE_CONNECT_TIMEOUT_MS = 250;
|
|
17
20
|
const READY_STATUSES = ['connect', 'ready'];
|
|
18
21
|
class RedisCacheService {
|
|
19
|
-
constructor(options, loggerService, cacheInstrumentation) {
|
|
22
|
+
constructor(options, loggerService, cacheInstrumentation, cacheMapper) {
|
|
20
23
|
this.loggerService = loggerService;
|
|
21
24
|
this.cacheInstrumentation = cacheInstrumentation;
|
|
22
|
-
|
|
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;
|
|
23
28
|
const { environmentPrefix, ttl = redisCacheService_constants_1.DEFAULT_TTL_SECS, distributedEntitlementsFetching = {} } = redisOptions;
|
|
24
29
|
this.redisClient = new ioredis_1.default(redisOptions);
|
|
25
|
-
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;
|
|
26
33
|
this.environmentPrefix = environmentPrefix;
|
|
27
34
|
this.ttl = ttl;
|
|
28
35
|
this.redisClient.on('error', (err) => {
|
|
36
|
+
var _a, _b;
|
|
29
37
|
this.loggerService.error('Redis client error: ', err);
|
|
30
|
-
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' });
|
|
31
39
|
});
|
|
32
40
|
this.redisClient.on('connect', () => {
|
|
33
41
|
this.loggerService.log('Redis client connected!');
|
|
@@ -48,7 +56,12 @@ class RedisCacheService {
|
|
|
48
56
|
*/
|
|
49
57
|
waitForInitialization() {
|
|
50
58
|
return new Promise((resolve) => {
|
|
51
|
-
//
|
|
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
|
+
}
|
|
52
65
|
if (this.isClientConnected()) {
|
|
53
66
|
resolve();
|
|
54
67
|
return;
|
|
@@ -82,85 +95,106 @@ class RedisCacheService {
|
|
|
82
95
|
isClientConnected() {
|
|
83
96
|
return READY_STATUSES.includes(this.redisClient.status);
|
|
84
97
|
}
|
|
85
|
-
async
|
|
86
|
-
return this.executeSafely('
|
|
87
|
-
|
|
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;
|
|
110
|
+
}
|
|
111
|
+
const item = this.getUsageItemToUpdate({
|
|
112
|
+
customerId,
|
|
113
|
+
resourceId,
|
|
114
|
+
entitlementReference,
|
|
115
|
+
usage,
|
|
116
|
+
usageTimestamp,
|
|
117
|
+
});
|
|
88
118
|
await this.updateCacheItems([item]);
|
|
89
|
-
return true;
|
|
90
119
|
});
|
|
91
120
|
}
|
|
92
|
-
|
|
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;
|
|
93
127
|
const value = {
|
|
94
128
|
currentUsage,
|
|
95
129
|
usagePeriodStart,
|
|
96
130
|
usagePeriodEnd,
|
|
97
131
|
};
|
|
98
132
|
return {
|
|
99
|
-
messageTimestamp:
|
|
100
|
-
key: (0, cacheKeysHelpers_1.buildRedisUsageKey)(this.environmentPrefix, customerId,
|
|
133
|
+
messageTimestamp: usageTimestamp,
|
|
134
|
+
key: (0, cacheKeysHelpers_1.buildRedisUsageKey)(this.environmentPrefix, customerId, entitlementReference, resourceId),
|
|
101
135
|
value,
|
|
102
136
|
};
|
|
103
137
|
}
|
|
104
|
-
async setCustomer(customerId,
|
|
105
|
-
|
|
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);
|
|
106
143
|
const lockKey = (0, cacheKeysHelpers_1.buildLockKey)(this.environmentPrefix, customerId, resourceId);
|
|
107
144
|
await this.distributedLocks.using(lockKey, async () => {
|
|
108
|
-
const { customerKey, metadataKey } = (0, cacheKeysHelpers_1.buildRedisCustomerKey)(this.environmentPrefix, customerId, resourceId);
|
|
109
145
|
const entitlementsItem = {
|
|
110
146
|
messageTimestamp: new Date(entitlementsTimestamp),
|
|
111
147
|
key: customerKey,
|
|
112
|
-
value:
|
|
148
|
+
value: entitlements.toJSON(),
|
|
149
|
+
};
|
|
150
|
+
const metadata = {
|
|
151
|
+
accessDeniedReason: (0, accessDeniedReasonMapper_1.mapAccessDeniedReason)(accessDeniedReason),
|
|
113
152
|
};
|
|
114
|
-
const metadata = { accessDeniedReason };
|
|
115
153
|
const metadataItem = {
|
|
116
154
|
messageTimestamp: new Date(entitlementsTimestamp),
|
|
117
155
|
key: metadataKey,
|
|
118
156
|
value: metadata,
|
|
119
157
|
};
|
|
120
|
-
const
|
|
158
|
+
const usagesItems = this.extractUsagesToUpdate({
|
|
121
159
|
customerId,
|
|
122
160
|
resourceId,
|
|
123
|
-
|
|
124
|
-
|
|
161
|
+
entitlements,
|
|
162
|
+
usageUpdatedAtMap,
|
|
125
163
|
});
|
|
126
|
-
await this.updateCacheItems([entitlementsItem, metadataItem, ...
|
|
164
|
+
await this.updateCacheItems([entitlementsItem, metadataItem, ...usagesItems]);
|
|
127
165
|
});
|
|
166
|
+
return freshenedEntitlements;
|
|
128
167
|
});
|
|
129
168
|
}
|
|
130
|
-
|
|
131
|
-
return (0, lodash_1.compact)(
|
|
132
|
-
.
|
|
169
|
+
extractUsagesToUpdate({ customerId, resourceId, entitlements, usageUpdatedAtMap, }) {
|
|
170
|
+
return (0, lodash_1.compact)(entitlements
|
|
171
|
+
.values()
|
|
172
|
+
.filter((entitlement) => entitlement.isUsageTrackable())
|
|
133
173
|
.map((entitlement) => {
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
customerId,
|
|
138
|
-
resourceId,
|
|
139
|
-
});
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
const featureId = feature.id;
|
|
143
|
-
const featureUsageTimestamp = featureIdToUsageTimestamp.get(featureId);
|
|
144
|
-
if (!featureUsageTimestamp) {
|
|
145
|
-
this.loggerService.error(`Usage timestamp for feature is missing`, {
|
|
146
|
-
customerId,
|
|
147
|
-
resourceId,
|
|
148
|
-
featureId,
|
|
149
|
-
});
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
return this.getFeatureUsageItemToUpdate({
|
|
174
|
+
const entitlementReference = entitlement.getEntitlementQuery();
|
|
175
|
+
const usageTimestamp = this.getUsageTimestamp(usageUpdatedAtMap, entitlementReference);
|
|
176
|
+
return this.getUsageItemToUpdate({
|
|
153
177
|
customerId,
|
|
154
178
|
resourceId,
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
usagePeriodEnd,
|
|
159
|
-
timestamp: new Date(featureUsageTimestamp),
|
|
179
|
+
entitlementReference,
|
|
180
|
+
usage: entitlement.usageData,
|
|
181
|
+
usageTimestamp,
|
|
160
182
|
});
|
|
161
183
|
}));
|
|
162
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
|
+
}
|
|
163
196
|
async getCustomerEntitlementsWithoutUsage(customerId, resourceId) {
|
|
197
|
+
var _a, _b, _c, _d;
|
|
164
198
|
const { customerKey, metadataKey } = (0, cacheKeysHelpers_1.buildRedisCustomerKey)(this.environmentPrefix, customerId, resourceId);
|
|
165
199
|
const keysToFetch = [customerKey, metadataKey];
|
|
166
200
|
if (resourceId) {
|
|
@@ -170,7 +204,7 @@ class RedisCacheService {
|
|
|
170
204
|
}
|
|
171
205
|
const [entitlementsRaw, metadataValue, entitlementsTimestampValue, globalEntitlementsTimestampValue] = await this.redisClient.mget(keysToFetch);
|
|
172
206
|
const entitlements = !(0, lodash_1.isNil)(entitlementsRaw) && !(0, lodash_1.isEmpty)(entitlementsRaw)
|
|
173
|
-
?
|
|
207
|
+
? entities_1.EntitlementsMap.fromJSON(this.migrateOldCacheFormat(JSON.parse(entitlementsRaw)))
|
|
174
208
|
: null;
|
|
175
209
|
let accessDeniedReason = null;
|
|
176
210
|
if (!(0, lodash_1.isNil)(metadataValue) && !(0, lodash_1.isEmpty)(metadataValue)) {
|
|
@@ -181,12 +215,12 @@ class RedisCacheService {
|
|
|
181
215
|
const globalEntitlementsTimestamp = this.parseTimestamp(globalEntitlementsTimestampValue);
|
|
182
216
|
const globalCustomerMissing = this.isGlobalCustomerMissingInCache(customerId, resourceId, entitlements, entitlementsTimestamp, globalEntitlementsTimestamp);
|
|
183
217
|
if (!entitlements || globalCustomerMissing) {
|
|
184
|
-
this.cacheInstrumentation.trackMiss({ customerId, resourceId, globalCustomerMissing });
|
|
185
|
-
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);
|
|
186
220
|
}
|
|
187
221
|
this.loggerService.debug(`Found entitlements in persisted cache for customer`, { customerId, resourceId });
|
|
188
|
-
this.cacheInstrumentation.trackHit({ customerId, resourceId });
|
|
189
|
-
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);
|
|
190
224
|
}
|
|
191
225
|
// resource entitlements are affected by global entitlements, so if global
|
|
192
226
|
// entitlements are missing or newer, we should refetch since the cache is stale
|
|
@@ -211,95 +245,140 @@ class RedisCacheService {
|
|
|
211
245
|
});
|
|
212
246
|
return true;
|
|
213
247
|
}
|
|
214
|
-
async getCustomerEntitlements(
|
|
215
|
-
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;
|
|
216
254
|
const response = await this.getCustomerEntitlementsWithoutUsage(customerId, resourceId);
|
|
217
255
|
if (response.cacheMiss) {
|
|
218
256
|
return response;
|
|
219
257
|
}
|
|
220
|
-
const { entitlements, accessDeniedReason } = response;
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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.`, {
|
|
230
301
|
customerId,
|
|
231
|
-
|
|
232
|
-
missingFeatureIds,
|
|
302
|
+
entitlementRef,
|
|
233
303
|
});
|
|
234
|
-
this.cacheInstrumentation.trackMiss({ customerId, resourceId });
|
|
235
|
-
return entitlementsService_utils_1.entitlementsResponseMapper.cacheMiss();
|
|
236
304
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
entitlements.set(featureKey, this.mergeEntitlementWithUsage(cachedEntitlement, usageValue));
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
this.loggerService.log(`Found usage for a feature the customer is not entitled to.`, {
|
|
244
|
-
customerId,
|
|
245
|
-
featureKey,
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
this.cacheInstrumentation.trackHit({ customerId, resourceId });
|
|
251
|
-
return entitlementsService_utils_1.entitlementsResponseMapper.cacheHit(entitlements, accessDeniedReason);
|
|
252
|
-
});
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
return entitlements;
|
|
253
308
|
}
|
|
254
|
-
async
|
|
255
|
-
const keysToFetch =
|
|
309
|
+
async getUsages(environmentPrefix, customerId, resourceId, entitlementReferences) {
|
|
310
|
+
const keysToFetch = entitlementReferences.map((ref) => (0, cacheKeysHelpers_1.buildRedisUsageKey)(environmentPrefix, customerId, ref, resourceId));
|
|
256
311
|
const usageValues = await this.redisClient.mget(keysToFetch);
|
|
257
|
-
const
|
|
312
|
+
const usageByEntitlementKey = new Map();
|
|
258
313
|
// Redis guarantees returning values in the same order of the keys so this is legit!
|
|
259
|
-
|
|
260
|
-
const
|
|
261
|
-
if (
|
|
262
|
-
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}`);
|
|
263
318
|
return;
|
|
264
319
|
}
|
|
265
|
-
|
|
320
|
+
usageByEntitlementKey.set(entities_1.EntitlementsMap.getUniqueKey(ref), this.migrateUsageData(JSON.parse(usageValue)));
|
|
266
321
|
});
|
|
267
|
-
return
|
|
322
|
+
return usageByEntitlementKey;
|
|
268
323
|
}
|
|
269
324
|
clearCache() {
|
|
270
325
|
return;
|
|
271
326
|
}
|
|
272
327
|
async updateCacheItems(items) {
|
|
328
|
+
var _a, _b, _c, _d;
|
|
273
329
|
if ((0, lodash_1.isEmpty)(items)) {
|
|
274
330
|
return;
|
|
275
331
|
}
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
if (
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const writeableValue = typeof value === 'string' ? value : JSON.stringify(value);
|
|
284
|
-
itemsToUpdate.push({ key, value: writeableValue });
|
|
285
|
-
itemsToUpdate.push({ key: `${key}#${redisCacheService_constants_1.TIMESTAMP_SUFFIX}`, value: messageTimestamp.getTime() });
|
|
286
|
-
}
|
|
287
|
-
else {
|
|
288
|
-
this.loggerService.log('Cache data timestamp is after message timestamp, skipping key update', {
|
|
289
|
-
messageTimestamp,
|
|
290
|
-
latestTimestamp,
|
|
291
|
-
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),
|
|
292
339
|
});
|
|
340
|
+
return;
|
|
293
341
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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);
|
|
297
371
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
}
|
|
302
|
-
|
|
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);
|
|
303
382
|
}
|
|
304
383
|
async getKeysLatestTimestamp(keys) {
|
|
305
384
|
const timestampKeys = keys.map((key) => `${key}#${redisCacheService_constants_1.TIMESTAMP_SUFFIX}`);
|
|
@@ -325,50 +404,104 @@ class RedisCacheService {
|
|
|
325
404
|
await this.distributedLocks.cleanup();
|
|
326
405
|
await ((_a = this.distributedRefetchEntitlementsService) === null || _a === void 0 ? void 0 : _a.cleanup());
|
|
327
406
|
}
|
|
328
|
-
async
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const entitlement = !cacheMiss ? (entitlements === null || entitlements === void 0 ? void 0 : entitlements.get(featureId)) || null : null;
|
|
337
|
-
const result = { cacheMiss, accessDeniedReason, entitlement, globalCustomerMissing };
|
|
338
|
-
if (!entitlement || !(0, featureTypes_1.isMetered)(entitlement === null || entitlement === void 0 ? void 0 : entitlement.calculatedEntitlement.feature)) {
|
|
339
|
-
return result;
|
|
340
|
-
}
|
|
341
|
-
const featuresUsageByFeatureKey = await this.getFeaturesUsage(this.environmentPrefix, customerId, resourceId, [
|
|
342
|
-
featureId,
|
|
343
|
-
]);
|
|
344
|
-
const cachedFeatureUsage = featuresUsageByFeatureKey.get(featureId);
|
|
345
|
-
if ((0, lodash_1.isNil)(cachedFeatureUsage)) {
|
|
346
|
-
this.loggerService.error('Failed to find metered feature usage - considering it as cache miss', {
|
|
347
|
-
customerId,
|
|
348
|
-
resourceId,
|
|
349
|
-
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}`];
|
|
350
415
|
});
|
|
351
|
-
|
|
352
|
-
cacheMiss: true,
|
|
353
|
-
accessDeniedReason: undefined,
|
|
354
|
-
entitlement: null,
|
|
355
|
-
globalCustomerMissing: false,
|
|
356
|
-
};
|
|
416
|
+
await this.redisClient.del(keysToDelete);
|
|
357
417
|
}
|
|
358
|
-
return Object.assign(Object.assign({}, result), { entitlement: this.mergeEntitlementWithUsage(entitlement, cachedFeatureUsage) });
|
|
359
418
|
});
|
|
360
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
|
+
}
|
|
361
427
|
mergeEntitlementWithUsage(entitlement, cachedUsage) {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Migrates old cache format to new format.
|
|
442
|
+
* Handles: featureUsage→usageData rename, adds type discriminator, moves fields,
|
|
443
|
+
* adds updatedAt, adds displayName fallback, nextResetDate→usagePeriodEnd.
|
|
444
|
+
*/
|
|
445
|
+
migrateOldCacheFormat(cacheData) {
|
|
446
|
+
for (const [key, value] of Object.entries(cacheData)) {
|
|
447
|
+
const entry = value;
|
|
448
|
+
if (!(entry === null || entry === void 0 ? void 0 : entry.calculatedEntitlement))
|
|
449
|
+
continue;
|
|
450
|
+
// 1. Rename featureUsage → usageData
|
|
451
|
+
if (entry.featureUsage && !entry.usageData) {
|
|
452
|
+
entry.usageData = entry.featureUsage;
|
|
453
|
+
delete entry.featureUsage;
|
|
454
|
+
}
|
|
455
|
+
// 2. Add type discriminator if missing (old cache only had Feature entitlements)
|
|
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
|
+
}
|
|
462
|
+
entry.calculatedEntitlement.type = entities_1.EntitlementType.Feature;
|
|
463
|
+
}
|
|
464
|
+
// 3. Move fields from usageData to calculatedEntitlement (for Feature type)
|
|
465
|
+
if (entry.usageData && entry.calculatedEntitlement.type === entities_1.EntitlementType.Feature) {
|
|
466
|
+
const fieldsToMove = ['usagePeriodAnchor', 'resetPeriod', 'resetPeriodConfiguration'];
|
|
467
|
+
for (const field of fieldsToMove) {
|
|
468
|
+
if (entry.usageData[field] !== undefined && entry.calculatedEntitlement[field] === undefined) {
|
|
469
|
+
entry.calculatedEntitlement[field] = entry.usageData[field];
|
|
470
|
+
delete entry.usageData[field];
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
// 4. Add updatedAt if missing
|
|
475
|
+
if (entry.usageData && !entry.usageData.updatedAt) {
|
|
476
|
+
entry.usageData.updatedAt = Date.now();
|
|
477
|
+
}
|
|
478
|
+
// 5. Add displayName fallback if missing
|
|
479
|
+
if (entry.calculatedEntitlement.feature && !entry.calculatedEntitlement.feature.displayName) {
|
|
480
|
+
entry.calculatedEntitlement.feature.displayName = entry.calculatedEntitlement.feature.id;
|
|
481
|
+
}
|
|
482
|
+
// 6. Migrate usageData (nextResetDate → usagePeriodEnd)
|
|
483
|
+
if (entry.usageData) {
|
|
484
|
+
entry.usageData = this.migrateUsageData(entry.usageData);
|
|
485
|
+
}
|
|
486
|
+
cacheData[key] = entry;
|
|
368
487
|
}
|
|
369
|
-
return
|
|
488
|
+
return cacheData;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Migrates old usage data format.
|
|
492
|
+
* Handles backward compatibility for old items that have nextResetDate instead of usagePeriodEnd.
|
|
493
|
+
*/
|
|
494
|
+
migrateUsageData(usageData) {
|
|
495
|
+
if (!(0, lodash_1.isNil)(usageData.nextResetDate) && (0, lodash_1.isNil)(usageData.usagePeriodEnd)) {
|
|
496
|
+
return Object.assign(Object.assign({}, (0, lodash_1.omit)(usageData, 'nextResetDate')), { usagePeriodEnd: usageData.nextResetDate });
|
|
497
|
+
}
|
|
498
|
+
return usageData;
|
|
370
499
|
}
|
|
371
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
|
+
}
|
|
372
505
|
if (!this.isClientConnected()) {
|
|
373
506
|
return defaultValue;
|
|
374
507
|
}
|
|
@@ -382,4 +515,5 @@ class RedisCacheService {
|
|
|
382
515
|
}
|
|
383
516
|
}
|
|
384
517
|
exports.RedisCacheService = RedisCacheService;
|
|
385
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkaXNDYWNoZVNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvY2FjaGUvcmVkaXNDYWNoZVNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQ0EsNEVBQXNFO0FBQ3RFLHNEQUE0QjtBQUM1QixtQ0FBb0Y7QUFHcEYsbUVBQXVHO0FBQ3ZHLCtFQUE0RTtBQUM1RSw0RUFLc0M7QUFDdEMsK0VBT3VDO0FBQ3ZDLDJEQUFxRDtBQUVyRCwrREFBNEQ7QUFrQjVELE1BQU0sd0JBQXdCLEdBQUcsR0FBRyxDQUFDO0FBRXJDLE1BQU0sY0FBYyxHQUFhLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBRXRELE1BQWEsaUJBQWlCO0lBUTVCLFlBQ0UsT0FBc0MsRUFDckIsYUFBNEIsRUFDNUIsb0JBQTBDO1FBRDFDLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBQzVCLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBc0I7UUFFM0QsTUFBTSxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsbUJBQW1CLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFDN0QsTUFBTSxFQUFFLGlCQUFpQixFQUFFLEdBQUcsR0FBRyw4Q0FBZ0IsRUFBRSwrQkFBK0IsR0FBRyxFQUFFLEVBQUUsR0FBRyxZQUFZLENBQUM7UUFFekcsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLGlCQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksbUNBQWdCLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxhQUFhLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztRQUNwRyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsaUJBQWlCLENBQUM7UUFDM0MsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFFZixJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFH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
|
|
518
|
+
RedisCacheService.DELETE_CHUNK_SIZE = 1000;
|
|
519
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkaXNDYWNoZVNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvY2FjaGUvcmVkaXNDYWNoZVNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBUUEseUNBQThHO0FBRTlHLHNEQUE0QjtBQUM1QixtQ0FBd0U7QUFFeEUsbUVBQXdGO0FBQ3hGLHlEQUE2RjtBQUM3RiwrRUFBNEU7QUFDNUUseURBSytCO0FBQy9CLHVFQUFvRTtBQUVwRSw2RUFBMEU7QUFDMUUsK0VBTXVDO0FBQ3ZDLCtEQUE0RDtBQUc1RCx5RUFBbUU7QUFpQm5FLE1BQU0sd0JBQXdCLEdBQUcsR0FBRyxDQUFDO0FBRXJDLE1BQU0sY0FBYyxHQUFhLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBRXRELE1BQWEsaUJBQWlCO0lBYTVCLFlBQ0UsT0FBZ0MsRUFDZixhQUF5QixFQUN6QixvQkFBMEMsRUFDMUMsV0FBK0I7UUFGL0Isa0JBQWEsR0FBYixhQUFhLENBQVk7UUFDekIseUJBQW9CLEdBQXBCLG9CQUFvQixDQUFzQjtRQUMxQyxnQkFBVyxHQUFYLFdBQVcsQ0FBb0I7UUFSakMsWUFBTyxHQUFHLElBQUksNkNBQXFCLEVBQUUsQ0FBQztRQVVyRCxNQUFNLEVBQ0osS0FBSyxFQUFFLFlBQVksRUFDbkIsbUJBQW1CLEdBQUcsNkRBQStCLEVBQ3JELGlCQUFpQixHQUFHLHNDQUFpQixDQUFDLE1BQU0sRUFDNUMsWUFBWSxFQUNaLGVBQWUsR0FBRyxLQUFLLEdBQ3hCLEdBQUcsT0FBTyxDQUFDO1FBQ1osTUFBTSxFQUFFLGlCQUFpQixFQUFFLEdBQUcsR0FBRyw4Q0FBZ0IsRUFBRSwrQkFBK0IsR0FBRyxFQUFFLEVBQUUsR0FBRyxZQUFZLENBQUM7UUFFekcsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLGlCQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLGdCQUFnQixHQUFH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
|