From 8b839d329e0a5bd954b164c6bb1d78021362c21b Mon Sep 17 00:00:00 2001 From: Julien Ripouteau Date: Sun, 10 Dec 2023 04:53:01 +0100 Subject: [PATCH] fix: release connection in provider shutdown (#977) --- providers/database_provider.ts | 8 ++++ test/database_provider.spec.ts | 84 ++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 test/database_provider.spec.ts diff --git a/providers/database_provider.ts b/providers/database_provider.ts index 0e38c6d8..5f4c40e4 100644 --- a/providers/database_provider.ts +++ b/providers/database_provider.ts @@ -110,4 +110,12 @@ export default class DatabaseServiceProvider { await this.registerReplBindings() await this.registerVineJSRules(db) } + + /** + * Gracefully close connections during shutdown + */ + async shutdown() { + const db = await this.app.container.make('lucid.db') + await db.manager.closeAll() + } } diff --git a/test/database_provider.spec.ts b/test/database_provider.spec.ts new file mode 100644 index 00000000..85300dee --- /dev/null +++ b/test/database_provider.spec.ts @@ -0,0 +1,84 @@ +import { test } from '@japa/runner' +import { IgnitorFactory } from '@adonisjs/core/factories' + +import { defineConfig } from '../src/define_config.js' +import { Database } from '../src/database/main.js' + +const BASE_URL = new URL('./tmp/', import.meta.url) +const IMPORTER = (filePath: string) => { + if (filePath.startsWith('./') || filePath.startsWith('../')) { + return import(new URL(filePath, BASE_URL).href) + } + return import(filePath) +} + +test.group('Database Provider', () => { + test('register database provider', async ({ assert }) => { + const ignitor = new IgnitorFactory() + .merge({ + rcFileContents: { + providers: [() => import('../providers/database_provider.js')], + }, + }) + .withCoreConfig() + .withCoreProviders() + .merge({ + config: { + database: defineConfig({ + connection: 'sqlite', + connections: { + sqlite: { + client: 'sqlite', + connection: { filename: new URL('./tmp/database.sqlite', import.meta.url).href }, + migrations: { naturalSort: true, paths: ['database/migrations'] }, + }, + }, + }), + }, + }) + .create(BASE_URL, { importer: IMPORTER }) + + const app = ignitor.createApp('web') + await app.init() + await app.boot() + + assert.instanceOf(await app.container.make('lucid.db'), Database) + }) + + test('release connection when app is terminating', async ({ assert }) => { + const ignitor = new IgnitorFactory() + .merge({ + rcFileContents: { + providers: [() => import('../providers/database_provider.js')], + }, + }) + .withCoreConfig() + .withCoreProviders() + .merge({ + config: { + database: defineConfig({ + connection: 'sqlite', + connections: { + sqlite: { + client: 'sqlite', + connection: { filename: new URL('./tmp/database.sqlite', import.meta.url).href }, + migrations: { naturalSort: true, paths: ['database/migrations'] }, + }, + }, + }), + }, + }) + .create(BASE_URL, { importer: IMPORTER }) + + const app = ignitor.createApp('web') + await app.init() + await app.boot() + + const db = await app.container.make('lucid.db') + + await db.from('users').catch(() => {}) + await app.terminate() + + assert.isFalse(db.manager.isConnected('sqlite')) + }) +})