Skip to content

Commit

Permalink
feat: add backoff in each retry and calls connectDevice if reachable (#…
Browse files Browse the repository at this point in the history
…706)

* chore: add backoff in each retry and calls connectDevice if reachable

* adjust

* add misisng await
  • Loading branch information
KazuCocoa authored Jan 29, 2025
1 parent ab02600 commit 0f14e79
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 15 deletions.
41 changes: 40 additions & 1 deletion packages/appium-tizen-tv-driver/lib/cli/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import {exec} from 'teen_process';
import {fs, system} from 'appium/support';
import path from 'path';
import log from '../logger';
import net from 'node:net';
import _ from 'lodash';

const TIZEN_BIN_NAME = 'tizen';
const SDB_BIN_NAME = 'sdb';
Expand All @@ -16,6 +18,11 @@ export const CMD_TIMEOUT_MS = 120000;
*/
export const CMD_RETRY_MAX = 2;

/**
* back off time in each retry
*/
export const CMD_RETRY_BACKOFF_MS = 1000;

/**
* Lookup of path parts by bin name, relative to `TIZEN_HOME` env var
*/
Expand Down Expand Up @@ -90,7 +97,39 @@ async function setBin(name) {
bins[name] = bin;
log.info(`Binary was found at ${bin}`);
}
export {runCmd, setBin, TIZEN_BIN_NAME, SDB_BIN_NAME};

/**
* Check the connection of the given host:port
* @param {string} udid Expected to be <host:port> string
* @param {number} timeout
* @returns
*/
async function checkConnection(udid, timeout = 5000) {
const [host, port] = _.split(udid, ':');
return new Promise((resolve, reject) => {
const socket = new net.Socket();

socket.setTimeout(timeout);
socket.on('connect', () => {
socket.destroy();
resolve(true);
});

socket.on('timeout', () => {
socket.destroy();
reject(new Error('Connection timed out'));
});

socket.on('error', (err) => {
socket.destroy();
reject(err);
});

socket.connect(_.toNumber(port), host);
});
}

export {runCmd, setBin, TIZEN_BIN_NAME, SDB_BIN_NAME, checkConnection};

