"use strict"; // Set up Apache OpenWhisk Client SDK const openwhisk = require('openwhisk'); const options = { apihost: , api_key: } const ow = openwhisk(options) const rand_int = () => Math.floor(Math.random() * 100) // Promise-ify setTimeout const delay = async ms => new Promise(resolve => setTimeout(resolve, ms)) // Returns function which checks whether max elapsed time has passed // since instance creation. const elapsed_time = max => { const start = new Date().getTime() return () => { const now = new Date().getTime() return (now - start) > max } } // Perform non-blocking action invocation and poll activation result using returned activation id. // `activations.get()` will return result if action has finished and result is available. // HTTP 404 returned when activation has not finished, wait and re-check after delay. // All other errors code are fatal and should be thrown to caller. // // Parameters include delay_ms which controls polling delay and max_time // which indicates maximum allowable waiting time for action to finish. const invoke_and_poll = async (action, params, delay_ms, max_time) => { const time_has_elapsed = elapsed_time(max_time) const activation = await ow.actions.invoke({name: action, params}) console.log(`new activation id: ${activation.activationId}`) let result = null while (!result) { try { result = await ow.activations.get({ name: activation.activationId }) console.log(`activation result (${activation.activationId}) now available!`) } catch (err) { if (err.statusCode !== 404) { throw err } console.log(`activation result (${activation.activationId}) not available yet`) } await delay(delay_ms) if (time_has_elapsed()) throw new Error(`Maximum polling duration has elapsed (${result.activationId})`) } return result } // Action invocation with retries when activation result indicates a failure // result.response.success boolean value shows whether action result suceeded or failed // retries parameter configures the maximum number of allowable retries const invoke_with_retries = async (invoke, retries) => { let result = null let max_invocations = retries + 1 const actvs = [] do { if (max_invocations == 0) throw new Error(`Exhaused all available retries. ${actvs}`) result = await invoke() actvs.push(result.activationId) console.log('action invocation succeeded:', result.response.success) max_invocations-- } while (!result.response.success) console.log('action result:', result.response.result) return result } ;(async () => { // 100 invocations, 1 second between polls, 15 second maximum polling time, 15 maximum retries const polling_delay_ms = 1000 const polling_timeout_ms = 1000 * 15 const maximum_retries = 5 const invocations = 200 // Generate input data for N invocations. const input = new Array(invocations).fill(null).map(() => { return { a: rand_int(), b: rand_int() } }) // Fire polling invocation with retries for each input value const output = input.map(async params => { const ow_invoke = () => invoke_and_poll('sum', params, polling_delay_ms, polling_timeout_ms) const result = await invoke_with_retries(ow_invoke, maximum_retries) console.log(`${params.a} + ${params.b} = ${result.response.result.sum}`) return result }) // Wait for all results to be returned! const all_results = await Promise.all(output) console.log(all_results.map(result => result.response.result)) })();