async waitForActivations()

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);
        }
    }