Browse Source

Service loading/installation/connection improvement

master
David Ludwig 4 years ago
parent
commit
eeec01c105
5 changed files with 112 additions and 47 deletions
  1. +11
    -4
      .env.example
  2. +44
    -38
      src/server/Application.ts
  3. +8
    -5
      src/server/services/Service.ts
  4. +34
    -0
      src/server/services/TvDb.ts
  5. +15
    -0
      src/server/services/index.ts

+ 11
- 4
.env.example View File

@ -1,7 +1,17 @@
# Keys ---------------------------------------------------------------------------------------------
# Application key to sign stuff
APP_KEY_FILE = /run/secrets/app_key
# Database credentials
# Discord bot token
DISCORD_BOT_KEY_FILE = /run/secrets/discord_bot_key
# TVDB API key
TVDB_KEY_FILE = /run/secrets/tvdb_key
TVDB_PIN =
# Database -----------------------------------------------------------------------------------------
DB_TYPE = mysql
DB_HOST = database
DB_PORT = 3306
@ -16,6 +26,3 @@ TORRENT_CLIENT_IPC_SOCKET = /tmp/torrent_client.sock
# Web server port
WEBSERVER_PORT = 3200
# Discord bot token
DISCORD_BOT_TOKEN =

+ 44
- 38
src/server/Application.ts View File

@ -1,17 +1,19 @@
import DiscordBot from "./services/DiscordBot";
import services from "./services";
import Service from "./services/Service";
import TorrentClientIpc from "./services/TorrentClientIpc";
import WebServer from "./services/WebServer";
import { User, RegisterToken } from "./database/entities";
import Database from "./services/Database";
import assert from "assert";
let instance: Application;
interface ServiceMap {
[name: string]: Service
}
/**
* The main application class
*/
export default class Application
{
private static __instance: Application;
/**
* The application key used for signing stuff
*/
@ -20,56 +22,40 @@ export default class Application
/**
* All available services
*/
protected services: Service[];
/**
* The database service
*/
protected database!: Database;
/**
* The discord bot service
*/
protected discord!: DiscordBot;
/**
* The webserver service
*/
protected web!: WebServer;
/**
* The torrent client service
*/
protected torrent!: TorrentClientIpc;
protected services: ServiceMap = {};
/**
* Return the current application instance
*/
public static instance() {
return instance;
return this.__instance;
}
/**
* Create a new application instance
*/
public constructor(appKey: string) {
instance = this;
Application.__instance = this;
this.APP_KEY = appKey;
this.services = [
this.database = new Database(this),
// this.discord = new DiscordBot(this),
this.web = new WebServer(this),
// this.torrent = new TorrentClientIpc(this)
]
for (let ServiceClass of Object.values(services)) {
this.installService(ServiceClass);
}
}
// this.torrent.logging = false;
/**
* Install a service into the application
*/
protected installService(ServiceClass: new (app: Application) => Service) {
let service = new ServiceClass(this);
this.services[service.name] = service;
}
/**
* Boot the application and all of the services
*/
protected async boot() {
return Promise.all(this.services.map(service => service.boot()));
let services = Object.values(this.services);
return Promise.all(services.map(service => service.boot()));
}
/**
@ -91,7 +77,8 @@ export default class Application
* Shutdown the application
*/
protected shutdown() {
return Promise.all(this.services.map(service => service.shutdown()));
let services = Object.values(this.services);
return Promise.all(services.map(service => service.shutdown()));
}
/**
@ -100,7 +87,9 @@ export default class Application
public async start() {
await this.boot();
await this.initialize();
this.services.forEach(service => service.start());
for (let service of Object.values(this.services)) {
service.start();
}
}
/**
@ -110,4 +99,21 @@ export default class Application
await this.shutdown();
process.exit(code);
}
// Access --------------------------------------------------------------------------------------
/**
* Get all available services
*/
public serviceList() {
return Object.keys(this.services);
}
/**
* Get an application service instance
*/
public service<T extends Service>(serviceName: string) {
assert(serviceName in this.services);
return <T>this.services[serviceName];
}
}

+ 8
- 5
src/server/services/Service.ts View File

@ -2,7 +2,10 @@ import Application from "../Application";
export default abstract class Service
{
private readonly __name: string;
/**
* The name of the service
*/
public readonly name: string;
/**
* The application instance
@ -19,7 +22,7 @@ export default abstract class Service
*/
public constructor(name: string, app: Application) {
this.app = app;
this.__name = name;
this.name = name;
}
// Required Service Implementation -------------------------------------------------------------
@ -44,12 +47,12 @@ export default abstract class Service
};
/**
* Log to the console
* Service-specific logging
*/
protected log(...args: any[]) {
public log(...args: any[]) {
if (!this.logging) {
return;
}
console.log(`[${this.__name}]:`, ...args);
console.log(`[${this.name}]:`, ...args);
}
}

+ 34
- 0
src/server/services/TvDb.ts View File

@ -0,0 +1,34 @@
import { readFile } from "fs/promises";
import Application from "@server/Application";
import TVDB from "tvdb-v4";
import Service from "./Service";
export default class TvDb extends Service
{
/**
* The active TVDB instance
*/
protected tvdb!: TVDB;
/**
* Create a new TvDb service instance
*/
public constructor(app: Application) {
super("TVDB", app);
this.tvdb;
}
/**
* Boot the service
*/
public async boot() {
let apiKey = await readFile(<string>process.env["TVDB_KEY_FILE"]);
}
/**
* Shutdown the service
*/
public async shutdown() {
}
}

+ 15
- 0
src/server/services/index.ts View File

@ -0,0 +1,15 @@
import Database from "./Database";
import DiscordBot from "./DiscordBot";
import MovieSearch from "./MovieSearch";
import TorrentClientIpc from "./TorrentClientIpc";
import TvDb from "./TvDb";
import WebServer from "./WebServer";
export default {
Database,
// DiscordBot,
MovieSearch,
// TorrentClientIpc,
TvDb,
WebServer
}

Loading…
Cancel
Save