mirror of
https://github.com/appium/appium.git
synced 2026-02-22 11:19:06 -06:00
chore(base-driver): Optimize server close algorithm (#20345)
This commit is contained in:
@@ -65,7 +65,7 @@
|
||||
"sync-pkgs:license": "sync-monorepo-packages --force --no-package-json --packages=\"!packages/logger\" LICENSE",
|
||||
"test": "run-s test:quick",
|
||||
"test:ci": "run-s test:smoke test:unit test:types test:e2e",
|
||||
"test:e2e": "lerna run --concurrency=2 test:e2e",
|
||||
"test:e2e": "lerna run test:e2e",
|
||||
"test:quick": "run-s lint test:unit test:types",
|
||||
"test:slow": "run-s test:quick test:smoke test:e2e",
|
||||
"test:smoke": "smoker --all test:smoke",
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
"postinstall": "node ./scripts/autoinstall-extensions.js",
|
||||
"publish:docs": "cross-env APPIUM_DOCS_PUBLISH=1 npm run build:docs",
|
||||
"test": "npm run test:unit",
|
||||
"test:e2e": "mocha -p --timeout 1m --slow 30s \"./test/e2e/**/*.spec.js\"",
|
||||
"test:e2e": "mocha --timeout 1m --slow 30s \"./test/e2e/**/*.spec.js\"",
|
||||
"test:smoke": "cross-env APPIUM_HOME=./local_appium_home node ./index.js driver install uiautomator2 && cross-env APPIUM_HOME=./local_appium_home node ./index.js driver list",
|
||||
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
|
||||
},
|
||||
|
||||
@@ -28,10 +28,10 @@ import {
|
||||
} from './websocket';
|
||||
import B from 'bluebird';
|
||||
import {DEFAULT_BASE_PATH} from '../constants';
|
||||
import {EventEmitter} from 'events';
|
||||
import {fs} from '@appium/support';
|
||||
import {fs, timing} from '@appium/support';
|
||||
|
||||
const KEEP_ALIVE_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
|
||||
const SERVER_CLOSE_TIMEOUT_MS = 5000;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -192,10 +192,6 @@ function configureServer({
|
||||
* @returns {AppiumServer}
|
||||
*/
|
||||
function configureHttp({httpServer, reject, keepAliveTimeout}) {
|
||||
const serverState = {
|
||||
notifier: new EventEmitter(),
|
||||
closed: false,
|
||||
};
|
||||
/**
|
||||
* @type {AppiumServer}
|
||||
*/
|
||||
@@ -208,23 +204,34 @@ function configureHttp({httpServer, reject, keepAliveTimeout}) {
|
||||
|
||||
// http.Server.close() only stops new connections, but we need to wait until
|
||||
// all connections are closed and the `close` event is emitted
|
||||
const close = appiumServer.close.bind(appiumServer);
|
||||
const originalClose = appiumServer.close.bind(appiumServer);
|
||||
appiumServer.close = async () =>
|
||||
await new B((resolve, reject) => {
|
||||
// https://github.com/nodejs/node-v0.x-archive/issues/9066#issuecomment-124210576
|
||||
serverState.closed = true;
|
||||
serverState.notifier.emit('shutdown');
|
||||
log.info('Waiting until the server is closed');
|
||||
httpServer.on('close', () => {
|
||||
log.info('Received server close event');
|
||||
resolve();
|
||||
await new B((_resolve, _reject) => {
|
||||
log.info('Closing Appium HTTP server');
|
||||
const timer = new timing.Timer().start();
|
||||
const onTimeout = setTimeout(() => {
|
||||
log.info(
|
||||
`Not all active connections have been closed within ` +
|
||||
`${timer.getDuration().asMilliSeconds.toFixed(0)}ms. Exiting anyway.`
|
||||
);
|
||||
process.exit(process.exitCode ?? 0);
|
||||
}, SERVER_CLOSE_TIMEOUT_MS);
|
||||
httpServer.once('close', () => {
|
||||
log.info(
|
||||
`Appium HTTP server has been succesfully closed after ` +
|
||||
`${timer.getDuration().asMilliSeconds.toFixed(0)}ms`
|
||||
);
|
||||
clearTimeout(onTimeout);
|
||||
_resolve();
|
||||
});
|
||||
close((err) => {
|
||||
if (err) reject(err); // eslint-disable-line curly
|
||||
originalClose((/** @type {Error|undefined} */ err) => {
|
||||
if (err) {
|
||||
_reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
appiumServer.on(
|
||||
appiumServer.once(
|
||||
'error',
|
||||
/** @param {NodeJS.ErrnoException} err */ (err) => {
|
||||
if (err.code === 'EADDRNOTAVAIL') {
|
||||
@@ -242,31 +249,7 @@ function configureHttp({httpServer, reject, keepAliveTimeout}) {
|
||||
}
|
||||
);
|
||||
|
||||
appiumServer.on(
|
||||
'connection',
|
||||
/** @param {AppiumServerSocket} socket */ (socket) => {
|
||||
socket.setTimeout(keepAliveTimeout);
|
||||
socket.on('error', reject);
|
||||
|
||||
function destroy() {
|
||||
socket.destroy();
|
||||
}
|
||||
socket._openReqCount = 0;
|
||||
socket.once('close', () => serverState.notifier.removeListener('shutdown', destroy));
|
||||
serverState.notifier.once('shutdown', destroy);
|
||||
}
|
||||
);
|
||||
|
||||
appiumServer.on('request', function (req, res) {
|
||||
const socket = /** @type {AppiumServerSocket} */ (req.connection || req.socket);
|
||||
socket._openReqCount++;
|
||||
res.on('finish', function () {
|
||||
socket._openReqCount--;
|
||||
if (serverState.closed && socket._openReqCount === 0) {
|
||||
socket.destroy();
|
||||
}
|
||||
});
|
||||
});
|
||||
appiumServer.on('connection', (socket) => socket.setTimeout(keepAliveTimeout));
|
||||
|
||||
return appiumServer;
|
||||
}
|
||||
@@ -324,7 +307,6 @@ export {server, configureServer, normalizeBasePath};
|
||||
|
||||
/**
|
||||
* @typedef {import('@appium/types').AppiumServer} AppiumServer
|
||||
* @typedef {import('@appium/types').AppiumServerSocket} AppiumServerSocket
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
],
|
||||
"scripts": {
|
||||
"test": "npm run test:unit",
|
||||
"test:e2e": "mocha -p --timeout 20s --slow 10s \"./test/e2e/**/*.spec.js\"",
|
||||
"test:e2e": "mocha --timeout 20s --slow 10s \"./test/e2e/**/*.spec.js\"",
|
||||
"test:smoke": "node ./index.js",
|
||||
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
|
||||
},
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
],
|
||||
"scripts": {
|
||||
"test": "npm run test:unit",
|
||||
"test:e2e": "mocha -p --timeout 20s --slow 10s \"./test/e2e/**/*.spec.js\"",
|
||||
"test:e2e": "mocha --timeout 20s --slow 10s \"./test/e2e/**/*.spec.js\"",
|
||||
"test:smoke": "node ./index.js",
|
||||
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user