Skip to content

Commit

Permalink
Merge pull request #908 from pooreumu/fix-error-handling
Browse files Browse the repository at this point in the history
fix(): catch unhandled exceptions
  • Loading branch information
kamilmysliwiec committed Aug 7, 2023
2 parents 0484f8c + ff091ec commit 9a6451f
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 6 deletions.
6 changes: 3 additions & 3 deletions lib/decorators/on-event.decorator.ts
Expand Up @@ -33,9 +33,9 @@ export const OnEvent = (
): MethodDecorator => {
const decoratorFactory = (target: object, key?: any, descriptor?: any) => {
extendArrayMetadata(
EVENT_LISTENER_METADATA,
[{ event, options } as OnEventMetadata],
descriptor.value,
EVENT_LISTENER_METADATA,
[{ event, options } as OnEventMetadata],
descriptor.value,
);
return descriptor;
};
Expand Down
22 changes: 19 additions & 3 deletions lib/event-subscribers.loader.ts
@@ -1,5 +1,6 @@
import {
Injectable,
Logger,
OnApplicationBootstrap,
OnApplicationShutdown,
} from '@nestjs/common';
Expand All @@ -24,6 +25,7 @@ export class EventSubscribersLoader
implements OnApplicationBootstrap, OnApplicationShutdown
{
private readonly injector = new Injector();
private readonly logger = new Logger('Event');

constructor(
private readonly discoveryService: DiscoveryService,
Expand Down Expand Up @@ -92,7 +94,8 @@ export class EventSubscribersLoader
} else {
listenerMethod(
event,
(...args: unknown[]) => instance[methodKey].call(instance, ...args),
(...args: unknown[]) =>
this.wrapFunctionInTryCatchBlocks(instance, methodKey, args),
options,
);
}
Expand Down Expand Up @@ -135,9 +138,10 @@ export class EventSubscribersLoader
moduleRef.providers,
contextId,
);
return contextInstance[listenerMethodKey].call(
return this.wrapFunctionInTryCatchBlocks(
contextInstance,
...args,
listenerMethodKey,
args,
);
},
options,
Expand Down Expand Up @@ -168,4 +172,16 @@ export class EventSubscribersLoader

this.moduleRef.registerRequestByContextId(payloadObjectOrArray, contextId);
}

private async wrapFunctionInTryCatchBlocks(
instance: Record<string, any>,
methodKey: string,
args: unknown[],
) {
try {
return await instance[methodKey].call(instance, ...args);
} catch (e) {
this.logger.error(e);
}
}
}
20 changes: 20 additions & 0 deletions tests/e2e/module-e2e.spec.ts
Expand Up @@ -122,6 +122,26 @@ describe('EventEmitterModule - e2e', () => {
expect(customConsumer.isEmitted).toBeTruthy();
});

it('should be able to gracefully recover when an unexpected error occurs from provider', async () => {
const eventsConsumerRef = app.get(EventsProviderConsumer);
await app.init();

const emitter = app.get(EventEmitter2);
const result = emitter.emit('error-handling.provider');

expect(eventsConsumerRef.errorHandlingCalls).toEqual(1);
expect(result).toBeTruthy();
});

it('should be able to gracefully recover when an unexpected error occurs from request scoped', async () => {
await app.init();

const eventEmitter = app.get(EventEmitter2);
const result = eventEmitter.emit('error-handling.request-scoped');

expect(result).toBeTruthy();
});

afterEach(async () => {
await app.close();
});
Expand Down
7 changes: 7 additions & 0 deletions tests/src/events-provider.consumer.ts
Expand Up @@ -5,6 +5,7 @@ import { OnEvent } from '../../lib';
export class EventsProviderConsumer {
public eventPayload = {};
public stackedEventCalls = 0;
public errorHandlingCalls = 0;

@OnEvent('test.*')
onTestEvent(payload: Record<string, any>) {
Expand All @@ -16,4 +17,10 @@ export class EventsProviderConsumer {
onStackedEvent() {
this.stackedEventCalls++;
}

@OnEvent('error-handling.provider')
onErrorHandlingEvent() {
this.errorHandlingCalls++;
throw new Error('This is a test error');
}
}
5 changes: 5 additions & 0 deletions tests/src/events-provider.request-scoped.consumer.ts
Expand Up @@ -21,4 +21,9 @@ export class EventsProviderRequestScopedConsumer {

@OnEvent('string.*')
onStringPayloadEvent() {}

@OnEvent('error-handling.request-scoped')
onErrorHandlingEvent() {
throw new Error('This is a test error');
}
}

0 comments on commit 9a6451f

Please sign in to comment.