Skip to content
This repository was archived by the owner on Mar 20, 2023. It is now read-only.

Commit d25ac78

Browse files
fix(api): temporary timeout for EventsSubscription and isolate tests of register-course-user.test-module #368 (#369)
Co-authored-by: Hubert Kawałek <hubert.kawalek.dev@gmail.com>
1 parent 6d4dd65 commit d25ac78

File tree

8 files changed

+37
-29
lines changed

8 files changed

+37
-29
lines changed

packages/api/src/module/automation/when-email-confirmation-was-approved-then-complete-user-registration/email-confirmation-was-approved-event-handler.service.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
1+
import { Injectable, OnApplicationBootstrap, OnModuleDestroy } from '@nestjs/common';
22
import { CommandBus } from '@nestjs/cqrs';
33

44
import { ApplicationEvent } from '@/module/application-command-events';
@@ -12,7 +12,7 @@ import { EventsSubscription } from '@/write/shared/application/events-subscripti
1212
import { EventsSubscriptionsRegistry } from '@/write/shared/application/events-subscription/events-subscriptions-registry';
1313

1414
@Injectable()
15-
export class EmailConfirmationWasApprovedEventHandler implements OnModuleInit, OnModuleDestroy {
15+
export class EmailConfirmationWasApprovedEventHandler implements OnApplicationBootstrap, OnModuleDestroy {
1616
private eventsSubscription: EventsSubscription;
1717

1818
constructor(
@@ -21,7 +21,7 @@ export class EmailConfirmationWasApprovedEventHandler implements OnModuleInit, O
2121
private readonly eventsSubscriptionsFactory: EventsSubscriptionsRegistry,
2222
) {}
2323

24-
async onModuleInit() {
24+
async onApplicationBootstrap() {
2525
this.eventsSubscription = this.eventsSubscriptionsFactory
2626
.subscription('WhenEmailConfirmationWasApprovedThenCompleteUserRegistrationAutomationModule_Automation_v1')
2727
.onEvent<EmailConfirmationWasApproved>('EmailConfirmationWasApproved', (event) =>

packages/api/src/module/automation/when-email-confirmation-was-approved-then-complete-user-registration/when-email-confirmation-was-approved-then-complete-user-registration.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ describe('CompleteUser registration when emailConfirmationWasApproved', () => {
2929
event,
3030
);
3131

32-
moduleUnderTest.expectCommandExecutedLastly(completeUserRegistrationCommand({ userId }));
32+
await moduleUnderTest.expectCommandExecutedLastly(completeUserRegistrationCommand({ userId }));
3333
});
3434
});

packages/api/src/module/automation/when-user-registration-was-started-then-request-email-confirmation/user-registration-was-started.event-handler.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Injectable, OnApplicationBootstrap, OnModuleDestroy } from '@nestjs/common';
1+
import { Injectable, OnApplicationBootstrap, OnModuleDestroy } from '@nestjs/common';
22
import { CommandBus } from '@nestjs/cqrs';
33

44
import { ApplicationEvent } from '@/module/application-command-events';

packages/api/src/module/read/course-progress/course-progress.read-module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Module, OnApplicationBootstrap, OnModuleDestroy} from '@nestjs/common';
1+
import { Module, OnApplicationBootstrap, OnModuleDestroy } from '@nestjs/common';
22

33
import { LearningMaterialsUrlWasGenerated } from '@/events/learning-materials-url-was-generated.domain-event';
44
import { ApplicationEvent } from '@/module/application-command-events';

packages/api/src/module/read/learning-materials/learning-materials.read-module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Module, OnApplicationBootstrap, OnModuleDestroy } from '@nestjs/common';
1+
import { Module, OnApplicationBootstrap, OnModuleDestroy } from '@nestjs/common';
22

33
import { LearningMaterialsUrlWasGenerated } from '@/events/learning-materials-url-was-generated.domain-event';
44
import { ApplicationEvent } from '@/module/application-command-events';
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { initWriteTestModule } from '@/shared/test-utils';
2+
import { RegisterCourseUserWriteModule } from '@/write/register-course-user/register-course-user.write-module';
23

34
export async function registerCourseUserTestModule() {
4-
return initWriteTestModule();
5+
return initWriteTestModule({
6+
modules: [RegisterCourseUserWriteModule],
7+
});
58
}

