Skip to content
Snippets Groups Projects
Unverified Commit d8f968bd authored by Nemanja Glumac's avatar Nemanja Glumac Committed by GitHub
Browse files

Refactor `backend.js` #5 - Simplify the main logic (#24119)

* Simplify temporary DB path

* Set the port to 4000

* Move logic to create server config inside the base function

* Rename `kill` function to distinguish between it and Node process `kill`

* `createServer` as a method

* Remove reliance on Maps

* Stop server logic implemented directly in a method

* Remove unneeded parameter

* Start server logic implemented directly in a method

* Remove `isReady` from global scope

* Remove `delay` from the global scope

* Rename `BackendResource` to `CypressBackend`

* Rename file

* Simplify `CypressBackend`

No need to invoke the function when we can store everything
as method definitions under `CypressBackend` object.

* Pass `port` as an argument with default value

* Use template literals for logging

* Destructure `response`

* Fix small typo in the comment

* Tidy up `dbFile` in the `server`
parent d1047a0e
No related branches found
No related tags found
No related merge requests found
......@@ -7,32 +7,21 @@ const { spawn } = require("child_process");
const fetch = require("isomorphic-fetch");
let testDbId = 0;
const generateTempDbPath = () =>
path.join(os.tmpdir(), `metabase-test-${process.pid}-${testDbId++}.db`);
const CypressBackend = {
createServer(port = 4000) {
const generateTempDbPath = () =>
path.join(os.tmpdir(), `metabase-test-${process.pid}.db`);
let port = 4000;
const getPort = () => port++;
const BackendResource = createSharedResource("BackendResource", {
create({ dbKey }) {
const dbFile = generateTempDbPath();
const absoluteDbKey = dbKey ? __dirname + dbKey : dbFile;
const port = getPort();
return {
dbKey: absoluteDbKey,
dbFile: dbFile,
const server = {
dbFile: generateTempDbPath(),
host: `http://localhost:${port}`,
port: port,
port,
};
return server;
},
async start(server) {
if (!server.process) {
if (server.dbKey !== server.dbFile) {
fs.copyFileSync(`${server.dbKey}.mv.db`, `${server.dbFile}.mv.db`);
}
const javaFlags = [
"-XX:+IgnoreUnrecognizedVMOptions", // ignore options not recognized by this Java version (e.g. Java 8 should ignore Java 9 options)
"-Dh2.bindAddress=localhost", // fix H2 randomly not working (?)
......@@ -95,32 +84,43 @@ const BackendResource = createSharedResource("BackendResource", {
},
);
}
if (!(await isReady(server.host))) {
process.stdout.write(
"Waiting for backend (host=" +
server.host +
" dbKey=" +
server.dbKey +
")",
`Waiting for backend (host=${server.host}, dbFile=${server.dbFile})`,
);
while (!(await isReady(server.host))) {
if (!process.env["CI"]) {
// disable for CI since it break's CircleCI's no_output_timeout
// disable for CI since it breaks CircleCI's no_output_timeout
process.stdout.write(".");
}
await delay(500);
}
process.stdout.write("\n");
}
console.log(
"Backend ready (host=" + server.host + " dbKey=" + server.dbKey + ")",
);
console.log(`Backend ready host=${server.host}, dbFile=${server.dbFile}`);
// Copied here from `frontend/src/metabase/lib/promise.js` to decouple Cypress from Typescript
function delay(duration) {
return new Promise((resolve, reject) => setTimeout(resolve, duration));
}
async function isReady(host) {
try {
const { status } = await fetch(`${host}/api/health`);
if (status === 200) {
return true;
}
} catch (e) {}
return false;
}
},
async stop(server) {
if (server.process) {
server.process.kill("SIGKILL");
console.log(
"Stopped backend (host=" + server.host + " dbKey=" + server.dbKey + ")",
`Stopped backend (host=${server.host}, dbFile=${server.dbFile})`,
);
}
try {
......@@ -129,69 +129,6 @@ const BackendResource = createSharedResource("BackendResource", {
}
} catch (e) {}
},
});
async function isReady(host) {
try {
const response = await fetch(`${host}/api/health`);
if (response.status === 200) {
return true;
}
} catch (e) {}
return false;
}
function createSharedResource(
resourceName,
{ defaultOptions, create, start, stop },
) {
const entriesByKey = new Map();
const entriesByResource = new Map();
function kill(entry) {
if (entriesByKey.has(entry.key)) {
entriesByKey.delete(entry.key);
entriesByResource.delete(entry.resource);
const p = stop(entry.resource).then(null, err =>
console.log("Error stopping resource", resourceName, entry.key, err),
);
return p;
}
}
return {
get(options = defaultOptions) {
const dbKey = options;
const key = dbKey || {};
let entry = entriesByKey.get(key);
if (!entry) {
entry = {
key: key,
references: 0,
resource: create(options),
};
entriesByKey.set(entry.key, entry);
entriesByResource.set(entry.resource, entry);
}
++entry.references;
return entry.resource;
},
async start(resource) {
const entry = entriesByResource.get(resource);
return start(entry.resource);
},
async stop(resource) {
const entry = entriesByResource.get(resource);
if (entry && --entry.references <= 0) {
await kill(entry);
}
},
};
}
// Copied here from `frontend/src/metabase/lib/promise.js` to decouple Cypress from Typescript
function delay(duration) {
return new Promise((resolve, reject) => setTimeout(resolve, duration));
}
};
module.exports = BackendResource;
module.exports = CypressBackend;
......@@ -2,11 +2,11 @@ const { printBold } = require("./cypress-runner-utils");
const runCypress = require("./cypress-runner-run-tests");
const getVersion = require("./cypress-runner-get-version");
const generateSnapshots = require("./cypress-runner-generate-snapshots");
const BackendResource = require("./backend.js");
const CypressBackend = require("./cypress-runner-backend");
const e2eHost = process.env["E2E_HOST"];
const server = BackendResource.get({ dbKey: "" });
const server = CypressBackend.createServer();
const baseUrl = e2eHost || server.host;
const init = async () => {
......@@ -15,7 +15,7 @@ const init = async () => {
await getVersion();
printBold("Starting backend");
await BackendResource.start(server);
await CypressBackend.start(server);
printBold("Generating snapshots");
await generateSnapshots(baseUrl, cleanup);
......@@ -28,7 +28,7 @@ const init = async () => {
const cleanup = async (exitCode = 0) => {
if (!e2eHost) {
printBold("Cleaning up...");
await BackendResource.stop(server);
await CypressBackend.stop(server);
}
process.exit(exitCode);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment