diff --git a/services/torrent-client/package.json b/services/torrent-client/package.json index 43bb422..ccf3e55 100644 --- a/services/torrent-client/package.json +++ b/services/torrent-client/package.json @@ -26,6 +26,8 @@ "typescript": "^4.2.3" }, "dependencies": { + "@autoplex/microservice": "^0.0.0", + "@autoplex/utils": "^0.0.0", "bitfield": "^4.0.0", "mysql": "^2.18.1", "node-ipc": "^9.1.4", diff --git a/services/torrent-client/src/Application.ts b/services/torrent-client/src/Application.ts deleted file mode 100644 index cba7e5e..0000000 --- a/services/torrent-client/src/Application.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Equal } from "typeorm"; -import connectToDatabase from "./database"; -import IpcInterface from "./services/IpcInterface"; -import TorrentClient from "./services/TorrentClient"; - -export default class Application -{ - /** - * The torrent client instance - */ - private __client: TorrentClient; - - /** - * The IPC interface for the torrent client - */ - private __ipcInterface: IpcInterface; - - /** - * Create the application - */ - public constructor() { - this.__client = new TorrentClient(); - this.__ipcInterface = new IpcInterface(this.__client); - } - - /** - * Boot the application services - */ - private async boot() { - await connectToDatabase(); - await this.__client.boot(); - await this.__ipcInterface.boot(); - } - - /** - * Start and run the application - */ - public async exec() { - await this.boot(); - console.log("Torrent client ready"); - } - - /** - * Get the torrent client instance - */ - public get torrentClient() { - return this.__client; - } -} diff --git a/services/torrent-client/src/database/index.ts b/services/torrent-client/src/database/index.ts index 8de7bfc..3b3b3db 100644 --- a/services/torrent-client/src/database/index.ts +++ b/services/torrent-client/src/database/index.ts @@ -1,15 +1,16 @@ -import { readFileSync } from "fs"; import { createConnection } from "typeorm"; import entities from "./entities"; -export default async function connectToDatabase() { +export default async function connectToDatabase(host: string, port: number, username: string, + password: string, database: string) +{ return createConnection({ - type : <"mysql" | "mariadb">process.env["DB_TYPE"], - host : process.env["DB_HOST"], - port : parseInt(process.env["DB_PORT"]), - username : process.env["DB_USER"], - password : readFileSync(process.env["DB_PASSWORD_FILE"]).toString().trim(), - database : process.env["DB_DATABASE"], + type: "mysql", + host, + port, + username, + password, + database, synchronize: true, entities, migrations: ["src/migrations/*.ts"] diff --git a/services/torrent-client/src/index.ts b/services/torrent-client/src/index.ts index 96b6def..b5b506a 100644 --- a/services/torrent-client/src/index.ts +++ b/services/torrent-client/src/index.ts @@ -1,7 +1,11 @@ -import Application from "./Application"; +import { Microservice } from "@autoplex/microservice"; +import * as services from "./services"; // Create the application -let app = new Application(); +let app = new Microservice(); + +// Install the services +app.installServices(Object.values(services)); // Execute the app -app.exec(); +app.exec().then(process.exit); diff --git a/services/torrent-client/src/services/Database.ts b/services/torrent-client/src/services/Database.ts new file mode 100644 index 0000000..d2ec00c --- /dev/null +++ b/services/torrent-client/src/services/Database.ts @@ -0,0 +1,38 @@ +import { Connection } from "typeorm"; +import connectToDatabase from "../database"; +import { env, secret } from "@autoplex/utils"; +import { InternalService } from "@autoplex/microservice"; + +export default class Database extends InternalService +{ + /** + * The active database connection + */ + public connection!: Connection; + + /** + * The service name + */ + public get name() { + return "Database"; + } + + /** + * Boot the database service + */ + public async boot() { + let host = env("DB_HOST"); + let port = parseInt(env("DB_PORT")); + let username = env("DB_USER"); + let password = await secret(env("DB_PASSWORD_FILE")); + let database = env("DB_DATABASE"); + this.connection = await connectToDatabase(host, port, username, password, database); + } + + /** + * Shutdown the database service + */ + public async shutdown() { + await this.connection.close(); + } +} diff --git a/services/torrent-client/src/services/IpcInterface.ts b/services/torrent-client/src/services/IpcInterface.ts index 92e38fd..78c4333 100644 --- a/services/torrent-client/src/services/IpcInterface.ts +++ b/services/torrent-client/src/services/IpcInterface.ts @@ -6,18 +6,19 @@ import { Socket } from "net"; import assert from "assert"; import WebTorrent from "webtorrent-hybrid"; import TorrentClient from "./TorrentClient"; +import { InternalService, Microservice } from "@autoplex/microservice"; type IAddTorrent = string | { type: "Buffer", data: number[] } -export default class IpcInterface +export default class IpcInterface extends InternalService { /** * The torrent client instance */ - protected torrentClient: TorrentClient; + protected torrentClient!: TorrentClient; /** * Quick reference to the IPC server @@ -27,18 +28,28 @@ export default class IpcInterface /** * Create a new IPC interface */ - public constructor(client: TorrentClient) { + public constructor(app: Microservice) { + super(app); ipc.config.id = "torrent-client"; ipc.config.retry = 1500; ipc.config.silent = true; + } - this.torrentClient = client; + /** + * The service name + */ + public get name() { + return "IPC"; } /** * Boot the IPC interface */ public boot() { + // Store a reference to the torrent client + this.torrentClient = this.app.service("Torrent Client"); + + // Boot the IPC socket return new Promise(async (resolve, reject) => { console.log("Serving:", process.env["IPC_SOCKET_PATH"]); await mkdir(dirname(process.env["IPC_SOCKET_PATH"]), { recursive: true }); diff --git a/services/torrent-client/src/services/TorrentClient.ts b/services/torrent-client/src/services/TorrentClient.ts index 363f600..2917f9a 100644 --- a/services/torrent-client/src/services/TorrentClient.ts +++ b/services/torrent-client/src/services/TorrentClient.ts @@ -1,3 +1,4 @@ +import { InternalService } from "@autoplex/microservice"; import assert from "assert"; import MagnetUri from "magnet-uri"; import WebTorrent from "webtorrent-hybrid"; @@ -6,7 +7,7 @@ import { extname, join, sep } from "path"; import Torrent from "../database/entities/Torrent"; import rimraf from "rimraf"; import { ISerializedTorrent, TorrentState } from "../common"; -import { EventEmitter } from "events"; +import { Database } from "."; interface IAddOptions { downloadPath?: string; @@ -32,7 +33,7 @@ export declare interface TorrentClient { ): this; } -export class TorrentClient extends EventEmitter +export class TorrentClient extends InternalService { /** * The current WebTorrent instance (available after boot) @@ -41,6 +42,16 @@ export class TorrentClient extends EventEmitter // --------------------------------------------------------------------------------------------- + /** + * The service name + */ + public get name() { + return "Torrent Client" + } + + /** + * Boot the service + */ public async boot() { this.__webtorrent = new WebTorrent(); @@ -53,8 +64,14 @@ export class TorrentClient extends EventEmitter torrent.on("noPeers", (...args) => this.onTorrentNoPeers(torrent, ...args)); torrent.on("wire", (...args) => this.onTorrentWire(torrent, ...args)); }); + } - await this.loadTorrents(); + /** + * @TODO really this is kinda bad putting this here... + * Start the torrent client + */ + public start() { + this.loadTorrents(); } // Event Handling ------------------------------------------------------------------------------ diff --git a/services/torrent-client/src/services/index.ts b/services/torrent-client/src/services/index.ts new file mode 100644 index 0000000..10435e8 --- /dev/null +++ b/services/torrent-client/src/services/index.ts @@ -0,0 +1,9 @@ +import Database from "./Database"; +import IpcInterface from "./IpcInterface"; +import TorrentClient from "./TorrentClient"; + +export { + Database, + IpcInterface, + TorrentClient +}