Застосунок
Ditsmod дозволяє писати застосунки з різними архітектурними стилями:
- REST
- REST testing
- tRPC
- GraphQL
- WebSockets
- Microservices
- ...
Ditsmod надає API, що дозволяє додати підтримку необхідної архітектури. Такі пакети - більше, ніж звичайні модулі фіч, оскільки вони мають ще й клас застосунку та клас ініціалізатора застосунку, в яких прописано конфіг застосунку, послідовність збірки застосунку і т.д. Як правило, кожен із таких пакетів має свої особливості щодо метаданих їхніх модулів. Окрім цього, якщо вебсервер застосунку має свої особливості роботи для різних Runtimes (Node, Bun, Deno і т.п.), Ditsmod дозволяє це враховувати саме на етапі ініціалізації класу застосунку.
Інстанс класу застосунку, як правило, створюється у файлі main.ts, і з нього починається робота застосунку. Наприклад, наступним чином створюється інстанс класу REST-застосунку:
import { RestApplication } from '@ditsmod/rest';
import { AppModule } from './app/app.module.js';
const app = await RestApplication.create(AppModule);
app.server.listen(3000, '0.0.0.0');
Граційне завершення роботи
Ditsmod підтримує граційне завершення роботи (Graceful Shutdown), що дозволяє застосунку припинити прийом нових HTTP-запитів, дочекатися завершення обробки активних запитів, виконати завдання з очищення ресурсів у синглтон-сервісах і вийти без втрати даних.
Увімкнення перехоплення сигналів
Щоб активувати граційне завершення роботи, викличте метод enableShutdownHooks() на інстансі застосунку. Ви можете передати туди необов'язковий масив системних сигналів (наприклад, SIGTERM, SIGINT).
import { RestApplication } from '@ditsmod/rest';
import { AppModule } from './app/app.module.js';
const app = await RestApplication.create(AppModule);
app.enableShutdownHooks();
app.server.listen(3000, '0.0.0.0');
За замовчуванням прослуховуються такі сигнали: ['SIGTERM', 'SIGINT', 'SIGHUP', 'SIGUSR2', 'SIGQUIT'].
Хуки життєвого циклу
Сервіси, що зареєстровані як синглтони (наприклад, providersPerApp або providersPerMod), можуть реалізовувати хуки життєвого циклу для очищення ресурсів:
BeforeShutdown: Викликається перед тим, як HTTP-сервер почне закриватися. Чудово підходить для сповіщення фонових завдань про зупинку.OnShutdown: Викликається після того, як HTTP-сервер повністю закрився. Чудово підходить для закриття пулів з'єднань баз даних, клієнтів Redis тощо.
Обидва хуки отримують як параметр системний сигнал, що спричинив завершення роботи, і можуть повертати void або Promise<void>.
import { BeforeShutdown, OnShutdown, injectable } from '@ditsmod/core';
@injectable()
export class MyService implements BeforeShutdown, OnShutdown {
beforeShutdown(signal?: string) {
console.log(`Отримано ${signal}. Зупиняємо фонові процеси...`);
}
async onShutdown(signal?: string) {
console.log(`Закриваємо з'єднання з базою даних...`);
await this.db.close();
}
}
Очищення з'єднань (REST)
У пакеті @ditsmod/rest при отриманні сигналу завершення:
- Вебсервер негайно перестає приймати нові TCP-з'єднання (
server.close()). - Усі неактивні keep-alive з'єднання відразу закриваються.
- Активним з'єднанням дається час на завершення обробки поточних запитів.
- Якщо активні з'єднання не закриваються самостійно протягом часу
shutdownTimeout(за замовчуванням 15 секунд), вони закриваються примусово.
Ви можете налаштувати тайм-аут заверш ення з'єднань shutdownTimeout (у мілісекундах) через AppOptions у вашому кореневому модулі:
import { AppOptions } from '@ditsmod/core';
import { RestModule } from '@ditsmod/rest';
@rootModule({
imports: [RestModule],
providersPerApp: [
{ token: AppOptions, useValue: { shutdownTimeout: 20000 } }
]
})
export class AppModule {}