@monorise/core 0.1.2 → 0.1.3
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/base/utils/index.js +2 -9
- package/dist/base/utils/index.js.map +1 -1
- package/dist/core/controllers/entity/create-entity.controller.js +39 -32
- package/dist/core/controllers/entity/create-entity.controller.js.map +1 -1
- package/dist/core/controllers/entity/delete-entity.controller.js +26 -20
- package/dist/core/controllers/entity/delete-entity.controller.js.map +1 -1
- package/dist/core/controllers/entity/get-entity-by-unique-field-value.controller.js +25 -17
- package/dist/core/controllers/entity/get-entity-by-unique-field-value.controller.js.map +1 -1
- package/dist/core/controllers/entity/get-entity.controller.js +25 -17
- package/dist/core/controllers/entity/get-entity.controller.js.map +1 -1
- package/dist/core/controllers/entity/list-entities.controller.js +39 -36
- package/dist/core/controllers/entity/list-entities.controller.js.map +1 -1
- package/dist/core/controllers/entity/update-entity.controller.js +40 -33
- package/dist/core/controllers/entity/update-entity.controller.js.map +1 -1
- package/dist/core/controllers/entity/upsert-entity.controller.js +64 -59
- package/dist/core/controllers/entity/upsert-entity.controller.js.map +1 -1
- package/dist/core/controllers/mutual/create-mutual.controller.js +42 -38
- package/dist/core/controllers/mutual/create-mutual.controller.js.map +1 -1
- package/dist/core/controllers/mutual/delete-mutual.controller.js +28 -22
- package/dist/core/controllers/mutual/delete-mutual.controller.js.map +1 -1
- package/dist/core/controllers/mutual/get-mutual.controller.js +25 -17
- package/dist/core/controllers/mutual/get-mutual.controller.js.map +1 -1
- package/dist/core/controllers/mutual/list-entities-by-entity.controller.js +52 -44
- package/dist/core/controllers/mutual/list-entities-by-entity.controller.js.map +1 -1
- package/dist/core/controllers/mutual/update-mutual.controller.js +38 -32
- package/dist/core/controllers/mutual/update-mutual.controller.js.map +1 -1
- package/dist/core/controllers/tag/list-tags.controller.js +39 -31
- package/dist/core/controllers/tag/list-tags.controller.js.map +1 -1
- package/dist/core/data/DbUtils.js +23 -12
- package/dist/core/data/DbUtils.js.map +1 -1
- package/dist/core/data/Entity.js +298 -334
- package/dist/core/data/Entity.js.map +1 -1
- package/dist/core/data/EventUtils.js +35 -27
- package/dist/core/data/EventUtils.js.map +1 -1
- package/dist/core/data/Mutual.js +282 -342
- package/dist/core/data/Mutual.js.map +1 -1
- package/dist/core/data/Tag.js +225 -228
- package/dist/core/data/Tag.js.map +1 -1
- package/dist/core/data/abstract/Repository.base.js +4 -7
- package/dist/core/data/abstract/Repository.base.js.map +1 -1
- package/dist/core/errors/extendable-error.js +0 -7
- package/dist/core/errors/extendable-error.js.map +1 -1
- package/dist/core/errors/standard-error.js +0 -3
- package/dist/core/errors/standard-error.js.map +1 -1
- package/dist/core/helpers/event.js +35 -34
- package/dist/core/helpers/event.js.map +1 -1
- package/dist/core/helpers/test/test-utils.js +60 -58
- package/dist/core/helpers/test/test-utils.js.map +1 -1
- package/dist/core/index.js +0 -8
- package/dist/core/index.js.map +1 -1
- package/dist/core/processors/create-entity-processor.js +12 -3
- package/dist/core/processors/create-entity-processor.js.map +1 -1
- package/dist/core/processors/mutual-processor.js +33 -23
- package/dist/core/processors/mutual-processor.js.map +1 -1
- package/dist/core/processors/prejoin-processor.js +117 -105
- package/dist/core/processors/prejoin-processor.js.map +1 -1
- package/dist/core/processors/replication-processor.js +27 -26
- package/dist/core/processors/replication-processor.js.map +1 -1
- package/dist/core/processors/tag-processor.js +47 -35
- package/dist/core/processors/tag-processor.js.map +1 -1
- package/dist/core/services/DependencyContainer.js +0 -4
- package/dist/core/services/DependencyContainer.js.map +1 -1
- package/dist/core/services/entity-service-lifecycle.js +29 -20
- package/dist/core/services/entity-service-lifecycle.js.map +1 -1
- package/dist/core/services/entity.service.js +95 -92
- package/dist/core/services/entity.service.js.map +1 -1
- package/dist/core/services/mutual.service.js +117 -113
- package/dist/core/services/mutual.service.js.map +1 -1
- package/package.json +1 -1
package/dist/core/data/Mutual.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
1
10
|
import { BatchStatementErrorCodeEnum, TransactionCanceledException, } from '@aws-sdk/client-dynamodb';
|
|
2
11
|
import { marshall, unmarshall } from '@aws-sdk/util-dynamodb';
|
|
3
12
|
import { ulid } from 'ulid';
|
|
@@ -6,18 +15,6 @@ import { sleep } from '../helpers/sleep';
|
|
|
6
15
|
import { PROJECTION_EXPRESSION, } from './ProjectionExpression';
|
|
7
16
|
import { Repository } from './abstract/Repository.base';
|
|
8
17
|
export class Mutual {
|
|
9
|
-
byEntityType;
|
|
10
|
-
byEntityId;
|
|
11
|
-
byData;
|
|
12
|
-
entityType;
|
|
13
|
-
entityId;
|
|
14
|
-
data;
|
|
15
|
-
mutualData;
|
|
16
|
-
mutualId;
|
|
17
|
-
_createdAt;
|
|
18
|
-
_updatedAt;
|
|
19
|
-
_mutualUpdatedAt;
|
|
20
|
-
_expiresAt;
|
|
21
18
|
constructor(byEntityType, byEntityId, byData, entityType, entityId, data, mutualData, mutualId, _createdAt, _updatedAt, _mutualUpdatedAt, _expiresAt) {
|
|
22
19
|
this.byEntityType = byEntityType;
|
|
23
20
|
this.byEntityId = byEntityId;
|
|
@@ -68,37 +65,28 @@ export class Mutual {
|
|
|
68
65
|
return '#METADATA#';
|
|
69
66
|
}
|
|
70
67
|
get createdAt() {
|
|
71
|
-
|
|
68
|
+
var _a;
|
|
69
|
+
return (_a = this._createdAt) === null || _a === void 0 ? void 0 : _a.toISOString();
|
|
72
70
|
}
|
|
73
71
|
get updatedAt() {
|
|
74
|
-
|
|
72
|
+
var _a;
|
|
73
|
+
return (_a = this._updatedAt) === null || _a === void 0 ? void 0 : _a.toISOString();
|
|
75
74
|
}
|
|
76
75
|
get mutualUpdatedAt() {
|
|
77
|
-
|
|
76
|
+
var _a;
|
|
77
|
+
return (_a = this._mutualUpdatedAt) === null || _a === void 0 ? void 0 : _a.toISOString();
|
|
78
78
|
}
|
|
79
79
|
get expiresAt() {
|
|
80
|
-
|
|
80
|
+
var _a;
|
|
81
|
+
return (_a = this._expiresAt) === null || _a === void 0 ? void 0 : _a.toISOString();
|
|
81
82
|
}
|
|
82
83
|
toItem() {
|
|
83
|
-
return {
|
|
84
|
-
...marshall(this.toJSON(), { removeUndefinedValues: true }),
|
|
85
|
-
...this.mainKeys(),
|
|
86
|
-
};
|
|
84
|
+
return Object.assign(Object.assign({}, marshall(this.toJSON(), { removeUndefinedValues: true })), this.mainKeys());
|
|
87
85
|
}
|
|
88
86
|
toReversedItem() {
|
|
89
87
|
const item = this.toJSON();
|
|
90
|
-
const reversedMutual = {
|
|
91
|
-
|
|
92
|
-
byEntityType: item.entityType,
|
|
93
|
-
byEntityId: item.entityId,
|
|
94
|
-
entityType: item.byEntityType,
|
|
95
|
-
entityId: item.byEntityId,
|
|
96
|
-
data: this.byData,
|
|
97
|
-
};
|
|
98
|
-
return {
|
|
99
|
-
...marshall(reversedMutual, { removeUndefinedValues: true }),
|
|
100
|
-
...this.mainKeys(),
|
|
101
|
-
};
|
|
88
|
+
const reversedMutual = Object.assign(Object.assign({}, item), { byEntityType: item.entityType, byEntityId: item.entityId, entityType: item.byEntityType, entityId: item.byEntityId, data: this.byData });
|
|
89
|
+
return Object.assign(Object.assign({}, marshall(reversedMutual, { removeUndefinedValues: true })), this.mainKeys());
|
|
102
90
|
}
|
|
103
91
|
toJSON() {
|
|
104
92
|
return {
|
|
@@ -117,380 +105,332 @@ export class Mutual {
|
|
|
117
105
|
}
|
|
118
106
|
}
|
|
119
107
|
export class MutualRepository extends Repository {
|
|
120
|
-
TABLE_NAME;
|
|
121
|
-
dynamodbClient;
|
|
122
|
-
ddbUtils;
|
|
123
108
|
constructor(TABLE_NAME, dynamodbClient, ddbUtils) {
|
|
124
109
|
super();
|
|
125
110
|
this.TABLE_NAME = TABLE_NAME;
|
|
126
111
|
this.dynamodbClient = dynamodbClient;
|
|
127
112
|
this.ddbUtils = ddbUtils;
|
|
128
113
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
'#
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
':PK': {
|
|
142
|
-
S: mutual.byFullEntityId,
|
|
114
|
+
listEntitiesByEntity(byEntityType_1, byEntityId_1, entityType_1) {
|
|
115
|
+
return __awaiter(this, arguments, void 0, function* (byEntityType, byEntityId, entityType, opts = {}) {
|
|
116
|
+
var _a, _b, _c, _d;
|
|
117
|
+
const mutual = new Mutual(byEntityType, byEntityId, {}, entityType, 'list_by_only', {}, {});
|
|
118
|
+
const listAssociationsQuery = {
|
|
119
|
+
TableName: this.TABLE_NAME,
|
|
120
|
+
KeyConditionExpression: '#PK = :PK and begins_with(#SK, :SK)',
|
|
121
|
+
FilterExpression: 'attribute_not_exists(#expiresAt) or attribute_type(#expiresAt, :nullType)',
|
|
122
|
+
ExpressionAttributeNames: {
|
|
123
|
+
'#PK': 'PK',
|
|
124
|
+
'#SK': 'SK',
|
|
125
|
+
'#expiresAt': 'expiresAt',
|
|
143
126
|
},
|
|
144
|
-
|
|
145
|
-
|
|
127
|
+
ExpressionAttributeValues: {
|
|
128
|
+
':PK': {
|
|
129
|
+
S: mutual.byFullEntityId,
|
|
130
|
+
},
|
|
131
|
+
':SK': {
|
|
132
|
+
S: `${mutual.listEntitySK}#`,
|
|
133
|
+
},
|
|
134
|
+
':nullType': { S: 'NULL' },
|
|
146
135
|
},
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
do {
|
|
155
|
-
const resp = await this.dynamodbClient.query({
|
|
156
|
-
...listAssociationsQuery,
|
|
157
|
-
...(remainingCount && { Limit: remainingCount }),
|
|
158
|
-
...(lastKey && {
|
|
136
|
+
ProjectionExpression: opts.ProjectionExpression,
|
|
137
|
+
};
|
|
138
|
+
let lastKey = opts.lastKey;
|
|
139
|
+
let items = [];
|
|
140
|
+
let remainingCount = (_a = opts.limit) !== null && _a !== void 0 ? _a : 0;
|
|
141
|
+
do {
|
|
142
|
+
const resp = yield this.dynamodbClient.query(Object.assign(Object.assign(Object.assign({}, listAssociationsQuery), (remainingCount && { Limit: remainingCount })), (lastKey && {
|
|
159
143
|
ExclusiveStartKey: lastKey,
|
|
160
|
-
})
|
|
144
|
+
})));
|
|
145
|
+
items = items.concat(((_b = resp.Items) === null || _b === void 0 ? void 0 : _b.map((item) => Mutual.fromItem(item))) || []);
|
|
146
|
+
lastKey = resp.LastEvaluatedKey;
|
|
147
|
+
if (opts.limit) {
|
|
148
|
+
remainingCount = remainingCount - ((_d = (_c = resp.Items) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0);
|
|
149
|
+
}
|
|
150
|
+
} while (
|
|
151
|
+
// limit is given, haven't reach limit, and there are still items to retrieve
|
|
152
|
+
(opts.limit && remainingCount && lastKey) ||
|
|
153
|
+
// no limit is given and there are still items to retrieve
|
|
154
|
+
(!opts.limit && lastKey));
|
|
155
|
+
return {
|
|
156
|
+
items,
|
|
157
|
+
lastKey,
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
getMutual(byEntityType, byEntityId, entityType, entityId, opts) {
|
|
162
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
163
|
+
var _a, _b;
|
|
164
|
+
const mutual = new Mutual(byEntityType, byEntityId, {}, entityType, entityId, {}, {});
|
|
165
|
+
const resp = yield this.dynamodbClient.query({
|
|
166
|
+
TableName: this.TABLE_NAME,
|
|
167
|
+
KeyConditionExpression: '#PK = :PK and begins_with(#SK, :SK)',
|
|
168
|
+
FilterExpression: 'attribute_not_exists(#expiresAt) or attribute_type(#expiresAt, :nullType)',
|
|
169
|
+
ExpressionAttributeNames: {
|
|
170
|
+
'#PK': 'PK',
|
|
171
|
+
'#SK': 'SK',
|
|
172
|
+
'#expiresAt': 'expiresAt',
|
|
173
|
+
},
|
|
174
|
+
ExpressionAttributeValues: {
|
|
175
|
+
':PK': { S: mutual.byFullEntityId },
|
|
176
|
+
':SK': { S: mutual.fullEntityId },
|
|
177
|
+
':nullType': { S: 'NULL' },
|
|
178
|
+
},
|
|
179
|
+
Limit: 1,
|
|
161
180
|
});
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
181
|
+
let mutualMetadata = null;
|
|
182
|
+
if (opts === null || opts === void 0 ? void 0 : opts.isFromMetadata) {
|
|
183
|
+
const tempMutual = Mutual.fromItem((_a = resp.Items) === null || _a === void 0 ? void 0 : _a[0]);
|
|
184
|
+
const respMetadataMutual = yield this.dynamodbClient.getItem({
|
|
185
|
+
TableName: this.TABLE_NAME,
|
|
186
|
+
Key: tempMutual.mainKeys(),
|
|
187
|
+
ProjectionExpression: opts === null || opts === void 0 ? void 0 : opts.ProjectionExpression,
|
|
188
|
+
});
|
|
189
|
+
mutualMetadata = Mutual.fromItem(respMetadataMutual.Item);
|
|
166
190
|
}
|
|
167
|
-
|
|
168
|
-
// limit is given, haven't reach limit, and there are still items to retrieve
|
|
169
|
-
(opts.limit && remainingCount && lastKey) ||
|
|
170
|
-
// no limit is given and there are still items to retrieve
|
|
171
|
-
(!opts.limit && lastKey));
|
|
172
|
-
return {
|
|
173
|
-
items,
|
|
174
|
-
lastKey,
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
async getMutual(byEntityType, byEntityId, entityType, entityId, opts) {
|
|
178
|
-
const mutual = new Mutual(byEntityType, byEntityId, {}, entityType, entityId, {}, {});
|
|
179
|
-
const resp = await this.dynamodbClient.query({
|
|
180
|
-
TableName: this.TABLE_NAME,
|
|
181
|
-
KeyConditionExpression: '#PK = :PK and begins_with(#SK, :SK)',
|
|
182
|
-
FilterExpression: 'attribute_not_exists(#expiresAt) or attribute_type(#expiresAt, :nullType)',
|
|
183
|
-
ExpressionAttributeNames: {
|
|
184
|
-
'#PK': 'PK',
|
|
185
|
-
'#SK': 'SK',
|
|
186
|
-
'#expiresAt': 'expiresAt',
|
|
187
|
-
},
|
|
188
|
-
ExpressionAttributeValues: {
|
|
189
|
-
':PK': { S: mutual.byFullEntityId },
|
|
190
|
-
':SK': { S: mutual.fullEntityId },
|
|
191
|
-
':nullType': { S: 'NULL' },
|
|
192
|
-
},
|
|
193
|
-
Limit: 1,
|
|
191
|
+
return mutualMetadata || Mutual.fromItem((_b = resp.Items) === null || _b === void 0 ? void 0 : _b[0]);
|
|
194
192
|
});
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
193
|
+
}
|
|
194
|
+
checkMutualExist(byEntityType, byEntityId, entityType, entityId) {
|
|
195
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
196
|
+
var _a;
|
|
197
|
+
const mutual = new Mutual(byEntityType, byEntityId, {}, entityType, entityId, {}, {});
|
|
198
|
+
const resp = yield this.dynamodbClient.getItem({
|
|
199
199
|
TableName: this.TABLE_NAME,
|
|
200
|
-
Key:
|
|
201
|
-
ProjectionExpression:
|
|
200
|
+
Key: mutual.subKeys(),
|
|
201
|
+
ProjectionExpression: 'PK, SK, expiresAt',
|
|
202
202
|
});
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
async checkMutualExist(byEntityType, byEntityId, entityType, entityId) {
|
|
208
|
-
const mutual = new Mutual(byEntityType, byEntityId, {}, entityType, entityId, {}, {});
|
|
209
|
-
const resp = await this.dynamodbClient.getItem({
|
|
210
|
-
TableName: this.TABLE_NAME,
|
|
211
|
-
Key: mutual.subKeys(),
|
|
212
|
-
ProjectionExpression: 'PK, SK, expiresAt',
|
|
203
|
+
if (resp.Item && !((_a = resp.Item) === null || _a === void 0 ? void 0 : _a.expiresAt)) {
|
|
204
|
+
throw new StandardError('MUTUAL_EXISTS', 'Entities are already linked');
|
|
205
|
+
}
|
|
206
|
+
return;
|
|
213
207
|
});
|
|
214
|
-
if (resp.Item && !resp.Item?.expiresAt) {
|
|
215
|
-
throw new StandardError('MUTUAL_EXISTS', 'Entities are already linked');
|
|
216
|
-
}
|
|
217
|
-
return;
|
|
218
208
|
}
|
|
219
209
|
createMutualTransactItems(mutual, opts) {
|
|
220
210
|
const TransactItems = [
|
|
221
211
|
{
|
|
222
212
|
Put: {
|
|
223
213
|
TableName: this.TABLE_NAME,
|
|
224
|
-
ConditionExpression: opts
|
|
214
|
+
ConditionExpression: (opts === null || opts === void 0 ? void 0 : opts.ConditionExpression) ||
|
|
225
215
|
'attribute_not_exists(PK) OR attribute_exists(expiresAt)',
|
|
226
|
-
ExpressionAttributeNames: opts
|
|
227
|
-
ExpressionAttributeValues: opts
|
|
216
|
+
ExpressionAttributeNames: opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeNames,
|
|
217
|
+
ExpressionAttributeValues: opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeValues,
|
|
228
218
|
Item: mutual.toItem(),
|
|
229
219
|
},
|
|
230
220
|
},
|
|
231
221
|
{
|
|
232
222
|
Put: {
|
|
233
223
|
TableName: this.TABLE_NAME,
|
|
234
|
-
ConditionExpression: opts
|
|
224
|
+
ConditionExpression: (opts === null || opts === void 0 ? void 0 : opts.ConditionExpression) ||
|
|
235
225
|
'attribute_not_exists(PK) OR attribute_exists(expiresAt)',
|
|
236
|
-
ExpressionAttributeNames: opts
|
|
237
|
-
ExpressionAttributeValues: opts
|
|
238
|
-
Item: {
|
|
239
|
-
...mutual.toItem(),
|
|
240
|
-
PK: { S: mutual.byFullEntityId },
|
|
241
|
-
SK: { S: mutual.fullEntityId },
|
|
242
|
-
R1PK: { S: mutual.fullEntityId },
|
|
243
|
-
R1SK: { S: mutual.byFullEntityId },
|
|
244
|
-
R2PK: { S: mutual.mainPk },
|
|
245
|
-
R2SK: { S: mutual.byFullEntityId },
|
|
246
|
-
},
|
|
226
|
+
ExpressionAttributeNames: opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeNames,
|
|
227
|
+
ExpressionAttributeValues: opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeValues,
|
|
228
|
+
Item: Object.assign(Object.assign({}, mutual.toItem()), { PK: { S: mutual.byFullEntityId }, SK: { S: mutual.fullEntityId }, R1PK: { S: mutual.fullEntityId }, R1SK: { S: mutual.byFullEntityId }, R2PK: { S: mutual.mainPk }, R2SK: { S: mutual.byFullEntityId } }),
|
|
247
229
|
},
|
|
248
230
|
},
|
|
249
231
|
{
|
|
250
232
|
Put: {
|
|
251
233
|
TableName: this.TABLE_NAME,
|
|
252
|
-
ConditionExpression: opts
|
|
234
|
+
ConditionExpression: (opts === null || opts === void 0 ? void 0 : opts.ConditionExpression) ||
|
|
253
235
|
'attribute_not_exists(PK) OR attribute_exists(expiresAt)',
|
|
254
|
-
ExpressionAttributeNames: opts
|
|
255
|
-
ExpressionAttributeValues: opts
|
|
256
|
-
Item: {
|
|
257
|
-
...mutual.toReversedItem(),
|
|
258
|
-
PK: { S: mutual.fullEntityId },
|
|
259
|
-
SK: { S: mutual.byFullEntityId },
|
|
260
|
-
R1PK: { S: mutual.byFullEntityId },
|
|
261
|
-
R1SK: { S: mutual.fullEntityId },
|
|
262
|
-
R2PK: { S: mutual.mainPk },
|
|
263
|
-
R2SK: { S: mutual.fullEntityId },
|
|
264
|
-
},
|
|
236
|
+
ExpressionAttributeNames: opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeNames,
|
|
237
|
+
ExpressionAttributeValues: opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeValues,
|
|
238
|
+
Item: Object.assign(Object.assign({}, mutual.toReversedItem()), { PK: { S: mutual.fullEntityId }, SK: { S: mutual.byFullEntityId }, R1PK: { S: mutual.byFullEntityId }, R1SK: { S: mutual.fullEntityId }, R2PK: { S: mutual.mainPk }, R2SK: { S: mutual.fullEntityId } }),
|
|
265
239
|
},
|
|
266
240
|
},
|
|
267
241
|
];
|
|
268
242
|
return TransactItems;
|
|
269
243
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
244
|
+
createMutual(byEntityType_1, byEntityId_1, byData_1, entityType_1, entityId_1, data_1) {
|
|
245
|
+
return __awaiter(this, arguments, void 0, function* (byEntityType, byEntityId, byData, entityType, entityId, data, mutualData = {}, opts) {
|
|
246
|
+
const errorContext = {};
|
|
247
|
+
const currentDatetime = (opts === null || opts === void 0 ? void 0 : opts.createAndUpdateDatetime) || new Date();
|
|
248
|
+
const mutual = new Mutual(byEntityType, byEntityId, byData, entityType, entityId, data, mutualData, ulid(), currentDatetime, currentDatetime, currentDatetime);
|
|
249
|
+
const TransactItems = this.createMutualTransactItems(mutual, {
|
|
250
|
+
ConditionExpression: opts === null || opts === void 0 ? void 0 : opts.ConditionExpression,
|
|
251
|
+
ExpressionAttributeNames: opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeNames,
|
|
252
|
+
ExpressionAttributeValues: opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeValues,
|
|
253
|
+
});
|
|
254
|
+
errorContext.TransactItems = TransactItems;
|
|
255
|
+
yield this.dynamodbClient.transactWriteItems({ TransactItems });
|
|
256
|
+
return mutual;
|
|
278
257
|
});
|
|
279
|
-
errorContext.TransactItems = TransactItems;
|
|
280
|
-
await this.dynamodbClient.transactWriteItems({ TransactItems });
|
|
281
|
-
return mutual;
|
|
282
258
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
...toUpdateExpressions.ExpressionAttributeValues,
|
|
302
|
-
...opts?.ExpressionAttributeValues,
|
|
303
|
-
},
|
|
304
|
-
};
|
|
305
|
-
const TransactItems = [
|
|
306
|
-
{
|
|
307
|
-
Update: {
|
|
308
|
-
TableName: this.TABLE_NAME,
|
|
309
|
-
Key: mutual.mainKeys(),
|
|
310
|
-
...updateExpression,
|
|
259
|
+
updateMutual(byEntityType, byEntityId, entityType, entityId, toUpdate, opts) {
|
|
260
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
261
|
+
var _a;
|
|
262
|
+
const returnUpdatedValue = (_a = opts === null || opts === void 0 ? void 0 : opts.returnUpdatedValue) !== null && _a !== void 0 ? _a : false;
|
|
263
|
+
const errorContext = {};
|
|
264
|
+
try {
|
|
265
|
+
const mutual = yield this.getMutual(byEntityType, byEntityId, entityType, entityId, { ProjectionExpression: PROJECTION_EXPRESSION.NO_DATA });
|
|
266
|
+
const currentDatetime = new Date().toISOString();
|
|
267
|
+
const toUpdateExpressions = this.toUpdate(Object.assign({ mutualUpdatedAt: currentDatetime }, toUpdate), { maxLevel: opts === null || opts === void 0 ? void 0 : opts.maxObjectUpdateLevel });
|
|
268
|
+
const updateExpression = {
|
|
269
|
+
ConditionExpression: (opts === null || opts === void 0 ? void 0 : opts.ConditionExpression) || 'attribute_exists(PK)',
|
|
270
|
+
UpdateExpression: toUpdateExpressions.UpdateExpression,
|
|
271
|
+
ExpressionAttributeNames: Object.assign(Object.assign({}, toUpdateExpressions.ExpressionAttributeNames), opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeNames),
|
|
272
|
+
ExpressionAttributeValues: Object.assign(Object.assign({}, toUpdateExpressions.ExpressionAttributeValues), opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeValues),
|
|
273
|
+
};
|
|
274
|
+
const TransactItems = [
|
|
275
|
+
{
|
|
276
|
+
Update: Object.assign({ TableName: this.TABLE_NAME, Key: mutual.mainKeys() }, updateExpression),
|
|
311
277
|
},
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
PK: { S: mutual.byFullEntityId },
|
|
318
|
-
SK: { S: mutual.fullEntityId },
|
|
319
|
-
},
|
|
320
|
-
...updateExpression,
|
|
278
|
+
{
|
|
279
|
+
Update: Object.assign({ TableName: this.TABLE_NAME, Key: {
|
|
280
|
+
PK: { S: mutual.byFullEntityId },
|
|
281
|
+
SK: { S: mutual.fullEntityId },
|
|
282
|
+
} }, updateExpression),
|
|
321
283
|
},
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
PK: { S: mutual.fullEntityId },
|
|
328
|
-
SK: { S: mutual.byFullEntityId },
|
|
329
|
-
},
|
|
330
|
-
...updateExpression,
|
|
284
|
+
{
|
|
285
|
+
Update: Object.assign({ TableName: this.TABLE_NAME, Key: {
|
|
286
|
+
PK: { S: mutual.fullEntityId },
|
|
287
|
+
SK: { S: mutual.byFullEntityId },
|
|
288
|
+
} }, updateExpression),
|
|
331
289
|
},
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
290
|
+
];
|
|
291
|
+
errorContext.TransactItems = TransactItems;
|
|
292
|
+
yield this.ddbUtils.executeTransactWrite({ TransactItems });
|
|
293
|
+
if (!returnUpdatedValue) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
const updatedMutual = yield this.getMutual(byEntityType, byEntityId, entityType, entityId);
|
|
297
|
+
return updatedMutual;
|
|
338
298
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
});
|
|
299
|
+
catch (err) {
|
|
300
|
+
if (err instanceof StandardError &&
|
|
301
|
+
err.code === 'CONDITIONAL_CHECK_FAILED') {
|
|
302
|
+
throw new StandardError('MUTUAL_NOT_FOUND', 'Mutual not found', err, {
|
|
303
|
+
errorContext,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
throw err;
|
|
348
307
|
}
|
|
349
|
-
|
|
350
|
-
}
|
|
308
|
+
});
|
|
351
309
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
const mutual = await this.getMutual(byEntityType, byEntityId, entityType, entityId, { ProjectionExpression: PROJECTION_EXPRESSION.NO_DATA });
|
|
361
|
-
const tenMinsLater = Math.floor(new Date().getTime() / 1000 + 10 * 60);
|
|
362
|
-
const expressions = {
|
|
363
|
-
UpdateExpression: 'SET #expiresAt = :expiresAt, #mutualUpdatedAt = :mutualUpdatedAt, #updatedAt = :mutualUpdatedAt',
|
|
364
|
-
ConditionExpression: opts?.ConditionExpression ||
|
|
365
|
-
'attribute_exists(PK) AND attribute_not_exists(#expiresAt)',
|
|
366
|
-
ExpressionAttributeNames: {
|
|
367
|
-
'#expiresAt': 'expiresAt',
|
|
368
|
-
'#mutualUpdatedAt': 'mutualUpdatedAt',
|
|
369
|
-
'#updatedAt': 'updatedAt',
|
|
370
|
-
...opts?.ExpressionAttributeNames,
|
|
371
|
-
},
|
|
372
|
-
ExpressionAttributeValues: {
|
|
373
|
-
':expiresAt': { N: String(tenMinsLater) },
|
|
374
|
-
':mutualUpdatedAt': { S: new Date().toISOString() },
|
|
375
|
-
...opts?.ExpressionAttributeValues,
|
|
376
|
-
},
|
|
310
|
+
deleteMutual(byEntityType, byEntityId, entityType, entityId, opts) {
|
|
311
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
312
|
+
var _a;
|
|
313
|
+
const errorContext = {
|
|
314
|
+
byEntityType,
|
|
315
|
+
byEntityId,
|
|
316
|
+
entityType,
|
|
317
|
+
entityId,
|
|
377
318
|
};
|
|
378
|
-
|
|
379
|
-
{
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
319
|
+
try {
|
|
320
|
+
const mutual = yield this.getMutual(byEntityType, byEntityId, entityType, entityId, { ProjectionExpression: PROJECTION_EXPRESSION.NO_DATA });
|
|
321
|
+
const tenMinsLater = Math.floor(new Date().getTime() / 1000 + 10 * 60);
|
|
322
|
+
const expressions = {
|
|
323
|
+
UpdateExpression: 'SET #expiresAt = :expiresAt, #mutualUpdatedAt = :mutualUpdatedAt, #updatedAt = :mutualUpdatedAt',
|
|
324
|
+
ConditionExpression: (opts === null || opts === void 0 ? void 0 : opts.ConditionExpression) ||
|
|
325
|
+
'attribute_exists(PK) AND attribute_not_exists(#expiresAt)',
|
|
326
|
+
ExpressionAttributeNames: Object.assign({ '#expiresAt': 'expiresAt', '#mutualUpdatedAt': 'mutualUpdatedAt', '#updatedAt': 'updatedAt' }, opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeNames),
|
|
327
|
+
ExpressionAttributeValues: Object.assign({ ':expiresAt': { N: String(tenMinsLater) }, ':mutualUpdatedAt': { S: new Date().toISOString() } }, opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeValues),
|
|
328
|
+
};
|
|
329
|
+
const TransactItems = [
|
|
330
|
+
{
|
|
331
|
+
Update: Object.assign({ TableName: this.TABLE_NAME, Key: mutual.mainKeys() }, expressions),
|
|
384
332
|
},
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
PK: { S: mutual.byFullEntityId },
|
|
391
|
-
SK: { S: mutual.fullEntityId },
|
|
392
|
-
},
|
|
393
|
-
...expressions,
|
|
333
|
+
{
|
|
334
|
+
Update: Object.assign({ TableName: this.TABLE_NAME, Key: {
|
|
335
|
+
PK: { S: mutual.byFullEntityId },
|
|
336
|
+
SK: { S: mutual.fullEntityId },
|
|
337
|
+
} }, expressions),
|
|
394
338
|
},
|
|
339
|
+
{
|
|
340
|
+
Update: Object.assign({ TableName: this.TABLE_NAME, Key: {
|
|
341
|
+
PK: { S: mutual.fullEntityId },
|
|
342
|
+
SK: { S: mutual.byFullEntityId },
|
|
343
|
+
} }, expressions),
|
|
344
|
+
},
|
|
345
|
+
];
|
|
346
|
+
errorContext.TransactItems = TransactItems;
|
|
347
|
+
yield this.dynamodbClient.transactWriteItems({ TransactItems });
|
|
348
|
+
return mutual;
|
|
349
|
+
}
|
|
350
|
+
catch (err) {
|
|
351
|
+
const isConditionalCheckFailed = err instanceof TransactionCanceledException &&
|
|
352
|
+
((_a = err.CancellationReasons) === null || _a === void 0 ? void 0 : _a.some((reason) => reason.Code === BatchStatementErrorCodeEnum.ConditionalCheckFailed));
|
|
353
|
+
const isMutualIsUndefined = err instanceof StandardError && err.code === 'MUTUAL_IS_UNDEFINED';
|
|
354
|
+
if (isConditionalCheckFailed || isMutualIsUndefined) {
|
|
355
|
+
throw new StandardError('MUTUAL_NOT_FOUND', 'Mutual not found', err, {
|
|
356
|
+
errorContext,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
throw err;
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
createMutualLock(_a) {
|
|
364
|
+
return __awaiter(this, arguments, void 0, function* ({ byEntityType, byEntityId, entityType, version, }) {
|
|
365
|
+
var _b, _c, _d;
|
|
366
|
+
let retryCount = 2;
|
|
367
|
+
const itemKey = {
|
|
368
|
+
PK: {
|
|
369
|
+
S: `MUTUAL#${byEntityType}#${byEntityId}#${entityType}`,
|
|
395
370
|
},
|
|
396
|
-
{
|
|
397
|
-
|
|
371
|
+
SK: { S: '#LOCK#' },
|
|
372
|
+
};
|
|
373
|
+
do {
|
|
374
|
+
try {
|
|
375
|
+
const fiveMinsLater = Math.floor(new Date().getTime() / 1000 + 5 * 60);
|
|
376
|
+
yield this.dynamodbClient.putItem({
|
|
398
377
|
TableName: this.TABLE_NAME,
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
378
|
+
Item: Object.assign(Object.assign({}, itemKey), { version: { S: version }, status: { S: 'LOCK' }, expiresAt: {
|
|
379
|
+
// auto release lock in case the mutual logic gone wrong to prevent dead lock
|
|
380
|
+
N: `${fiveMinsLater}`,
|
|
381
|
+
} }),
|
|
382
|
+
ConditionExpression: 'attribute_not_exists(PK) OR version < :version AND #status <> :status',
|
|
383
|
+
ExpressionAttributeNames: { '#status': 'status' },
|
|
384
|
+
ExpressionAttributeValues: {
|
|
385
|
+
':version': { S: version },
|
|
386
|
+
':status': { S: 'LOCK' },
|
|
402
387
|
},
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
388
|
+
});
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
catch (err) {
|
|
392
|
+
console.log('=====CATCHED_MUTUAL_LOCK_CONFLICT=====');
|
|
393
|
+
const lock = yield this.dynamodbClient.getItem({
|
|
394
|
+
TableName: this.TABLE_NAME,
|
|
395
|
+
Key: itemKey,
|
|
396
|
+
});
|
|
397
|
+
// if version is lower, throw not retryable error to skip
|
|
398
|
+
const existingVersion = (_d = (_c = (_b = lock.Item) === null || _b === void 0 ? void 0 : _b.version) === null || _c === void 0 ? void 0 : _c.S) !== null && _d !== void 0 ? _d : '';
|
|
399
|
+
const isExistingVersionGreaterThanNewVersion = existingVersion >= version;
|
|
400
|
+
if (isExistingVersionGreaterThanNewVersion) {
|
|
401
|
+
throw new StandardError('MUTUAL_LOCK_CONFLICT', 'Lock conflict', err, { lock: lock.Item });
|
|
402
|
+
}
|
|
403
|
+
// default behaviour
|
|
404
|
+
// if version is higher, retry
|
|
405
|
+
// if lock not found, retry
|
|
406
|
+
yield sleep(2000);
|
|
407
|
+
console.log('=====RETRY_MUTUAL_LOCK=====');
|
|
408
|
+
}
|
|
409
|
+
} while (retryCount-- > 0);
|
|
410
|
+
// catch real unhandled error, so it can reach DLQ for inspection
|
|
411
|
+
throw new StandardError('RETRYABLE_MUTUAL_LOCK_CONFLICT', 'Retryable lock conflict');
|
|
412
|
+
});
|
|
422
413
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
const itemKey = {
|
|
426
|
-
PK: {
|
|
427
|
-
S: `MUTUAL#${byEntityType}#${byEntityId}#${entityType}`,
|
|
428
|
-
},
|
|
429
|
-
SK: { S: '#LOCK#' },
|
|
430
|
-
};
|
|
431
|
-
do {
|
|
414
|
+
deleteMutualLock(_a) {
|
|
415
|
+
return __awaiter(this, arguments, void 0, function* ({ byEntityType, byEntityId, entityType, }) {
|
|
432
416
|
try {
|
|
433
|
-
|
|
434
|
-
await this.dynamodbClient.putItem({
|
|
417
|
+
yield this.dynamodbClient.updateItem({
|
|
435
418
|
TableName: this.TABLE_NAME,
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
status: { S: 'LOCK' },
|
|
440
|
-
expiresAt: {
|
|
441
|
-
// auto release lock in case the mutual logic gone wrong to prevent dead lock
|
|
442
|
-
N: `${fiveMinsLater}`,
|
|
419
|
+
Key: {
|
|
420
|
+
PK: {
|
|
421
|
+
S: `MUTUAL#${byEntityType}#${byEntityId}#${entityType}`,
|
|
443
422
|
},
|
|
423
|
+
SK: { S: '#LOCK#' },
|
|
444
424
|
},
|
|
445
|
-
|
|
425
|
+
UpdateExpression: 'REMOVE #status',
|
|
446
426
|
ExpressionAttributeNames: { '#status': 'status' },
|
|
447
|
-
ExpressionAttributeValues: {
|
|
448
|
-
':version': { S: version },
|
|
449
|
-
':status': { S: 'LOCK' },
|
|
450
|
-
},
|
|
451
427
|
});
|
|
452
428
|
return;
|
|
453
429
|
}
|
|
454
|
-
catch (
|
|
455
|
-
|
|
456
|
-
const lock = await this.dynamodbClient.getItem({
|
|
457
|
-
TableName: this.TABLE_NAME,
|
|
458
|
-
Key: itemKey,
|
|
459
|
-
});
|
|
460
|
-
// if version is lower, throw not retryable error to skip
|
|
461
|
-
const existingVersion = lock.Item?.version?.S ?? '';
|
|
462
|
-
const isExistingVersionGreaterThanNewVersion = existingVersion >= version;
|
|
463
|
-
if (isExistingVersionGreaterThanNewVersion) {
|
|
464
|
-
throw new StandardError('MUTUAL_LOCK_CONFLICT', 'Lock conflict', err, { lock: lock.Item });
|
|
465
|
-
}
|
|
466
|
-
// default behaviour
|
|
467
|
-
// if version is higher, retry
|
|
468
|
-
// if lock not found, retry
|
|
469
|
-
await sleep(2000);
|
|
470
|
-
console.log('=====RETRY_MUTUAL_LOCK=====');
|
|
430
|
+
catch (error) {
|
|
431
|
+
// if lock is not found, it's okay
|
|
471
432
|
}
|
|
472
|
-
}
|
|
473
|
-
// catch real unhandled error, so it can reach DLQ for inspection
|
|
474
|
-
throw new StandardError('RETRYABLE_MUTUAL_LOCK_CONFLICT', 'Retryable lock conflict');
|
|
475
|
-
}
|
|
476
|
-
async deleteMutualLock({ byEntityType, byEntityId, entityType, }) {
|
|
477
|
-
try {
|
|
478
|
-
await this.dynamodbClient.updateItem({
|
|
479
|
-
TableName: this.TABLE_NAME,
|
|
480
|
-
Key: {
|
|
481
|
-
PK: {
|
|
482
|
-
S: `MUTUAL#${byEntityType}#${byEntityId}#${entityType}`,
|
|
483
|
-
},
|
|
484
|
-
SK: { S: '#LOCK#' },
|
|
485
|
-
},
|
|
486
|
-
UpdateExpression: 'REMOVE #status',
|
|
487
|
-
ExpressionAttributeNames: { '#status': 'status' },
|
|
488
|
-
});
|
|
489
|
-
return;
|
|
490
|
-
}
|
|
491
|
-
catch (error) {
|
|
492
|
-
// if lock is not found, it's okay
|
|
493
|
-
}
|
|
433
|
+
});
|
|
494
434
|
}
|
|
495
435
|
}
|
|
496
436
|
//# sourceMappingURL=Mutual.js.map
|