@monorise/core 1.0.4-7 → 3.0.1

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