/**
* @typedef {typeof TIZEN_BIN_NAME|typeof SDB_BIN_NAME} KnownBinName
Expand Down
54 changes: 48 additions & 6 deletions packages/appium-tizen-tv-driver/lib/cli/sdb.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import log from '../logger';
import {runCmd, SDB_BIN_NAME} from './helpers';
import {CMD_RETRY_BACKOFF_MS, runCmd, SDB_BIN_NAME, checkConnection} from './helpers';
import {util} from 'appium/support';
import _ from 'lodash';
import {retry} from 'asyncbox';
import { retryInterval } from 'asyncbox';

const DEBUG_PORT_RE = /^(?:.*port:\s)(?<port>\d{1,5}).*/;
const APP_LIST_RE = /^[^']*'(?<name>[^']*)'[^']+'(?<id>[^']+)'\s*$/;
Expand All @@ -26,8 +26,45 @@ const PLATFORM_VERSION_COMMAND_COMPATIBILITY = '4.0.0';
*/
async function runSDBCmd(udid, args, timeout, retryCount) {
const restriction = udid ? ['-s', udid] : [];
const _runCmd = async () => await runCmd(SDB_BIN_NAME, [...restriction, ...args], timeout);
return await retry(retryCount, _runCmd);
const _runCmd = async () => {
try {
return await runCmd(SDB_BIN_NAME, [...restriction, ...args], timeout);
} catch (err) {
await ensureDeviceConnection(udid);
// throw the original error.
throw err;
}
};
return await retryInterval(
retryCount,
CMD_RETRY_BACKOFF_MS,
_runCmd
);
}


/**
* Ensure the device connection if it is reachable.
* @param {string?} udid
*/
async function ensureDeviceConnection (udid) {
try {
if (_.isString(udid)) {
log.info(`Checking if '${udid}' is reachable.`);
const isConnected = await checkConnection(udid);
log.info(`${udid} is ${isConnected ? 'reachable' : 'unreachable'}.`);
if (isConnected) {
log.info(`Running sdb connect to ensure the connection of '${udid}'.`);
try {
await connectDevice({udid, sdbExecTimeout: 30000, sdbExecRetryCount: 1});
} catch (err) {
log.warn(`Error occurred in ensuring the connection: ${err.message}`);
};
}
} else {
log.info(`Skipping the connection check since '${udid}' is not <host:port>.`);
}
} catch {};
}

/**
Expand Down Expand Up @@ -82,7 +119,11 @@ async function debugApp({appPackage, udid, sdbExecTimeout, sdbExecRetryCount}, p

log.info(`Starting ${appPackage} in debug mode on ${udid} up to ${sdbExecRetryCount} times`);
try {
const port = await retry(sdbExecRetryCount, getDebugPort);
const port = await retryInterval(
sdbExecRetryCount,
CMD_RETRY_BACKOFF_MS,
getDebugPort
);
log.info(`Debug port opened on ${port}`);
return port;
} catch (e) {
Expand Down Expand Up @@ -237,7 +278,8 @@ export {
_buildDebugCommand,
_parseDebugPort,
_parseCapability,
deviceCapabilities
deviceCapabilities,
ensureDeviceConnection
};

/**
Expand Down
30 changes: 22 additions & 8 deletions packages/appium-tizen-tv-driver/lib/cli/tizen.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
import { retry } from 'asyncbox';
import { retryInterval } from 'asyncbox';
import log from '../logger';
import {runCmd, TIZEN_BIN_NAME} from './helpers';
import {CMD_RETRY_BACKOFF_MS, runCmd, TIZEN_BIN_NAME} from './helpers';
import { ensureDeviceConnection } from './sdb';

/**
* @param {string[]} args
* @param {string} udid
* @param {number} timeout Timeout to raise an error
* @param {number} retryCount
*/
async function runTizenCmd(args, timeout, retryCount) {
const _runCmd = async () => await runCmd(TIZEN_BIN_NAME, args, timeout);
return await retry(retryCount, _runCmd);
async function runTizenCmd(args, udid, timeout, retryCount) {
const _runCmd = async () => {
try {
return await runCmd(TIZEN_BIN_NAME, args, timeout);
} catch (err) {
await ensureDeviceConnection(udid);
// throw the original error.
throw err;
}
};
return await retryInterval(
retryCount,
CMD_RETRY_BACKOFF_MS,
_runCmd
);
}

/**
Expand Down Expand Up @@ -43,7 +57,7 @@ async function tizenInstall({app, udid, sdbExecTimeout, sdbExecRetryCount}) {

// If an error occurred in the installation command, it will raise an error as well.
// e.g. Different signature app is already installed.
const {stdout} = await runTizenCmd(['install', '-n', app, '-s', udid], sdbExecTimeout, sdbExecRetryCount);
const {stdout} = await runTizenCmd(['install', '-n', app, '-s', udid], udid, sdbExecTimeout, sdbExecRetryCount);
if (/successfully/i.test(stdout)) {
return;
}
Expand Down Expand Up @@ -85,7 +99,7 @@ async function tizenUninstall({appPackage, udid, sdbExecTimeout, sdbExecRetryCou
// --------------------
// Total time: 00:00:00.324

const {stdout} = await runTizenCmd(['uninstall', '-p', appPackage, '-s', udid], sdbExecTimeout, sdbExecRetryCount);
const {stdout} = await runTizenCmd(['uninstall', '-p', appPackage, '-s', udid], udid, sdbExecTimeout, sdbExecRetryCount);
if (/uninstall completed/i.test(stdout)) {
// ok
return;
Expand All @@ -103,7 +117,7 @@ async function tizenUninstall({appPackage, udid, sdbExecTimeout, sdbExecRetryCou
*/
async function tizenRun({appPackage, udid, sdbExecTimeout, sdbExecRetryCount}) {
log.info(`Running tizen app '${appPackage}' on device '${udid}'`);
return await runTizenCmd(['run', '-p', appPackage, '-s', udid], sdbExecTimeout, sdbExecRetryCount);
return await runTizenCmd(['run', '-p', appPackage, '-s', udid], udid, sdbExecTimeout, sdbExecRetryCount);
}

export {runTizenCmd, tizenInstall, tizenUninstall, tizenRun};
Expand Down

0 comments on commit 0f14e79

Please sign in to comment.