@chevre/domain 22.9.0-alpha.100 → 22.9.0-alpha.101

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.
@@ -8,8 +8,8 @@ import { PendingReservationRepo } from '../../../../lib/chevre/repo/pendingReser
8
8
  const today = moment()
9
9
  .tz('Asia/Tokyo')
10
10
  .format('YYYYMMDD');
11
- const project = { id: String(process.env.PROJECT_ID) };
12
- const eventId = `sampleEventId${today}`;
11
+ // const project = { id: String(process.env.PROJECT_ID) };
12
+ const eventId = `sampleEventId${today}:01`;
13
13
  const eventStartDate = new Date('2025-05-01T00:00:00Z');
14
14
 
15
15
  const client = redis.createClient<redis.RedisDefaultModules, Record<string, never>, Record<string, never>>({
@@ -27,42 +27,54 @@ const client = redis.createClient<redis.RedisDefaultModules, Record<string, neve
27
27
  client.connect();
28
28
  mongoose.connect(<string>process.env.MONGOLAB_URI, { autoIndex: false });
29
29
 
30
+ const formatter = new Intl.NumberFormat('ja-JP');
31
+
30
32
  // tslint:disable-next-line:max-func-body-length
31
33
  async function main() {
34
+ let startTime: [number, number] = process.hrtime();
35
+ let diff: [number, number] = process.hrtime(startTime);
36
+ let result: any;
37
+
32
38
  // const stockHolderRepo = await chevre.repository.StockHolder.createInstance(client, mongoose.connection);
33
39
  const pendingReservationRepo = new PendingReservationRepo(mongoose.connection);
34
40
 
35
- pendingReservationRepo.countUnavailableOffers({
36
- event: {
37
- id: eventId,
38
- startDate: eventStartDate,
39
- hasTicketedSeat: true
41
+ result = await pendingReservationRepo.countUnavailableOffers(
42
+ {
43
+ event: {
44
+ id: eventId,
45
+ startDate: eventStartDate,
46
+ hasTicketedSeat: true
47
+ }
40
48
  }
41
- })
42
- .then((result) => {
43
- console.log('countUnavailableOffersResult:', result);
44
- });
49
+ );
50
+ console.log('countUnavailableOffersResult:', result);
45
51
 
46
- pendingReservationRepo.countUnavailableOffersByNumSeats({
47
- event: {
48
- id: eventId,
49
- startDate: eventStartDate,
50
- hasTicketedSeat: true
52
+ startTime = process.hrtime();
53
+ result = await pendingReservationRepo.countUnavailableOffersByNumSeats(
54
+ {
55
+ event: {
56
+ id: eventId,
57
+ startDate: eventStartDate,
58
+ hasTicketedSeat: true
59
+ }
60
+ },
61
+ {
62
+ limit: 100
51
63
  }
52
- })
53
- .then((result) => {
54
- console.log('countUnavailableOffersByNumSeatsResult:', result);
55
- });
64
+ );
65
+ diff = process.hrtime(startTime);
66
+ console.log('countUnavailableOffersByNumSeatsResult:', result);
67
+ console.log('diff:', [diff[0], formatter.format(diff[1])]);
56
68
 
57
- const size = await pendingReservationRepo.getSize({
58
- project: {
59
- id: project.id
60
- },
61
- eventId,
62
- startDate: eventStartDate,
63
- hasTicketedSeat: true
64
- });
65
- console.log('size:', size);
69
+ // const size = await pendingReservationRepo.getSize({
70
+ // project: {
71
+ // id: project.id
72
+ // },
73
+ // eventId,
74
+ // startDate: eventStartDate,
75
+ // hasTicketedSeat: true
76
+ // });
77
+ // console.log('size:', size);
66
78
  }
67
79
 
68
80
  main()
@@ -50,24 +50,18 @@ const formatter = new Intl.NumberFormat('ja-JP');
50
50
  // => "1,000"
51
51
 
52
52
  // tslint:disable-next-line:max-func-body-length
53
- async function lockSeatsForcibly() {
53
+ async function lockSeatsForcibly(params: {
54
+ maximumCapacity?: number;
55
+ }) {
56
+ const { maximumCapacity } = params;
54
57
  let startTime: [number, number] = process.hrtime();
55
58
  let diff: [number, number] = process.hrtime(startTime);
56
59
 
57
- const stockHolderRepo = await chevre.repository.StockHolder.createInstance(client, mongoose.connection);
58
-
59
- // startTime = process.hrtime();
60
- // console.log('counting unavailableOffers...');
61
- // const countUnavailableOffersMustBeZero = await stockHolderRepo.countUnavailableOffers({
62
- // event: {
63
- // id: 'xxxxxxxxx',
64
- // startDate: eventStartDate,
65
- // hasTicketedSeat: true
66
- // }
67
- // });
68
- // diff = process.hrtime(startTime);
69
- // console.log('countUnavailableOffersMustBeZero:', countUnavailableOffersMustBeZero);
70
- // console.log('diff:', [diff[0], formatter.format(diff[1])]);
60
+ const stockHolderRepo = await chevre.repository.StockHolder.createInstance(
61
+ client,
62
+ mongoose.connection,
63
+ { useMongooseForce: true }
64
+ );
71
65
 
72
66
  startTime = process.hrtime();
73
67
  console.log('counting unavailableOffers...');
@@ -143,35 +137,45 @@ async function lockSeatsForcibly() {
143
137
  await sleep(OPERATION_INTERVAL);
144
138
  const newHolder = Date.now()
145
139
  .toString();
140
+ const bookingTime = new Date();
146
141
  startTime = process.hrtime();
147
142
  console.log('locking...', newHolder, seatSection, seatNumbers);
148
- const lockResult = await stockHolderRepo.lock({
149
- project: {
150
- id: project.id
151
- },
152
- eventId,
153
- startDate: eventStartDate,
154
- hasTicketedSeat: true,
155
- offers: seatNumbers.map((seatNumber) => ({ seatSection, seatNumber })),
156
- expires: new Date(),
157
- holder: newHolder
158
- });
159
- // const lockResult = await stockHolderRepo.lockIfNotLimitExceeded(
160
- // {
161
- // project: {
162
- // id: project.id
163
- // },
164
- // eventId,
165
- // startDate: eventStartDate,
166
- // hasTicketedSeat: true,
167
- // offers: seatNumbers.map((seatNumber) => ({ seatSection, seatNumber })),
168
- // expires: new Date(),
169
- // holder: newHolder
170
- // },
171
- // MAXIMUM_CAPACITY
172
- // );
143
+ if (typeof maximumCapacity === 'number') {
144
+ try {
145
+ await stockHolderRepo.lockIfNotLimitExceeded(
146
+ {
147
+ project: { id: project.id },
148
+ eventId,
149
+ startDate: eventStartDate,
150
+ hasTicketedSeat: true,
151
+ offers: seatNumbers.map((seatNumber) => ({ seatSection, seatNumber })),
152
+ expires: bookingTime,
153
+ holder: newHolder,
154
+ bookingTime
155
+ },
156
+ maximumCapacity
157
+ );
158
+ } catch (error) {
159
+ if (error.message === 'maximumAttendeeCapacity exceeded') {
160
+ // ok
161
+ } else {
162
+ throw error;
163
+ }
164
+ }
165
+ } else {
166
+ await stockHolderRepo.lock({
167
+ project: { id: project.id },
168
+ eventId,
169
+ startDate: eventStartDate,
170
+ hasTicketedSeat: true,
171
+ offers: seatNumbers.map((seatNumber) => ({ seatSection, seatNumber })),
172
+ expires: bookingTime,
173
+ holder: newHolder,
174
+ bookingTime
175
+ });
176
+ }
173
177
  diff = process.hrtime(startTime);
174
- console.log('lockResult:', lockResult, newHolder);
178
+ console.log('locked.', newHolder);
175
179
  console.log('diff:', [diff[0], formatter.format(diff[1])]);
176
180
  locked = true;
177
181
  } catch (error) {
@@ -183,11 +187,10 @@ async function lockSeatsForcibly() {
183
187
  }
184
188
 
185
189
  await sleep(OPERATION_INTERVAL);
186
- const holder = currentHolders[0];
187
- if (typeof holder === 'string') {
190
+ for (const currentHolder of currentHolders) {
188
191
  for (const seatNumber of seatNumbers) {
189
192
  startTime = process.hrtime();
190
- console.log('unlocking...', holder, seatSection, seatNumber);
193
+ console.log('unlocking...', currentHolder, seatSection, seatNumber);
191
194
  const unlockResult = await stockHolderRepo.unlock({
192
195
  project: {
193
196
  id: project.id
@@ -196,7 +199,7 @@ async function lockSeatsForcibly() {
196
199
  startDate: eventStartDate,
197
200
  hasTicketedSeat: true,
198
201
  offer: { seatSection, seatNumber },
199
- holder
202
+ holder: currentHolder
200
203
  });
201
204
  diff = process.hrtime(startTime);
202
205
  console.log('unlockResult:', unlockResult);
@@ -217,31 +220,63 @@ async function lockSeatsForcibly() {
217
220
 
218
221
  }
219
222
 
220
- // const NUM_LOCK = 1;
221
- const NUM_LOCK = 1000;
222
- const LOCK_INTERVAL = 1000;
223
- let i = 0;
224
- let lockedCount = 0;
225
- let timeout: NodeJS.Timeout;
226
- const processStartDate = new Date();
227
- function onSeatsLocked() {
228
- lockedCount += 1;
229
- console.log(lockedCount, 'lockSeatsForcibly executed!');
230
- console.log('processed.', processStartDate, '~', new Date());
231
- }
223
+ async function main() {
224
+ // const stockHolderRepo = await chevre.repository.StockHolder.createInstance(
225
+ // client,
226
+ // mongoose.connection,
227
+ // { useMongooseForce: true }
228
+ // );
229
+ // const newHolder = Date.now()
230
+ // .toString();
231
+ // // tslint:disable-next-line:no-magic-numbers
232
+ // const seatNumbers = allSeatNumbers.slice(0, 1000);
233
+ // const lockResult = await stockHolderRepo.lock({
234
+ // project: {
235
+ // id: project.id
236
+ // },
237
+ // eventId,
238
+ // startDate: eventStartDate,
239
+ // hasTicketedSeat: true,
240
+ // offers: seatNumbers.map((seatNumber) => ({ seatSection, seatNumber })),
241
+ // expires: new Date(),
242
+ // holder: newHolder
243
+ // });
244
+ // console.log(lockResult);
245
+ // return;
232
246
 
233
- timeout = setInterval(
234
- () => {
235
- if (i >= NUM_LOCK) {
236
- clearInterval(timeout);
247
+ // tslint:disable-next-line:no-magic-numbers
248
+ const maximumCapacity = (typeof process.argv[2] === 'string') ? Number(process.argv[2]) : undefined;
237
249
 
238
- return;
239
- }
250
+ // const NUM_LOCK = 1;
251
+ const NUM_LOCK = 2000;
252
+ const LOCK_INTERVAL = 300;
253
+ let i = 0;
254
+ let lockedCount = 0;
255
+ let timeout: NodeJS.Timeout;
256
+ const processStartDate = new Date();
257
+ function onSeatsLocked() {
258
+ lockedCount += 1;
259
+ console.log(lockedCount, 'lockSeatsForcibly executed!');
260
+ console.log('processed.', processStartDate, '~', new Date());
261
+ }
240
262
 
241
- i += 1;
242
- lockSeatsForcibly()
243
- .then(onSeatsLocked)
244
- .catch(console.error);
245
- },
246
- LOCK_INTERVAL
247
- );
263
+ timeout = setInterval(
264
+ () => {
265
+ if (i >= NUM_LOCK) {
266
+ clearInterval(timeout);
267
+
268
+ return;
269
+ }
270
+
271
+ i += 1;
272
+ lockSeatsForcibly({ maximumCapacity })
273
+ .then(onSeatsLocked)
274
+ .catch(console.error);
275
+ },
276
+ LOCK_INTERVAL
277
+ );
278
+ }
279
+
280
+ main()
281
+ .then()
282
+ .catch(console.error);
@@ -34,7 +34,7 @@ export declare class AssetTransactionRepo {
34
34
  * 取引を開始する
35
35
  */
36
36
  start<T extends factory.assetTransactionType>(params: factory.assetTransaction.IStartParams<T>): Promise<factory.assetTransaction.ITransaction<T>>;
37
- startWithMinimalResponse<T extends factory.assetTransactionType>(params: factory.assetTransaction.IStartParams<T>): Promise<Pick<factory.assetTransaction.ITransaction<factory.assetTransactionType>, 'id'>>;
37
+ startWithMinimalResponse<T extends factory.assetTransactionType>(params: factory.assetTransaction.IStartParams<T>): Promise<Pick<factory.assetTransaction.ITransaction<factory.assetTransactionType>, 'id' | 'startDate'>>;
38
38
  findById<T extends factory.assetTransactionType>(params: {
39
39
  typeOf: T;
40
40
  id: string;
@@ -313,7 +313,8 @@ class AssetTransactionRepo {
313
313
  return __awaiter(this, void 0, void 0, function* () {
314
314
  var _a, _b;
315
315
  const { typeOf } = params;
316
- const creatingTransaction = Object.assign(Object.assign({}, params), { typeOf, status: factory.transactionStatusType.InProgress, startDate: new Date(),
316
+ const startDate = new Date();
317
+ const creatingTransaction = Object.assign(Object.assign({}, params), { typeOf, status: factory.transactionStatusType.InProgress, startDate,
317
318
  // endDate: undefined,
318
319
  tasksExportAction: {
319
320
  actionStatus: factory.actionStatusType.PotentialActionStatus
@@ -323,7 +324,7 @@ class AssetTransactionRepo {
323
324
  if (typeof id !== 'string') {
324
325
  throw new factory.errors.Internal('assetTransaction not saved');
325
326
  }
326
- return { id };
327
+ return { id, startDate };
327
328
  });
328
329
  }
329
330
  findById(params, inclusion) {
@@ -10,6 +10,8 @@ interface IReservationPackage {
10
10
  };
11
11
  typeOf: factory.reservationType.ReservationPackage;
12
12
  bookingTime: Date;
13
+ dateCreated: Date;
14
+ dateModified?: Date;
13
15
  numSeats: number;
14
16
  reservationFor: {
15
17
  id: string;
@@ -10,12 +10,14 @@ exports.modelName = modelName;
10
10
  const schemaDefinition = {
11
11
  project: { type: mongoose_1.SchemaTypes.Mixed, required: true },
12
12
  typeOf: { type: String, required: true },
13
- bookingTime: { type: Date, required: true },
14
- expires: { type: Date, required: true },
15
13
  numSeats: { type: Number, required: true },
16
14
  reservationFor: { type: mongoose_1.SchemaTypes.Mixed, required: true },
17
15
  reservationNumber: { type: String, required: true },
18
- subReservation: [mongoose_1.SchemaTypes.Mixed]
16
+ subReservation: [mongoose_1.SchemaTypes.Mixed],
17
+ bookingTime: { type: Date, required: true },
18
+ expires: { type: Date, required: true },
19
+ dateCreated: { type: Date, required: true },
20
+ dateModified: { type: Date, required: false }
19
21
  };
20
22
  const schemaOptions = {
21
23
  autoIndex: settings_1.MONGO_AUTO_INDEX,
@@ -46,21 +48,32 @@ const indexes = [
46
48
  { bookingTime: -1 },
47
49
  { name: 'bookingTime' }
48
50
  ],
51
+ // [
52
+ // { 'reservationFor.id': 1, bookingTime: -1 },
53
+ // { name: 'reservationForId' }
54
+ // ],
55
+ // [
56
+ // { 'project.id': 1, bookingTime: -1 },
57
+ // { name: 'projectId' }
58
+ // ],
59
+ // [
60
+ // { reservationNumber: 1, bookingTime: -1 },
61
+ // { name: 'reservationNumber' }
62
+ // ],
63
+ // [
64
+ // { 'subReservation.identifier': 1, bookingTime: -1 },
65
+ // { name: 'subReservationIdentifier' }
66
+ // ],
67
+ // [
68
+ // { 'subReservation.identifier': 1 },
69
+ // { name: 'subReservationIdentifier' }
70
+ // ],
49
71
  [
50
- { 'project.id': 1, bookingTime: -1 },
51
- { name: 'projectId' }
52
- ],
53
- [
54
- { 'reservationFor.id': 1, bookingTime: -1 },
55
- { name: 'reservationForId' }
56
- ],
57
- [
58
- { reservationNumber: 1, bookingTime: -1 },
59
- { name: 'reservationNumber' }
60
- ],
61
- [
62
- { 'subReservation.identifier': 1, bookingTime: -1 },
63
- { name: 'subReservationIdentifier' }
72
+ { reservationNumber: 1 },
73
+ {
74
+ unique: true,
75
+ name: 'uniqueReservationNumber'
76
+ }
64
77
  ],
65
78
  [
66
79
  { 'reservationFor.id': 1, 'subReservation.identifier': 1 },
@@ -73,24 +86,36 @@ const indexes = [
73
86
  }
74
87
  ],
75
88
  [
76
- { reservationNumber: 1 },
77
89
  {
78
- unique: true,
79
- name: 'uniqueReservationNumber'
90
+ 'reservationFor.id': 1,
91
+ reservationNumber: 1,
92
+ 'subReservation.identifier': 1
93
+ },
94
+ {
95
+ name: 'deleteReservationIfExists',
96
+ partialFilterExpression: {
97
+ 'subReservation.identifier': { $exists: true }
98
+ }
80
99
  }
81
100
  ],
82
101
  [
83
102
  {
84
103
  'reservationFor.id': 1,
85
- reservationNumber: 1,
86
- 'subReservation.identifier': 1
104
+ 'subReservation.identifier': 1,
105
+ bookingTime: 1,
106
+ dateCreated: 1
87
107
  },
88
- { name: 'unlock' }
108
+ {
109
+ name: 'aggregateNumSeats',
110
+ partialFilterExpression: {
111
+ 'subReservation.identifier': { $exists: true }
112
+ }
113
+ }
89
114
  ]
90
115
  ];
91
116
  exports.indexes = indexes;
92
117
  /**
93
- * 在庫保持者スキーマ
118
+ * 保留予約スキーマ
94
119
  */
95
120
  let schema;
96
121
  function createSchema() {
@@ -44,18 +44,22 @@ const indexes = [
44
44
  { expires: -1 },
45
45
  { name: 'expires' }
46
46
  ],
47
- [
48
- { 'project.id': 1, expires: -1 },
49
- { name: 'projectId' }
50
- ],
51
- [
52
- { reservationCount: 1, expires: -1 },
53
- { name: 'reservationCount' }
54
- ],
55
- [
56
- { 'reservationFor.id': 1, expires: -1 },
57
- { name: 'reservationForId' }
58
- ],
47
+ // [
48
+ // { 'project.id': 1, expires: -1 },
49
+ // { name: 'projectId' }
50
+ // ],
51
+ // [
52
+ // { 'reservationFor.id': 1, expires: -1 },
53
+ // { name: 'reservationForId' }
54
+ // ],
55
+ // [
56
+ // { reservationIds: 1, expires: -1 },
57
+ // { name: 'reservationIds' }
58
+ // ], // このindexで性能下がる?
59
+ // [
60
+ // { reservationIds: 1 },
61
+ // { name: 'reservationIds' }
62
+ // ], // このindexで性能下がる?
59
63
  [
60
64
  { 'reservationFor.id': 1 },
61
65
  {
@@ -75,16 +79,12 @@ const indexes = [
75
79
  'reservationFor.id': 1,
76
80
  reservationIds: 1
77
81
  },
78
- { name: 'unlock' }
79
- ],
80
- [
81
- { reservationIds: 1 },
82
- { name: 'reservationIds' }
82
+ { name: 'decreaseReservationCount' }
83
83
  ]
84
84
  ];
85
85
  exports.indexes = indexes;
86
86
  /**
87
- * 在庫保持者スキーマ
87
+ * 保留予約集計スキーマ
88
88
  */
89
89
  let schema;
90
90
  function createSchema() {
@@ -1,18 +1,19 @@
1
1
  import type { Connection } from 'mongoose';
2
2
  import { AbstractStockHolderRepo, IGetHolderResult, ILockKey, IOffer, IUnlockKey } from './stockHolderAbstract';
3
3
  /**
4
- * イベントストックホルダーリポジトリ
4
+ * 保留予約リポジトリ
5
5
  */
6
6
  export declare class PendingReservationRepo implements AbstractStockHolderRepo {
7
- private readonly aggregateModel;
8
7
  private readonly pendingReservationModel;
9
8
  constructor(connection: Connection);
10
9
  private static offer2identifier;
11
- private static lockKey2aggregateReservation;
12
10
  private static lockKey2reservationPackage;
13
11
  lockIfNotLimitExceeded(lockKey: ILockKey, maximumReservationCount: number): Promise<void>;
14
12
  lock(lockKey: ILockKey): Promise<void>;
15
13
  unlock(params: IUnlockKey): Promise<void>;
14
+ /**
15
+ * 現時点での保留予約数を集計する
16
+ */
16
17
  countUnavailableOffers(params: {
17
18
  event: {
18
19
  id: string;
@@ -26,6 +27,8 @@ export declare class PendingReservationRepo implements AbstractStockHolderRepo {
26
27
  startDate: Date;
27
28
  hasTicketedSeat: boolean;
28
29
  };
30
+ }, options?: {
31
+ limit?: number;
29
32
  }): Promise<number>;
30
33
  getHolder(params: Omit<IUnlockKey, 'holder'>): Promise<string | null | undefined>;
31
34
  searchHolders(params: {
@@ -37,11 +40,8 @@ export declare class PendingReservationRepo implements AbstractStockHolderRepo {
37
40
  hasTicketedSeat: boolean;
38
41
  offers: IOffer[];
39
42
  }): Promise<IGetHolderResult[]>;
40
- getSize(params: Omit<IUnlockKey, 'holder' | 'offer'>): Promise<any[]>;
41
- private createIfNotExist;
43
+ private aggregateNumSeats;
42
44
  private createReservationPackageIfPossible;
43
45
  private deleteReservationPackage;
44
- private increaseReservationCount;
45
46
  private deleteReservationIfExists;
46
- private decreaseReservationCount;
47
47
  }