From 547ed63037ed9491931407acea553d05aa25e8fc Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Mon, 6 Oct 2025 18:47:32 +0400 Subject: [PATCH 01/17] use process.kill for all platforms and early return if already killed --- src/libraries/Executor.ts | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/libraries/Executor.ts b/src/libraries/Executor.ts index 24dd4a6..c6a33b6 100644 --- a/src/libraries/Executor.ts +++ b/src/libraries/Executor.ts @@ -36,18 +36,10 @@ class Executor { } async #killProcess(process: ChildProcess): Promise { - let killed = false; - if (os.platform() === 'win32') { - const {error, stderr} = await this.#executeFile('taskkill', ['/pid', String(process.pid), '/t', '/f']) - if (!error && !stderr) { - killed = true; - } else { - this.logger.error(error || stderr) - } - } else { - killed = process.kill() - } - return killed; + // If the process has already been killed, return true + if (process.kill(0) === false) return true + + return process.kill() } //Returns a path to the binary if it should be deleted From fa4ab0b961fade70fc23a73e82574bf163bba595 Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Mon, 6 Oct 2025 18:55:42 +0400 Subject: [PATCH 02/17] add warning if killing already killed process --- src/libraries/Executor.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libraries/Executor.ts b/src/libraries/Executor.ts index c6a33b6..460d741 100644 --- a/src/libraries/Executor.ts +++ b/src/libraries/Executor.ts @@ -37,7 +37,10 @@ class Executor { async #killProcess(process: ChildProcess): Promise { // If the process has already been killed, return true - if (process.kill(0) === false) return true + if (process.kill(0) === false) { + this.logger.warn('Called #killProcess to kill mysqld but it has already been killed.') + return true + } return process.kill() } From 98fbef990a88a835211377266462e4bd50242ea2 Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Mon, 6 Oct 2025 21:46:34 +0400 Subject: [PATCH 03/17] run cleanup operations and call resolve on exit from signal --- src/libraries/Executor.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/libraries/Executor.ts b/src/libraries/Executor.ts index 460d741..3fd11ae 100644 --- a/src/libraries/Executor.ts +++ b/src/libraries/Executor.ts @@ -129,7 +129,29 @@ class Executor { fs.unwatchFile(errorLogFile) if (signal) { - this.logger.log('Exiting because of aborted signal.') + this.logger.log('Exiting because the process received a signal.') + + if (getInternalEnvVariable('deleteDBAfterStopped') === 'true') { + try { + await fsPromises.rm(dbPath, {recursive: true, force: true, maxRetries: 50, retryDelay: 100}) + } catch (e) { + this.logger.error('An error occurred while deleting database path after aborted signal. The error was:', e) + } + } + + const binaryPathToDelete = this.#returnBinaryPathToDelete(binaryFilepath, options) + if (binaryPathToDelete) { + try { + await fsPromises.rm(binaryPathToDelete, {force: true, recursive: true, maxRetries: 50}) + } catch (e) { + this.logger.error('An error occurred while deleting database binary after aborted signal. The error was:', e) + } + } + + if (resolveFunction) { + resolveFunction() + } + return } From e670658a7640915ab5c583bd65f8c87395fe5f5b Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Tue, 7 Oct 2025 09:32:26 +0400 Subject: [PATCH 04/17] log signal received --- src/libraries/Executor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Executor.ts b/src/libraries/Executor.ts index 3fd11ae..e8a039b 100644 --- a/src/libraries/Executor.ts +++ b/src/libraries/Executor.ts @@ -129,7 +129,7 @@ class Executor { fs.unwatchFile(errorLogFile) if (signal) { - this.logger.log('Exiting because the process received a signal.') + this.logger.log('Exiting because the process received a signal:', signal) if (getInternalEnvVariable('deleteDBAfterStopped') === 'true') { try { From 3d176c538f5b314e467889c70b6df252f62b1929 Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Tue, 7 Oct 2025 11:48:18 +0400 Subject: [PATCH 05/17] use same process close logic for signal and code --- src/libraries/Executor.ts | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/src/libraries/Executor.ts b/src/libraries/Executor.ts index e8a039b..5d78bb7 100644 --- a/src/libraries/Executor.ts +++ b/src/libraries/Executor.ts @@ -130,29 +130,8 @@ class Executor { if (signal) { this.logger.log('Exiting because the process received a signal:', signal) - - if (getInternalEnvVariable('deleteDBAfterStopped') === 'true') { - try { - await fsPromises.rm(dbPath, {recursive: true, force: true, maxRetries: 50, retryDelay: 100}) - } catch (e) { - this.logger.error('An error occurred while deleting database path after aborted signal. The error was:', e) - } - } - - const binaryPathToDelete = this.#returnBinaryPathToDelete(binaryFilepath, options) - if (binaryPathToDelete) { - try { - await fsPromises.rm(binaryPathToDelete, {force: true, recursive: true, maxRetries: 50}) - } catch (e) { - this.logger.error('An error occurred while deleting database binary after aborted signal. The error was:', e) - } - } - - if (resolveFunction) { - resolveFunction() - } - - return + } else { + this.logger.log('Exiting with code:', code) } let errorLog: string; From fe359307740392ccebd2ac9cda89ef408b8e88b2 Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Tue, 7 Oct 2025 12:52:18 +0400 Subject: [PATCH 06/17] forcibly shutdown mysqld with SIGKILL --- src/libraries/Executor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Executor.ts b/src/libraries/Executor.ts index 5d78bb7..53ed4cb 100644 --- a/src/libraries/Executor.ts +++ b/src/libraries/Executor.ts @@ -42,7 +42,7 @@ class Executor { return true } - return process.kill() + return process.kill('SIGKILL') } //Returns a path to the binary if it should be deleted From ab2554ab579ddeb266bff56d52626bd2c0b40f66 Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Wed, 8 Oct 2025 12:41:08 +0400 Subject: [PATCH 07/17] remove databaseDirectoryPath internal option --- .github/workflows/os-compatibility.yml | 1 + dist/src/constants.d.ts | 1 - src/constants.ts | 1 - src/libraries/Executor.ts | 2 +- tests/versions.test.ts | 10 +++++++++- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/os-compatibility.yml b/.github/workflows/os-compatibility.yml index d71d7d3..d942fec 100644 --- a/.github/workflows/os-compatibility.yml +++ b/.github/workflows/os-compatibility.yml @@ -33,6 +33,7 @@ jobs: - name: Run tests env: VERSION_REQUIREMENT: ${{ matrix.version-requirement }} + MOVE_MYSQLMSN_TO: ${{ runner.os == 'Windows' && 'C:\\Users\\RUNNER~1\\mysqlmsn' || '/tmp/mysqlmsn' }} run: npm run os-compat:ci - name: Upload mysqlmsn directory (Windows) diff --git a/dist/src/constants.d.ts b/dist/src/constants.d.ts index f81cb87..4126575 100644 --- a/dist/src/constants.d.ts +++ b/dist/src/constants.d.ts @@ -8,7 +8,6 @@ export declare const LOG_LEVELS: { }; declare const internalOptions: { deleteDBAfterStopped: string; - databaseDirectoryPath: string; binaryDirectoryPath: string; cli: string; }; diff --git a/src/constants.ts b/src/constants.ts index 8cf98c9..ac54144 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -32,7 +32,6 @@ export const LOG_LEVELS = { const internalOptions = { deleteDBAfterStopped: 'true', //mysqlmsn = MySQL Memory Server Node.js - databaseDirectoryPath: normalizePath(`${tmpdir()}/mysqlmsn/dbs`), binaryDirectoryPath: `${tmpdir()}/mysqlmsn/binaries`, cli: 'false' } diff --git a/src/libraries/Executor.ts b/src/libraries/Executor.ts index 53ed4cb..a0f68b2 100644 --- a/src/libraries/Executor.ts +++ b/src/libraries/Executor.ts @@ -516,7 +516,7 @@ class Executor { let retries = 0; - this.databasePath = normalizePath(`${getInternalEnvVariable('databaseDirectoryPath')}/${randomUUID().replaceAll("-", '')}`) + this.databasePath = normalizePath(`${os.tmpdir()}/mysqlmsn/dbs/${randomUUID().replaceAll("-", '')}`) const datadir = normalizePath(`${this.databasePath}/data`) diff --git a/tests/versions.test.ts b/tests/versions.test.ts index c3fd8e1..beaeef1 100644 --- a/tests/versions.test.ts +++ b/tests/versions.test.ts @@ -1,10 +1,12 @@ -import {expect, test, jest} from '@jest/globals' +import {expect, test, jest, afterAll} from '@jest/globals' import { createDB } from '../src/index' import sql from 'mysql2/promise' import { coerce, satisfies } from 'semver'; import { ServerOptions } from '../types'; import getBinaryURL from '../src/libraries/Version'; import { DOWNLOADABLE_MYSQL_VERSIONS } from '../src/constants'; +import fsPromises from 'fs/promises' +import os from 'os' const usernames = ['root', 'dbuser'] @@ -56,4 +58,10 @@ for (const version of DOWNLOADABLE_MYSQL_VERSIONS.filter(v => satisfies(v, proce //binary, we need this test here just in case all the MySQL binaries are skipped test('dummy test', () => { expect(1 + 1).toBe(2) +}) + +afterAll(async () => { + if (process.env.MOVE_MYSQLMSN_TO) { + await fsPromises.rename(`${os.tmpdir()}/mysqlmsn`, process.env.MOVE_MYSQLMSN_TO) + } }) \ No newline at end of file From 60ee200534a79baa9ea048149a9b99449482e5fc Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Wed, 8 Oct 2025 12:45:03 +0400 Subject: [PATCH 08/17] only move mysqlmsn foler if it exists --- tests/versions.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/versions.test.ts b/tests/versions.test.ts index beaeef1..6ba864f 100644 --- a/tests/versions.test.ts +++ b/tests/versions.test.ts @@ -5,6 +5,7 @@ import { coerce, satisfies } from 'semver'; import { ServerOptions } from '../types'; import getBinaryURL from '../src/libraries/Version'; import { DOWNLOADABLE_MYSQL_VERSIONS } from '../src/constants'; +import fs from 'fs' import fsPromises from 'fs/promises' import os from 'os' @@ -61,7 +62,8 @@ test('dummy test', () => { }) afterAll(async () => { - if (process.env.MOVE_MYSQLMSN_TO) { - await fsPromises.rename(`${os.tmpdir()}/mysqlmsn`, process.env.MOVE_MYSQLMSN_TO) + const originalPath = `${os.tmpdir()}/mysqlmsn` + if (process.env.MOVE_MYSQLMSN_TO && fs.existsSync(originalPath)) { + await fsPromises.rename(originalPath, process.env.MOVE_MYSQLMSN_TO) } }) \ No newline at end of file From 07984ef59e38c3008a3eceb96ce2e567f0af2b33 Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Wed, 8 Oct 2025 14:16:11 +0400 Subject: [PATCH 09/17] copy and then remove original path --- tests/versions.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/versions.test.ts b/tests/versions.test.ts index 6ba864f..5f697fc 100644 --- a/tests/versions.test.ts +++ b/tests/versions.test.ts @@ -64,6 +64,7 @@ test('dummy test', () => { afterAll(async () => { const originalPath = `${os.tmpdir()}/mysqlmsn` if (process.env.MOVE_MYSQLMSN_TO && fs.existsSync(originalPath)) { - await fsPromises.rename(originalPath, process.env.MOVE_MYSQLMSN_TO) + await fsPromises.cp(originalPath, process.env.MOVE_MYSQLMSN_TO, {recursive: true, force: true}) + await fsPromises.rm(originalPath, {force: true, recursive: true}) } }) \ No newline at end of file From 3f01ade4519a57570e80c722ffd3932d55a24473 Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Wed, 8 Oct 2025 16:16:10 +0400 Subject: [PATCH 10/17] do not copy socket files and increase maxRetries for rm --- tests/versions.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/versions.test.ts b/tests/versions.test.ts index 5f697fc..b40281b 100644 --- a/tests/versions.test.ts +++ b/tests/versions.test.ts @@ -64,7 +64,7 @@ test('dummy test', () => { afterAll(async () => { const originalPath = `${os.tmpdir()}/mysqlmsn` if (process.env.MOVE_MYSQLMSN_TO && fs.existsSync(originalPath)) { - await fsPromises.cp(originalPath, process.env.MOVE_MYSQLMSN_TO, {recursive: true, force: true}) - await fsPromises.rm(originalPath, {force: true, recursive: true}) + await fsPromises.cp(originalPath, process.env.MOVE_MYSQLMSN_TO, {recursive: true, force: true, filter: source => !source.includes('.sock')}) + await fsPromises.rm(originalPath, {force: true, recursive: true, maxRetries: 50, retryDelay: 100}) } }) \ No newline at end of file From 58cc21c1c57e016c6d7af3fa66a9ca194029fc7e Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Thu, 9 Oct 2025 12:18:47 +0400 Subject: [PATCH 11/17] do not copy mysqlmsn folder to same origin --- tests/versions.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/versions.test.ts b/tests/versions.test.ts index b40281b..dfa22ca 100644 --- a/tests/versions.test.ts +++ b/tests/versions.test.ts @@ -63,7 +63,7 @@ test('dummy test', () => { afterAll(async () => { const originalPath = `${os.tmpdir()}/mysqlmsn` - if (process.env.MOVE_MYSQLMSN_TO && fs.existsSync(originalPath)) { + if (process.env.MOVE_MYSQLMSN_TO && fs.existsSync(originalPath) && originalPath !== process.env.MOVE_MYSQLMSN_TO) { await fsPromises.cp(originalPath, process.env.MOVE_MYSQLMSN_TO, {recursive: true, force: true, filter: source => !source.includes('.sock')}) await fsPromises.rm(originalPath, {force: true, recursive: true, maxRetries: 50, retryDelay: 100}) } From dc369679ab59e33f997b9e1fd01636b395ac4eed Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Thu, 9 Oct 2025 16:40:35 +0400 Subject: [PATCH 12/17] log database deletion --- src/libraries/Executor.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libraries/Executor.ts b/src/libraries/Executor.ts index 829f738..f60b5dc 100644 --- a/src/libraries/Executor.ts +++ b/src/libraries/Executor.ts @@ -165,7 +165,9 @@ class Executor { try { if (getInternalEnvVariable('deleteDBAfterStopped') === 'true') { + this.logger.log('Deleting database path as deleteDBAfterStopped is true...') await fsPromises.rm(dbPath, {recursive: true, force: true, maxRetries: 50, retryDelay: 100}) + this.logger.log('Database deletion was successful.') } } catch (e) { this.logger.error('An error occurred while deleting database directory at path:', dbPath, '| The error was:', e) From 8eb08b68c2e7f8f577069b02fcb0490729bb06d1 Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:03:15 +0400 Subject: [PATCH 13/17] add taskkill back for Windows platforms --- src/libraries/Executor.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libraries/Executor.ts b/src/libraries/Executor.ts index f60b5dc..ab02ecb 100644 --- a/src/libraries/Executor.ts +++ b/src/libraries/Executor.ts @@ -42,6 +42,17 @@ class Executor { return true } + if (os.platform() === 'win32') { + const {error, stderr} = await this.#executeFile('taskkill', ['/pid', String(process.pid), '/t', '/f']) + + if (!error && !stderr) { + return true + } + + this.logger.error(error || stderr) + return false + } + return process.kill('SIGKILL') } From f477aea693e45a8507a94c792bfbaa9f7fb0e396 Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:36:34 +0400 Subject: [PATCH 14/17] remove databaseDirectoryPath from ciSetup --- ciSetup.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ciSetup.js b/ciSetup.js index aaa8709..d8bd284 100644 --- a/ciSetup.js +++ b/ciSetup.js @@ -4,7 +4,6 @@ process.env.useCIDBPath = true; const GitHubActionsTempFolder = process.platform === 'win32' ? 'C:\\Users\\RUNNER~1\\mysqlmsn' : '/tmp/mysqlmsn' -process.env.mysqlmsn_internal_DO_NOT_USE_databaseDirectoryPath = normalize(GitHubActionsTempFolder + '/dbs') process.env.mysqlmsn_internal_DO_NOT_USE_binaryDirectoryPath = normalize(GitHubActionsTempFolder + '/binaries') process.env.mysqlmsn_internal_DO_NOT_USE_deleteDBAfterStopped = false; From d47fdae8fdb7df1297dc38f9b8a6c64353ba5448 Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Tue, 14 Oct 2025 00:04:04 +0800 Subject: [PATCH 15/17] return true from #killProcess if taskkill says there is no running instance of task --- src/libraries/Executor.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libraries/Executor.ts b/src/libraries/Executor.ts index ab02ecb..dafe457 100644 --- a/src/libraries/Executor.ts +++ b/src/libraries/Executor.ts @@ -44,12 +44,18 @@ class Executor { if (os.platform() === 'win32') { const {error, stderr} = await this.#executeFile('taskkill', ['/pid', String(process.pid), '/t', '/f']) + const message = error || stderr - if (!error && !stderr) { + if (message) { return true } - this.logger.error(error || stderr) + if (message.toString().includes('There is no running instance of the task')) { + this.logger.warn('Called #killProcess and tried to kill mysqld process but taskkill could not because it is not running. Error received:', message) + return true + } + + this.logger.error(message) return false } From 08b04c3256706047ff7b8d184ce8bb4688562187 Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Tue, 14 Oct 2025 01:11:26 +0800 Subject: [PATCH 16/17] invert message if statement --- src/libraries/Executor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Executor.ts b/src/libraries/Executor.ts index dafe457..9b966e4 100644 --- a/src/libraries/Executor.ts +++ b/src/libraries/Executor.ts @@ -46,7 +46,7 @@ class Executor { const {error, stderr} = await this.#executeFile('taskkill', ['/pid', String(process.pid), '/t', '/f']) const message = error || stderr - if (message) { + if (!message) { return true } From 2726552f52776213b76303dd64dfba9428f7fcfd Mon Sep 17 00:00:00 2001 From: Sebastian-Webster <84299475+Sebastian-Webster@users.noreply.github.com> Date: Tue, 14 Oct 2025 12:34:59 +0800 Subject: [PATCH 17/17] log error as string --- src/libraries/Executor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Executor.ts b/src/libraries/Executor.ts index 9b966e4..9065799 100644 --- a/src/libraries/Executor.ts +++ b/src/libraries/Executor.ts @@ -55,7 +55,7 @@ class Executor { return true } - this.logger.error(message) + this.logger.error(message, '| Error toString:', message.toString()) return false }