diff --git a/.github/workflows/stress.yml b/.github/workflows/stress.yml index 26db3c38..2665885a 100644 --- a/.github/workflows/stress.yml +++ b/.github/workflows/stress.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - os: [macos-latest, ubuntu-latest, windows-latest] + os: [macos-latest, ubuntu-latest, windows-2019, windows-2022] steps: - name: Free Disk Space (Ubuntu) diff --git a/README.md b/README.md index f9b06551..be2b3374 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Requirements for Linux: #### Currently supported MySQL versions -- If using the system installed MySQL server: 8.0.11 and newer +- If using the system installed MySQL server: 5.7.19 and newer - If not using the system installed MySQL server: 8.0.39 - 8.0.41, 8.1.0 - 8.3.0, 8.4.2 - 8.4.4, and 9.0.1 - 9.2.0 ## Example Usage - Application Code @@ -112,11 +112,11 @@ Default: undefined Description: Version of MySQL to use for the database. Uses semver for getting the version, so valid semver versions are allowed. For example, `8.x` is a valid version and will use the latest 8.x MySQL version. If left undefined: -- If the system has MySQL installed, the system-installed version will be used. If the installed version is not supported by this package (currently <8.0.11), an error will be thrown unless `ignoreUnsupportedSystemVersion` is set to `true`. +- If the system has MySQL installed, the system-installed version will be used. If the installed version is not supported by this package (currently <5.7.19), an error will be thrown unless `ignoreUnsupportedSystemVersion` is set to `true`. - If the system does not have MySQL installed, the latest version of MySQL in the `versions.json` file in this package will be downloaded. If defined: -- If the version is older than 8.0.11, an error will be thrown as this package does not currently support those versions of MySQL. +- If the version is older than 5.7.19, an error will be thrown as this package does not currently support those versions of MySQL. - If the desired version of MySQL is installed on the system, the installed version will be used. Otherwise the selected version will be downloaded from the MySQL CDN as long as it can be found in the `versions.json` file. If it cannot be found in that file, an error will be thrown. - `dbName: string` @@ -179,7 +179,7 @@ Description: The port that the MySQL X Plugin will listen on. If set to 0, a ran Default: false -Description: This option only applies if the system-installed MySQL version is lower than the oldest supported MySQL version for this package (8.0.11) and the `version` option is not defined. If set to `true`, this package will use the latest version of MySQL instead of the system-installed version. If `false`, the package will throw an error. +Description: This option only applies if the system-installed MySQL version is lower than the oldest supported MySQL version for this package (5.7.19) and the `version` option is not defined. If set to `true`, this package will use the latest version of MySQL instead of the system-installed version. If `false`, the package will throw an error. - `downloadRetries: number` diff --git a/src/constants.ts b/src/constants.ts index 3fbf1581..799c3392 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -4,7 +4,7 @@ import {normalize as normalizePath} from 'path' import { tmpdir } from "os"; import { valid as validSemver, coerce as coerceSemver } from "semver"; -export const MIN_SUPPORTED_MYSQL = '8.0.11'; +export const MIN_SUPPORTED_MYSQL = '5.7.19'; export const DEFAULT_OPTIONS_GENERATOR: () => InternalServerOptions = () => ({ version: undefined, diff --git a/src/libraries/Executor.ts b/src/libraries/Executor.ts index bff0e5bf..6023be33 100644 --- a/src/libraries/Executor.ts +++ b/src/libraries/Executor.ts @@ -1,5 +1,5 @@ import { ChildProcess, execFile, spawn } from "child_process" -import {coerce, satisfies} from 'semver'; +import {coerce, gte, lt, satisfies} from 'semver'; import * as os from 'os' import * as fsPromises from 'fs/promises'; import * as fs from 'fs'; @@ -71,7 +71,43 @@ class Executor { const socket = os.platform() === 'win32' ? `MySQL-${randomUUID()}` : `${dbPath}/m.sock` const xSocket = os.platform() === 'win32' ? `MySQLX-${randomUUID()}` : `${dbPath}/x.sock` - const process = spawn(binaryFilepath, ['--no-defaults', `--port=${port}`, `--datadir=${datadir}`, `--mysqlx-port=${mySQLXPort}`, `--mysqlx-socket=${xSocket}`, `--socket=${socket}`, `--general-log-file=${logFile}`, '--general-log=1', `--init-file=${dbPath}/init.sql`, '--bind-address=127.0.0.1', '--innodb-doublewrite=OFF', '--mysqlx=FORCE', `--log-error=${errorLogFile}`, `--user=${os.userInfo().username}`], {signal: this.DBDestroySignal.signal, killSignal: 'SIGKILL'}) + const mysqlArguments = [ + '--no-defaults', + `--port=${port}`, + `--datadir=${datadir}`, + `--mysqlx-port=${mySQLXPort}`, + `--mysqlx-socket=${xSocket}`, + `--socket=${socket}`, + `--general-log-file=${logFile}`, + '--general-log=1', + `--init-file=${dbPath}/init.sql`, + '--bind-address=127.0.0.1', + '--innodb-doublewrite=OFF', + '--mysqlx=FORCE', + `--log-error=${errorLogFile}`, + `--user=${os.userInfo().username}` + ] + + //<8.0.11 does not have MySQL X turned on by default so we will be installing the X Plugin in this if statement. + //MySQL 5.7.12 introduced the X plugin, but according to https://dev.mysql.com/doc/refman/5.7/en/document-store-setting-up.html, the database needs to be initialised with version 5.7.19. + //If the MySQL version is >=5.7.19 & <8.0.11 then install the X Plugin + if (lt(this.version, '8.0.11') && gte(this.version, '5.7.19')) { + const pluginExtension = os.platform() === 'win32' ? 'dll' : 'so'; + let pluginPath: string; + const firstPath = resolvePath(`${binaryFilepath}/../../lib/plugin`) + const secondPath = '/usr/lib/mysql/plugin' + + if (fs.existsSync(`${firstPath}/mysqlx.${pluginExtension}`)) { + pluginPath = firstPath + } else if (os.platform() === 'linux' && fs.existsSync(`${secondPath}/mysqlx.so`)) { + pluginPath = secondPath + } else { + throw 'Could not install MySQL X as the path to the plugin cannot be found.' + } + mysqlArguments.splice(1, 0, `--plugin-dir=${pluginPath}`, `--plugin-load-add=mysqlx=mysqlx.${pluginExtension}`) + } + + const process = spawn(binaryFilepath, mysqlArguments, {signal: this.DBDestroySignal.signal, killSignal: 'SIGKILL'}) //resolveFunction is the function that will be called to resolve the promise that stops the database. //If resolveFunction is not undefined, the database has received a kill signal and data cleanup procedures should run. @@ -160,7 +196,7 @@ class Executor { if (!killed) { reject('Failed to kill MySQL process to retry listening on a free port.') } - } else if (file.includes('ready for connections. Version:')) { + } else if (file.includes('ready for connections. Version:') || file.includes('Server starts handling incoming connections')) { fs.unwatchFile(errorLogFile) resolve({ port, diff --git a/stress-tests/stress.test.ts b/stress-tests/stress.test.ts index 78012180..0f522f6b 100644 --- a/stress-tests/stress.test.ts +++ b/stress-tests/stress.test.ts @@ -18,8 +18,7 @@ for (let i = 0; i < 100; i++) { const options: ServerOptions = { username: 'dbuser', - logLevel: 'LOG', - ignoreUnsupportedSystemVersion: true + logLevel: 'LOG' } if (process.env.useCIDBPath) { diff --git a/tests/sql.test.ts b/tests/sql.test.ts index f4cdbb12..e60bd45f 100644 --- a/tests/sql.test.ts +++ b/tests/sql.test.ts @@ -18,8 +18,7 @@ beforeEach(async () => { const options: ServerOptions = { username: 'root', - logLevel: 'LOG', - ignoreUnsupportedSystemVersion: true + logLevel: 'LOG' } if (process.env.useCIDBPath) { diff --git a/tests/versions.test.ts b/tests/versions.test.ts index c8297357..3039185c 100644 --- a/tests/versions.test.ts +++ b/tests/versions.test.ts @@ -25,7 +25,6 @@ for (const version of versions) { dbName: 'testingdata', username: username, logLevel: 'LOG', - ignoreUnsupportedSystemVersion: true, initSQLString: 'CREATE DATABASE mytestdb;' }