diff --git a/tdrive/backend/node/src/cli/cmds/search_cmds/index_all.ts b/tdrive/backend/node/src/cli/cmds/search_cmds/index_all.ts index cf1cfdc3..86fc3f43 100644 --- a/tdrive/backend/node/src/cli/cmds/search_cmds/index_all.ts +++ b/tdrive/backend/node/src/cli/cmds/search_cmds/index_all.ts @@ -131,7 +131,9 @@ const command: yargs.CommandModule = { repository, spinner, }); - + spinner.start("Shutting down platform..."); + await platform.stop(); + spinner.succeed("Platform shutdown"); spinner.stop(); }, }; diff --git a/tdrive/backend/node/src/core/platform/services/database/index.ts b/tdrive/backend/node/src/core/platform/services/database/index.ts index 2f662c24..1c230be4 100644 --- a/tdrive/backend/node/src/core/platform/services/database/index.ts +++ b/tdrive/backend/node/src/core/platform/services/database/index.ts @@ -36,6 +36,14 @@ export default class Database extends TdriveService { return this; } + public async doStop(): Promise { + if (this.service) { + await this.service.disconnect(); + this.service = null; + } + return this; + } + api(): DatabaseServiceAPI { return this.service; } diff --git a/tdrive/backend/node/src/core/platform/services/database/services/index.ts b/tdrive/backend/node/src/core/platform/services/database/services/index.ts index 4b6066be..3bb13f8b 100644 --- a/tdrive/backend/node/src/core/platform/services/database/services/index.ts +++ b/tdrive/backend/node/src/core/platform/services/database/services/index.ts @@ -32,6 +32,13 @@ export default class DatabaseService implements DatabaseServiceAPI { return this.connector; } + async disconnect() { + if (this.connector) { + await this.connector.disconnect(); + this.connector = null; + } + } + getManager(): Manager { return new Manager(this.connector); } diff --git a/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/abstract-connector.ts b/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/abstract-connector.ts index bcbdd4d6..ff6e05c3 100644 --- a/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/abstract-connector.ts +++ b/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/abstract-connector.ts @@ -9,6 +9,7 @@ export abstract class AbstractConnector implements constructor(protected type: DatabaseType, protected options: T, protected secret: string) {} abstract connect(): Promise; + abstract disconnect(): Promise; abstract drop(): Promise; diff --git a/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/cassandra/cassandra.ts b/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/cassandra/cassandra.ts index a2a7b93c..956f4112 100644 --- a/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/cassandra/cassandra.ts +++ b/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/cassandra/cassandra.ts @@ -178,6 +178,12 @@ export class CassandraConnector extends AbstractConnector { + if (this.client) await this.client.shutdown(); + this.client = null; + return this; + } + async getTableDefinition(name: string): Promise { let result: string[]; diff --git a/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/index.ts b/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/index.ts index 175b944e..4be73d87 100644 --- a/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/index.ts +++ b/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/index.ts @@ -22,6 +22,11 @@ export interface Connector extends Initializable { */ connect(): Promise; + /** + * Disconnect from the database + */ + disconnect(): Promise; + /** * Get the type of connector */ diff --git a/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/mongodb.ts b/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/mongodb.ts index 4a627014..05755448 100644 --- a/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/mongodb.ts +++ b/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/mongodb.ts @@ -36,6 +36,12 @@ export class MongoConnector extends AbstractConnector { return this; } + async disconnect(): Promise { + if (this.client) await this.client.close(); + this.client = null; + return this; + } + getClient(): mongo.MongoClient { return this.client; } diff --git a/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/postgres/postgres.ts b/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/postgres/postgres.ts index d2ebf627..94dcd6a4 100644 --- a/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/postgres/postgres.ts +++ b/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/postgres/postgres.ts @@ -50,6 +50,12 @@ export class PostgresConnector extends AbstractConnector { + if (this.client) await this.client.end(); + this.client = null; + return this; + } + async init(): Promise { if (!this.client) { await this.connect(); diff --git a/tdrive/backend/node/src/core/platform/services/search/adapters/abstract.ts b/tdrive/backend/node/src/core/platform/services/search/adapters/abstract.ts index 1dd64b48..880cbebd 100644 --- a/tdrive/backend/node/src/core/platform/services/search/adapters/abstract.ts +++ b/tdrive/backend/node/src/core/platform/services/search/adapters/abstract.ts @@ -30,6 +30,9 @@ export class SearchAdapter implements SearchAdapterInterface { connect(): Promise { throw new Error("Method not implemented."); } + disconnect(): Promise { + throw new Error("Method not implemented."); + } upsert(entities: any[]): Promise { throw new Error("Method not implemented."); } diff --git a/tdrive/backend/node/src/core/platform/services/search/adapters/elasticsearch/elastic-open-search-adapter.ts b/tdrive/backend/node/src/core/platform/services/search/adapters/elasticsearch/elastic-open-search-adapter.ts index d6829b7e..a9c299bc 100644 --- a/tdrive/backend/node/src/core/platform/services/search/adapters/elasticsearch/elastic-open-search-adapter.ts +++ b/tdrive/backend/node/src/core/platform/services/search/adapters/elasticsearch/elastic-open-search-adapter.ts @@ -29,6 +29,7 @@ export default class ESAndOpenSearch extends SearchAdapter implements SearchAdap private bulkReaders = 0; private buffer: Operation[] = []; private client: OpenClient | ESClient; + private pendingTimeout: NodeJS.Timeout = null; constructor( readonly database: DatabaseServiceAPI, @@ -75,6 +76,18 @@ export default class ESAndOpenSearch extends SearchAdapter implements SearchAdap this.startBulkReader(); } + public async disconnect() { + if (this.client) { + const client = this.client; + this.client = null; + if (this.pendingTimeout) { + clearTimeout(this.pendingTimeout); + this.pendingTimeout = null; + } + await client.close(); + } + } + private async createIndex( entity: EntityDefinition, _columns: { [name: string]: ColumnDefinition }, @@ -214,10 +227,17 @@ export default class ESAndOpenSearch extends SearchAdapter implements SearchAdap let buffer; do { - await new Promise(r => - setTimeout(r, parseInt(`${this.configuration.flushInterval}`) || 3000), + await new Promise( + r => + (this.pendingTimeout = setTimeout(() => { + this.pendingTimeout = null; + r(); + }, parseInt(`${this.configuration.flushInterval}`) || 3000)), ); buffer = this.buffer; + if (!this.client) + // disconnect was called; break this tail loop + return; } while (buffer.length === 0); this.buffer = []; diff --git a/tdrive/backend/node/src/core/platform/services/search/adapters/mongosearch/index.ts b/tdrive/backend/node/src/core/platform/services/search/adapters/mongosearch/index.ts index c8cc6f38..ac3884c5 100644 --- a/tdrive/backend/node/src/core/platform/services/search/adapters/mongosearch/index.ts +++ b/tdrive/backend/node/src/core/platform/services/search/adapters/mongosearch/index.ts @@ -45,6 +45,14 @@ export default class MongoSearch extends SearchAdapter implements SearchAdapterI this.mongodb = await service.getDatabase(); } + public async disconnect() { + if (this.mongodb) { + const service = this.database.getConnector() as MongoConnector; + await service.disconnect(); + this.mongodb = null; + } + } + private async createIndex( entityDefinition: EntityDefinition, columns: { [name: string]: ColumnDefinition }, diff --git a/tdrive/backend/node/src/core/platform/services/search/api.ts b/tdrive/backend/node/src/core/platform/services/search/api.ts index 927d4e8b..da7a33ef 100644 --- a/tdrive/backend/node/src/core/platform/services/search/api.ts +++ b/tdrive/backend/node/src/core/platform/services/search/api.ts @@ -46,6 +46,7 @@ export type IndexedEntity = { export interface SearchAdapterInterface { connect(): Promise; + disconnect(): Promise; upsert(entities: any[]): Promise; remove(entities: any[]): Promise; diff --git a/tdrive/backend/node/src/core/platform/services/search/index.ts b/tdrive/backend/node/src/core/platform/services/search/index.ts index 6bd246b7..f3ccc201 100644 --- a/tdrive/backend/node/src/core/platform/services/search/index.ts +++ b/tdrive/backend/node/src/core/platform/services/search/index.ts @@ -73,6 +73,14 @@ export default class Search extends TdriveService { return this; } + public async doStop(): Promise { + if (this.service) { + await this.service.disconnect(); + this.service = null; + } + return this; + } + public async upsert(entities: never[]) { return this.service.upsert(entities); }