From c3c90280bea75b88d473953dc7ef26819d5e2078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 25 Aug 2022 15:27:44 +0200 Subject: [PATCH] added keepalive to DatabaseManager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/eleven-bees-marry.md | 6 ++++ .changeset/famous-hounds-sit.md | 6 ++++ .changeset/shaggy-vans-repeat.md | 18 +++++++++++ packages/backend-common/api-report.md | 1 + .../src/database/DatabaseManager.ts | 30 ++++++++++++++++++- packages/backend/src/index.ts | 2 +- .../default-app/packages/backend/src/index.ts | 2 +- 7 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 .changeset/eleven-bees-marry.md create mode 100644 .changeset/famous-hounds-sit.md create mode 100644 .changeset/shaggy-vans-repeat.md diff --git a/.changeset/eleven-bees-marry.md b/.changeset/eleven-bees-marry.md new file mode 100644 index 0000000000..fb0a6fb32e --- /dev/null +++ b/.changeset/eleven-bees-marry.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-common': patch +--- + +Added a keep-alive refresh loop to the `DatabaseManager`, keeping the connection +pool up. diff --git a/.changeset/famous-hounds-sit.md b/.changeset/famous-hounds-sit.md new file mode 100644 index 0000000000..d6cc852ff0 --- /dev/null +++ b/.changeset/famous-hounds-sit.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-common': patch +--- + +The options part of `DatabaseManager.fromConfig` now accepts an optional logger +field. diff --git a/.changeset/shaggy-vans-repeat.md b/.changeset/shaggy-vans-repeat.md new file mode 100644 index 0000000000..fd865c702c --- /dev/null +++ b/.changeset/shaggy-vans-repeat.md @@ -0,0 +1,18 @@ +--- +'@backstage/create-app': patch +--- + +The options part of `DatabaseManager.fromConfig` now accepts an optional logger +field. You may want to supply that logger in your backend initialization code to +ensure that you can get relevant logging data when things happen related to the +connection pool. + +In `packages/backend/src/index.ts`: + +```diff + function makeCreateEnv(config: Config) { + const root = getRootLogger(); + ... +- const databaseManager = DatabaseManager.fromConfig(config); ++ const databaseManager = DatabaseManager.fromConfig(config, { logger: root }); +``` diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index af62238925..40bd885fe8 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -252,6 +252,7 @@ export class DatabaseManager { // @public export type DatabaseManagerOptions = { migrations?: PluginDatabaseManager['migrations']; + logger?: Logger; }; // @public diff --git a/packages/backend-common/src/database/DatabaseManager.ts b/packages/backend-common/src/database/DatabaseManager.ts index 39ff864f8c..290cd4b181 100644 --- a/packages/backend-common/src/database/DatabaseManager.ts +++ b/packages/backend-common/src/database/DatabaseManager.ts @@ -29,6 +29,8 @@ import { } from './connection'; import { PluginDatabaseManager } from './types'; import path from 'path'; +import { Logger } from 'winston'; +import { stringifyError } from '@backstage/errors'; /** * Provides a config lookup path for a plugin's config block. @@ -44,6 +46,7 @@ function pluginPath(pluginId: string): string { */ export type DatabaseManagerOptions = { migrations?: PluginDatabaseManager['migrations']; + logger?: Logger; }; /** @@ -339,6 +342,31 @@ export class DatabaseManager { schemaOverrides, ); - return createDatabaseClient(pluginConfig, databaseClientOverrides); + const client = createDatabaseClient(pluginConfig, databaseClientOverrides); + this.startKeepaliveLoop(pluginId, client); + + return client; + } + + private startKeepaliveLoop(pluginId: string, client: Knex): void { + let lastKeepaliveFailed = false; + + setInterval(() => { + client.raw('select 1').then( + () => { + lastKeepaliveFailed = false; + }, + (error: unknown) => { + if (!lastKeepaliveFailed) { + lastKeepaliveFailed = true; + this.options?.logger?.warn( + `Database keepalive failed for plugin ${pluginId}, ${stringifyError( + error, + )}`, + ); + } + }, + ); + }, 60 * 1000); } } diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 1942c36ad1..af405589c1 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -69,7 +69,7 @@ function makeCreateEnv(config: Config) { discovery, tokenManager, }); - const databaseManager = DatabaseManager.fromConfig(config); + const databaseManager = DatabaseManager.fromConfig(config, { logger: root }); const cacheManager = CacheManager.fromConfig(config); const taskScheduler = TaskScheduler.fromConfig(config); diff --git a/packages/create-app/templates/default-app/packages/backend/src/index.ts b/packages/create-app/templates/default-app/packages/backend/src/index.ts index ef05fa50ee..f13190fbdb 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/index.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/index.ts @@ -36,7 +36,7 @@ function makeCreateEnv(config: Config) { const reader = UrlReaders.default({ logger: root, config }); const discovery = SingleHostDiscovery.fromConfig(config); const cacheManager = CacheManager.fromConfig(config); - const databaseManager = DatabaseManager.fromConfig(config); + const databaseManager = DatabaseManager.fromConfig(config, { logger: root }); const tokenManager = ServerTokenManager.noop(); const taskScheduler = TaskScheduler.fromConfig(config); const permissions = ServerPermissionClient.fromConfig(config, {