pifop v0.1.6
PIFOP Functions JavaScript API
Warning: PIFOP Functions is an experimental feature, and so is this library. You are welcomed to try it out, but USE IT AT YOUR OWN RISK.
Quick start
0. Load script/module
Browser
<script src="https://pifop.com/pifop.js"></script>Node.js
npm install pifopconst pifop = require("pifop");1. Execute a PIFOP Function that takes a single input file
pifop.execute("joe/example", "apikey_ABC123", myInput)
.onFinish((execution, event) => {
// Display/use the results here
console.log(execution.result);
});2. Execute a PIFOP Function that takes multiple input files
pifop.execute("joe/example", "apikey_ABC123")
.setInput("input1", myInput1)
.setInput("input2", myInput2)
.onFinish((execution, event) => {
// Display/use the results here
console.log(execution.result);
});3. Print terminal output during execution
pifop.execute("joe/example", "apikey_ABC123", myInput)
.onProgress((execution, event) => {
// Display execution log
console.log(event.data.log);
})
.onFinish((execution, event) => {
// Display/use the results here
console.log(execution.result);
});4. Handle errors
pifop.execute("joe/example", "apikey_ABC123", myInput)
.onFinish((execution, event) => {
// Display/use the results here
console.log(execution.result);
})
.onError((execution, event) => {
// Handle errors here
console.log(event);
});Documentation
Introduction
This library is a JavaScript client API to the more generic PIFOP Functions REST API. Internally, it works by queueing "atomic" REST API calls (initialization, start, termination, etc) to perform "molecular" actions, and then it notifies you when it has completed something.
The series of atomic actions that are needed to run an execution from start to finish is automatically queued when you create an Execution with pifop.execute(...). All that you have to do is to provide the input files and listen to the events generated during the execution lifetime, as such:
pifop.execute("joe/example", "apikey_ABC123")
.setInput("inputId", myInput)
.onProgress((execution, event) => {/* Do something */})
.onFinish((execution, event) => {/* Do something */})Execution
Constructors
pifop.execute(funcUID, apiKey, [input])
Creates and returns a self-managed Execution that will automatically initialize itself, upload the provided input, start the execution and terminate it once it has finished. The returned Execution is uninitialized, but you don't have to initialize it yourself. Just provide the input and set the event listeners as shown above and you are good to go.
funcUID: a function Universal Identifier (UID). The UID of a function is astringwith the formatauthor/id, whereauthoris the author of the function andidis the functionid.apiKey: an API key for the functionfuncUID.input: optional input content. You can only pass the input content as an argument if the Function being called only accepts one input — seewithInput()to learn more. Otherwise, you must callsetInput()to set the input content.
pifop.resume(funcUID, apiKey, execId)
Resume an Execution previously created with pifop.execute(). Only Executions that have already been started can be resumed. Use this constructor as a recovery mechanism in case of a program crash, client disconnection and other kinds of interruption.
Usage example:
pifop.execute("joe/example", "apikey_ABC123", input)
.onStarted((execution) => {
// Store the id of the execution so that
// you can resume it later, if necessary.
})
.onEvent(eventHandler);
// After crash or disconnection...
// Resume execution using its id
let execId = getExecutionId(...);
pifop.resume("joe/example", "apikey_ABC123", execId)
.onEvent(eventHandler);Instance Methods
setInput(inputId, content), withInput(content)
setInput() sets the content of the input inputId. The provided input is not immediatelly uploaded. Rather, it will be uploaded once the Execution has been initialized in the server.
withInput() is an alternative that you can use if, and only if, the Function being called only accepts a single input file. It behaves exactly like setInput(), except that you can ommit the inputId in this case.
inputId: the id of the input file to which thecontentbelongs.content: the content of the input file. It can be anything acceptable as afetch body, includingString,Blob,ArrayBuffer,TypedArrayandDataView.
onStarted(...), onProgress(...), onFinish(...), onError(...)
Family of event listener setters for common events that you may want to listen to. They all take two arguments: onXXXX(listener, [once]).
listener: a function that will be called with argumentslistener(execution, event).execution: theExecutionthat is related to the event.event: anEventobject containing all the details pertaining the event.
once: optional boolean. Iftrue, thelistenerwill be removed from the execution after being called once. Default:false.
Event type associated with each setter:
onStarted: thelistenerwill listen to the"execution_started"event.onProgress: thelistenerwill listen to"execution_info"events.onFinish: thelistenerwill listen to the"result_ready"event.onError: thelistenerwill listen to"error"events.
onEvent(listener, once)
Generic event listener setter. The listener will be called whenever an event of any kind happens. Use the type member of the event to distinguish between events.
Usage example:
pifop.execute("joe/example", "apikey_ABC123", input)
.onEvent((execution, event) => {
switch(event.type) {
case "event_type1": /* Do something */ break;
case "event_type2": /* Do something */ break;
// ...
}
});setMetadata(key, value)
User-defined arbitrary data. That's for your convenience only. It allows you to associate some data with an execution, which you can then access later, e.g., on event listeners.
key: thestringthat will be used as a key to accessing thevalue.value: any object whatsoever.
Usage example:
pifop.execute("joe/example", "apikey_ABC123", input)
.setMetadata("my_data", 48)
.onFinish((execution) => {
console.log(execution.metadata["my_data"]); // 48
});ignoreLog([boolean])
Call this function without arguments if you don't care for the execution log. The execution log is essentially what the execution prints out to the terminal. When the execution log is ignored, it is not periodically retrieved via the getInfo() function, meaning that no log will be available in the data member of the Event passed to the listener bound by onProgress(). The main benefit of this is an improvement on the network performance of your application, as less data will be transfered from PIFOP to your application.
boolean: optional boolean indicating if you want to ignore the execution log or not. Default:true.
Usage example:
pifop.execute("joe/example", "apikey_ABC123", input)
.ignoreLog()
.onFinish(/* Do something */);Events
The listener arguments in the onXXXX() family of functions are user-defined functions that will be called when certain events happen during the execution. Event listeners are passed two arguments: listener(object, event), where object is either an Execution or a Function, depending on who is listening to that event, and event is an Event object.
Event Properties:
type: type of the event. See below.operation: operation that was being perfomed when the event happened.data: the data related to the event. Each event type will have a differentdata. See below.objectType: astringrepresenting the type of the object related to theoperationtype. Can be"execution"or"function".execution:Executionobject related to that event.func:Functionobject related to that event.response: theResponsethat we've got from the server.
Event Types:
| Type | Description |
|---|---|
"function_initialized" | The func object has been initialized and is ready to be used. The data member contains the function data. listener setter: function.onInit() |
"execution_initialized" | The execution object has been initialized. The data member contains the execution data. listener setter: execution.onInit() |
"input_uploaded" | Input file has been uploaded to execution. The data member contains the input that has been uploaded. |
"execution_started" | The execution has been started. The data member contains the execution data. |
"execution_info" | Info about the execution has been retrieved. The data member contains the execution data. listener setter: execution.onProgress() |
"execution_ended" | The execution has ended. The data member contains the execution data. |
"result_ready" | The execution has ended and all of its output files have been retrieved. Output files can be found in execution.output, or in execution.result if only one output file has been generated. If the single output is a JSON, execution.result will be the parsed output so you can access its members directly. If the single output is not a JSON, execution.result will be an Output object. |
"output_retrieved" | An output file of execution has been retrieved. The data member contains the output that has been retrieved. |
"execution_stopped" | The execution has been stopped. The data member contains the execution data. |
"error" | Something bad has happened. listener setter: onError() |