Фабрики
Фабрики - функціональна група призначена для виконання єдиного завдання - вибір, запуск та надання екземпляра
стратегії / адаптера в залежності від конфігураційного параметра. Кожна фабрика також, конфігураційно може бути
підключена чи відключена. Фабрики запускаються / зупиняються в рамках запуску / зупинки сервісу
комбінацій CombinationService.
Архітектура
Фабрика поділяються на два фабрики адаптерів та фабрики стратегій.
Фабрики адаптерів
Фабрики адаптерів виконують запуск адаптера конкретного фреймворку відповідного протоколу. Так, наприклад, http
веб-сервер може бути представлений fastify, express, koa та іншими фреймворками. Наразі X-Fiber реалізовує
наступні адаптери:
| Назва | Адаптер | Опис |
|---|---|---|
| HttpAdapter | FastifyHttpAdapter | Реалізовує адаптер http веб-сервера на базі fastify фреймворку |
| WsAdapter | WsWsAdapter | Реалізовує адаптер ws веб-сервера на базі ws бібліотеки |
Фабрики адаптерів мають єдиний інтерфейс з методами run та stand, які визначають специфіку запуску та зупинку
адаптера відповідного протоколу.
Фабрики стратегій
Фабрики стратегій як і фабрики адаптерів здійснюють вибір конкретної стратегії на основі конфігураційного значення, а
самі стратегії повинні реалізовувати методи run та stand. Окрім цього фабрики стратегій надають екземпляр стратегії,
оскільки кожна стратегія є кінцевою реалізацією. Наразі X-Fiber реалізовує наступні стратегії:
| Назва | Стратегія | Опис |
|---|---|---|
| FileStorage | BufferFileStorageStrategy | Реалізовує стратегію зберігання файлів в буфері веб-сервера. |
| FileStorage | RedisFileStorageStrategy | Реалізовує стратегію зберігання файлів в буфері веб-сервера підтримуючи два режими роботи: повного завантаження та завантаження частинами з послідуючим відвантаженням за механікою стрімінгу. |
Підхід "Фабрика-стратегія" дозволяє уникнути привʼязки до конкретного інструмента, впроваджуючи загальний інтерфейс, до якого повинен бути приведений відповідний інструмент.
Застосування
Застосування фабрик відбувається за єдиним сценарієм - в фабриці описується конфігурація вибору, а в сервісі комбінацій вони викликаються
// ** http.factory.ts */
import { injectable, inject } from '~packages'
import { CoreSymbols } from '~symbols'
import { AbstractFactory } from './abtract.factory'
import type {
IAbstractFactory,
IDiscoveryService,
ILoggerService,
IAbstractHttpAdapter
} from '~types'
@injectable()
export class HttpFactory extends AbstractFactory implements IAbstractFactory {
constructor(
@inject(CoreSymbols.DiscoveryService)
private readonly _discoveryService: IDiscoveryService,
@inject(CoreSymbols.LoggerService)
private readonly _loggerService: ILoggerService,
@inject(CoreSymbols.FastifyAdapter)
private readonly _fastifyAdapter: IAbstractHttpAdapter,
@inject(CoreSymbols.ExpressAdapter)
private readonly _expressAdapter: IAbstractHttpAdapter
) {
super();
}
public async run<T>(): Promise<void> {
const enable = this._discoveryService.getBoolean('adapters.http.enable', false);
if (!enable) return
const kind = this._discoveryService.getString('adapters.http.kind', 'fastify');
try {
switch (kind) {
case 'fastify':
await this._fastifyAdapter.start();
break;
case 'express':
await this._expressAdapter.start()
default:
throw new Error(`Http adapter kind is not supported. Use "fastify" or "express" kind`);
}
} catch (e) {
this._loggerService.error(e)
throw e
}
}
public async stand(): Promise<void> {
const enable = this._discoveryService.getBoolean('adapters.http.enable', false);
if (!enable) return
const kind = this._discoveryService.getString('adapters.http.kind', 'fastify');
try {
switch (kind) {
case 'fastify':
await this._fastifyAdapter.stop();
break;
case 'express':
await this._expressAdapter.stop()
default:
throw new Error(`Http adapter kind is not supported. Use "fastify" or "express" kind`);
}
} catch (e) {
this._loggerService.error(e)
throw e
}
}
}
// ** combination.service.ts */
import { injectable, inject } from '~packages'
import { CoreSymbols } from '~symbols'
import { AbstractService } from './abstract.service';
import type {
IAbstractService,
IDiscoveryService,
ILoggerService,
IAbstractFactory
} from '~types'
@injectable()
export class CombinationService extends AbstractService implements IAbstractService {
protected readonly _SERVICE_NAME = GetawayService.name;
constructor(
@inject(CoreSymbols.DiscoveryService)
protected readonly _discoveryService: IDiscoveryService,
@inject(CoreSymbols.LoggerService)
protected readonly _loggerService: ILoggerService,
@inject(CoreSymbols.FrameworkFactory)
private readonly _httpFactory: IAbstractFactory,
// ... other factory inject
) {
super();
}
protected async init(): Promise<boolean> {
try {
await this._httpFactory.run();
return true;
} catch (e) {
this._loggerService.error(e)
return false
}
}
protected async destroy(): Promise<void> {
try {
await this._httpFactory.stay();
return true;
} catch (e) {
this._loggerService.error(e)
return false
}
}
}
де:
HttpFactory- класhttpфабрики.@inject(CoreSymbols.FastifyAdapter) ...- впровадженняfastifyкінцевогоhttpадаптера.run- метод запуску визначення кінцевого адаптера та його запуск.stay- метод зупинки кінцевого адаптера.
CombinationService- клас сервісу комбінацій.init- метод запуску сервісу.destroy- метод зупинки сервісу.