packages/api/src/module/write/register-course-user/register-course-user.write-module.spec.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ describe('registerCourseUserModule', () => {
1414
data: { userId, courseUserId, courseId },
1515
});
1616

17+
beforeEach(async () => {
18+
module = await registerCourseUserTestModule();
19+
});
20+
21+
afterEach(async () => {
22+
await module.close();
23+
});
24+
1725
it('should register new course user', async () => {
1826
// Given
1927
const command = commandBuilder();
@@ -39,8 +47,4 @@ describe('registerCourseUserModule', () => {
3947
// Then
4048
await expect(() => module.executeCommand(() => command)).rejects.toThrow();
4149
});
42-
43-
beforeEach(async () => {
44-
module = await registerCourseUserTestModule();
45-
});
4650
});

packages/api/src/module/write/shared/application/events-subscription/events-subscription.ts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -89,19 +89,26 @@ export class EventsSubscription {
8989
* See handleEvent for more details how handling event working.
9090
*/
9191
async start(): Promise<void> {
92-
const retryConfig = this.configuration.options?.retry ?? {
93-
retries: 'INFINITELY',
94-
backoff: 'EXPONENTIAL',
95-
delay: 3000,
92+
const retryConfig: Partial<RetryConfig<void>> = {
93+
...(this.configuration.options?.retry ?? {
94+
retries: 'INFINITELY',
95+
backoff: 'EXPONENTIAL',
96+
delay: 3000,
97+
}),
98+
logger: (msg) => this.logger.error(msg),
99+
// FIXME: after timeout EventsSubscription will stop processing
100+
timeout: 2147483647, // max timeout => max 32-bit signed integer
96101
};
97102

98-
// TODO: extract failure recovery to separeate module which will run in bootstrap phase (SRP)
99-
await retry(async () => {
103+
this.eventEmitter.onAny(this.eventEmitterListener);
104+
105+
// FIXME: it will work for 2147483647/(1000*60*60*24) = 24.85 days :D
106+
retry(async () => {
100107
await this.catchUp().catch((e) => {
101108
this.logger.warn(`EventsSubscription ${this.subscriptionId} processing error in CatchUp phase.`, e);
102109
throw e;
103110
});
104-
this.listen().catch((e) => {
111+
await this.listen().catch(async (e) => {
105112
this.logger.warn(`EventsSubscription ${this.subscriptionId} processing error in listen phase.`, e);
106113
throw e;
107114
});
@@ -118,7 +125,7 @@ export class EventsSubscription {
118125
*/
119126
async stop(): Promise<void> {
120127
this.eventEmitter.offAny(this.eventEmitterListener);
121-
this.queue.stop();
128+
this.queue.clear();
122129
}
123130

124131
/**
@@ -128,14 +135,11 @@ export class EventsSubscription {
128135
*/
129136
async reset(): Promise<void> {
130137
await this.stop();
131-
this.queue.clear();
132138
await this.moveCurrentPosition(this.configuration.options.start.from.globalPosition - 1, this.prismaService);
133139
await this.start();
134140
}
135141

136142
private async listen(): Promise<void> {
137-
this.eventEmitter.onAny(this.eventEmitterListener);
138-
139143
let event = await this.queue.pop();
140144

141145
while (!OrderedEventQueue.isStopToken(event)) {
@@ -172,10 +176,9 @@ export class EventsSubscription {
172176
: this.configuration.options.start.from.globalPosition,
173177
});
174178

175-
// eslint-disable-next-line no-restricted-syntax
176-
for (const event of eventsToCatchup) {
177-
await this.handleEvent(event);
178-
}
179+
this.eventsRetryCount.clear();
180+
this.queue.clear();
181+
eventsToCatchup.forEach((event) => this.queue.push(event));
179182
}
180183

181184
/**
@@ -193,12 +196,10 @@ export class EventsSubscription {
193196
this.eventsRetryCount.delete(event.id);
194197

195198
try {
196-
// TODO add transaction
197199
await this.processSubscriptionPositionChange(event, this.prismaService);
198200
await this.processEvent(event, this.prismaService);
199201
await this.moveCurrentPosition(event.globalOrder, this.prismaService);
200202
} catch (e) {
201-
await this.stop();
202203
this.logger.warn(
203204
`EventsSubscription ${this.subscriptionId} processing stopped on position ${event.globalOrder}`,
204205
e,

0 commit comments

Comments
 (0)