in src/agentmgr.js [260:380]
async waitForActivations() {
this.activationsSeen = this.activationsSeen || {};
// secondary loop to get next activation
// the $waitForActivation agent activation will block, but only until
// it times out, hence we need to retry when it fails
while (this.polling) {
try {
let activation;
if (this.concurrency) {
// invoke - blocking for up to 1 minute
activation = await this.wsk.actions.invoke({
name: this.actionName,
params: {
$waitForActivation: true
},
blocking: true
});
log.verboseWrite(".");
} else {
// poll for the newest activation
const since = Date.now();
// older openwhisk only allows the name of an action when filtering activations
// newer openwhisk versions want package/name
let name = this.actionName;
if (await this.openwhiskSupports("activationListFilterOnlyBasename")) {
if (this.actionName.includes("/")) {
name = this.actionName.substring(this.actionName.lastIndexOf("/") + 1);
}
}
while (true) {
const activations = await this.wsk.activations.list({
name: `${name}_wskdebug_invoked`,
since: since,
limit: 1, // get the most recent one only
docs: true // include results
});
if (activations && activations.length >= 1) {
const a = activations[0];
if (a.response && a.response.result && !this.activationsSeen[a.activationId]) {
activation = a;
if (!activation.response.success) {
throw {
error: activation
};
}
break;
}
}
log.verboseWrite(".");
// need to limit load on openwhisk (activation list)
await sleep(1000);
}
}
log.verboseWrite(".");
// check for successful response with a new activation
if (activation && activation.response) {
const params = activation.response.result;
// mark this as seen so we don't reinvoke it
this.activationsSeen[activation.activationId] = true;
log.verbose(); // because of the .....
log.log();
log.highlight("Activation: ", params.$activationId);
return params;
} else if (activation && activation.activationId) {
// ignore this and retry.
// usually means the action did not respond within one minute,
// which in turn is unlikely for the agent who should exit itself
// after 50 seconds, so can only happen if there was some delay
// outside the action itself
} else {
// unexpected, just log and retry
log.log("Unexpected empty response while waiting for new activations:", activation);
}
} catch (e) {
// look for special error codes from agent
const errorCode = getActivationError(e).code;
if (errorCode === 42) {
// 42 => retry, do nothing here (except logging progress)
log.verboseWrite(".");
} else if (errorCode === 43) {
// 43 => graceful shutdown (for unit tests)
log.log("Graceful shutdown requested by agent (only for unit tests)");
return null;
} else if (e.statusCode === 503 && !this.concurrency) {
// 503 => openwhisk activation DB likely overloaded with requests, warn, wait a bit and retry
log.verbose("x");
log.warn("Server responded with 503 while looking for new activation records. Consider using --ngrok option.")
await sleep(5000);
} else {
// otherwise log error and abort
log.error();
log.error("Unexpected error while polling agent for activation:");
log.deepObject(e);
throw new Error("Unexpected error while polling agent for activation.");
}
}
// some small wait to avoid too many requests in case things run amok
await sleep(100);
}
}