Clean up service manager - move all services to manager
This commit is contained in:
+29
-11
@@ -1,18 +1,18 @@
|
||||
import ServiceInterface from "../interfaces/ServiceInterface";
|
||||
|
||||
type Constructor = new (...args:any[]) => any;
|
||||
|
||||
const serviceNameSymbol = Symbol("symbol.serviceName");
|
||||
|
||||
export abstract class BaseService implements ServiceInterface {
|
||||
export abstract class BaseService {
|
||||
private startPromise: Promise<void> | null = null;
|
||||
|
||||
async start(): Promise<void> {
|
||||
if (!this.startPromise) {
|
||||
await ServiceManager.get().startDependencies(
|
||||
// @ts-ignore
|
||||
this.constructor[Symbol.metadata][serviceNameSymbol]
|
||||
);
|
||||
// @ts-ignore Retrieve service name from subclass metadata. (set by @service decorator)
|
||||
const serviceName = this.constructor[Symbol.metadata]?.[serviceNameSymbol];
|
||||
|
||||
// If the service is properly labeled, use it's serviceName to ensure all dependent services have been started first.
|
||||
if (serviceName) await ServiceManager.get().startDependencies(serviceName);
|
||||
|
||||
// Start the service by running the (subclass provided) init() function.
|
||||
this.startPromise = new Promise<void>(async (resolve) => {
|
||||
resolve(await this.init());
|
||||
})
|
||||
@@ -20,16 +20,24 @@ export abstract class BaseService implements ServiceInterface {
|
||||
return this.startPromise;
|
||||
}
|
||||
|
||||
abstract init(): Promise<void>;
|
||||
/**
|
||||
* Abstract method to provide functionality to "start" the service
|
||||
*/
|
||||
protected abstract init(): Promise<void>;
|
||||
|
||||
async stop(): Promise<void> {
|
||||
// Make sure we are not in the middle of starting the service
|
||||
await this.startPromise;
|
||||
|
||||
// Call (subclass provided) destroy method
|
||||
await this.destroy();
|
||||
this.startPromise = null;
|
||||
return;
|
||||
}
|
||||
|
||||
abstract destroy(): Promise<void>;
|
||||
/**
|
||||
* Abstract method to provide functionality to "stop" the service
|
||||
*/
|
||||
protected abstract destroy(): Promise<void>;
|
||||
}
|
||||
|
||||
type ServiceContainer = {
|
||||
@@ -80,6 +88,9 @@ export class ServiceManager {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start all decorated (@service) services that derive from the BaseService class
|
||||
*/
|
||||
async start() {
|
||||
// Start all constructed services
|
||||
for (const service of this.services.values()) {
|
||||
@@ -140,6 +151,13 @@ export class ServiceManager {
|
||||
|
||||
return service.service as T;
|
||||
}
|
||||
|
||||
replaceService(name: string, service: any) {
|
||||
if (!this.services.has(name)) {
|
||||
const serviceContainer = this.services.get(name) as ServiceContainer;
|
||||
serviceContainer.service = service;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function service(propertyName: string) {
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
export default interface ServiceInterface {
|
||||
start(): Promise<void>;
|
||||
init(): Promise<void>;
|
||||
stop(): Promise<void>;
|
||||
destroy(): Promise<void>;
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
import { spawn } from 'node:child_process';
|
||||
import { once } from 'node:events';
|
||||
import {service} from "../core/service";
|
||||
|
||||
export async function runCommand(command: string, args: string[]) {
|
||||
@service('cliService')
|
||||
export class CliService {
|
||||
async runCommand(command: string, args: string[]) {
|
||||
const cmd = spawn(command, args);
|
||||
const stdout = [] as string[];
|
||||
const stderr = [] as string[];
|
||||
@@ -19,4 +22,5 @@ export async function runCommand(command: string, args: string[]) {
|
||||
stdout: stdout.join(''),
|
||||
stderr: stderr.join(''),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,21 +11,21 @@ export default class DatabaseService extends BaseService {
|
||||
protected db: Database.Database;
|
||||
|
||||
@inject('configService') protected accessor config!: ConfigService;
|
||||
protected migrations: Migration[];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.db = new Database('database/core.db');
|
||||
this.db.pragma('journal_mode = WAL');
|
||||
this.migrations = this.config.migrations;
|
||||
}
|
||||
|
||||
async init() {
|
||||
const migrations = this.config.migrations;
|
||||
|
||||
this.assertMigrationTable();
|
||||
|
||||
// Turn array of migrations into dictionary
|
||||
const migrationDict = {} as {[key: string]: Migration};
|
||||
for (const migration of migrations) {
|
||||
for (const migration of this.migrations) {
|
||||
migrationDict[migration.name] = migration;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import {runCommand} from "./CliService";
|
||||
import {service} from "../core/service";
|
||||
import {inject, service} from "../core/service";
|
||||
import {CliService} from "./CliService";
|
||||
|
||||
@service('ffmpegService')
|
||||
export default class FFMpegService {
|
||||
static async checkFile(filename: string) {
|
||||
const file = await runCommand('ffprobe', [
|
||||
@inject('cliService') protected accessor cliService!: CliService;
|
||||
|
||||
async checkFile(filename: string) {
|
||||
const file = await this.cliService.runCommand('ffprobe', [
|
||||
'-v',
|
||||
'quiet',
|
||||
'-print_format',
|
||||
|
||||
@@ -4,12 +4,13 @@ import {Dirent} from "node:fs";
|
||||
import {fileTypeFromFile} from "file-type";
|
||||
import FFMpegService from "../services/FFMpegService";
|
||||
import TaskInterface from "../interfaces/TaskInterface";
|
||||
import {inject} from "../core/service";
|
||||
|
||||
export default class ScanFoldersTask implements TaskInterface {
|
||||
private hasRun: boolean = false;
|
||||
@inject('ffmpegService') protected accessor ffmpegService!: FFMpegService;
|
||||
|
||||
constructor(protected mount: string) {
|
||||
}
|
||||
constructor(protected mount: string) {}
|
||||
|
||||
shouldRun(): boolean {
|
||||
return !this.hasRun;
|
||||
@@ -37,7 +38,7 @@ export default class ScanFoldersTask implements TaskInterface {
|
||||
console.log('file', pathname);
|
||||
const type = await fileTypeFromFile(pathname);
|
||||
if (type === undefined || type.mime.startsWith('audio')) {
|
||||
console.log(await FFMpegService.checkFile(pathname));
|
||||
console.log(await this.ffmpegService.checkFile(pathname));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user