Rules Hub
Coding Rules Library
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Match error handling symmetrically across paired lifecycle hooks
If init is defensively wrapped in try/catch, wrap the matching destroy/cleanup hook the same way.
Bad example
| 1 | async onModuleInit() { |
| 2 | try { |
| 3 | await this.client.init(); |
| 4 | } catch (err) { |
| 5 | this.logger.warn(`Init failed: ${(err as Error).message}`); |
| 6 | } |
| 7 | } |
| 8 |
|
| 9 | async onModuleDestroy() { |
| 10 | await this.client.quit(); // unguarded — a rejection here aborts remaining teardown |
| 11 | } |
Explanation (EN)
Guarding the init hook with try/catch but leaving the destroy/cleanup hook unguarded is inconsistent — a rejected promise during teardown (e.g. a socket that drops mid-shutdown) throws out of the hook and can abort other cleanup that was supposed to run after it.
Objašnjenje (HR)
Zaštititi init hook s try/catch, ali ostaviti destroy/cleanup hook nezaštićenim je nekonzistentno — odbijeni promise tijekom gašenja (npr. socket koji padne usred shutdowna) baci grešku iz hooka i može prekinuti ostali cleanup koji je trebao izvršiti se nakon njega.
Good example
| 1 | async onModuleDestroy() { |
| 2 | try { |
| 3 | await this.client.quit(); |
| 4 | } catch (err) { |
| 5 | this.logger.warn(`Cleanup failed: ${(err as Error).message}`); |
| 6 | } |
| 7 | } |
Explanation (EN)
Apply the same defensive error handling to every lifecycle hook that performs I/O, so a failure in one teardown step doesn't prevent the rest of the shutdown sequence from running.
Objašnjenje (HR)
Primijeni istu defenzivnu obradu grešaka na svaki lifecycle hook koji radi I/O, tako da greška u jednom koraku gašenja ne spriječi izvršavanje ostatka shutdown sekvence.