Composer
IBM Cloud® Functions is deprecated. Existing Functions entities such as actions, triggers, or sequences will continue to run, but as of 28 December 2023, you can’t create new Functions entities. Existing Functions entities are supported until October 2024. Any Functions entities that still exist on that date will be deleted. For more information, see Deprecation overview.
With Composer, IBM Cloud® Functions supports conductor actions, which extends sequences with more combinators (JS, Python) By using Composer, you can create more complex flows that include conditional branching, error handling, retries, and loops.
Installing the Composer library for JavaScript or Python
You can use Composer with actions that are written in any language, but you express the composition in either JavaScript or Python. After the installation, you can use the Composer compose/pycompose
and deploy/pydeploy
commands to configure and run a composition.
For JavaScript
-
Install the Composer library Node.js package by using the Node Package Manager.
npm install -g @ibm-functions/composer
-
Confirm that you installed the library by running help for the Composer commands.
compose -h deploy -h
The following example shows possible output for the Composer commands.
Usage: compose composition.js [flags] Usage: deploy composition composition.json [flags]
For Python
Install the Composer for Python library by using pip3
.
-
Install the Composer library.
pip3 install git+https://github.com/ibm-functions/composer-python.git
-
Confirm that you installed the library by running help for the Composer commands.
pycompose -h pydeploy -h
Example output
usage: pycompose composition.py command [flags] usage: pydeploy composition composition.json [flags]
Configuring and running compositions in Cloud Functions
You can use the JavaScript or Python Composer libraries to create your compositions in Cloud Functions. Use compose
or pycompose
to compile your composition source code, then use deploy
or pydeploy
to deploy the composition to Cloud Functions. After you configure the composition, you can run it in Cloud Functions.
Before you begin
- Log in to IBM Cloud and install the IBM Cloud and the Cloud Functions CLI.
- Set up and target a namespace.
To run a composition, follow these steps
-
Create Composer source code with the Node.js or Python libraries. You can find some example code in the samples folder of each repository (JS, Python).
-
Compile the Composer source code into a JSON file.
-
JavaScript
compose demo.js > demo.json
-
Python
pycompose demo.py > demo.json
-
-
Deploy the code to Cloud Functions. Include the
-w
flag to overwrite any existing deployment that is nameddemo
.-
JavaScript
deploy demo demo.json -w
-
Python
pydeploy demo demo.json -w
-
-
Execute the composition in the same way you invoke other actions in Cloud Functions.
ibmcloud fn action invoke demo
Cloud Functions executes the code that you deployed as a special action. For more information, see the documentation on conductor actions.
Extending sequences with Composer
With Apache OpenWhisk, you can chain functions together in a sequence
, where the output of one action becomes the input to another action.
Sequences without Composer
You can chain together two functions that are named action1
and action2
in Cloud Functions:
ibmcloud fn action create --sequence mysequence action1 action2
The result of this command is a function that is called mysequence
, which is a composite of action1
and action2
. You can use mysequence
in the same manner as any function in OpenWhisk.
Sequences with Composer
In Composer, you can specify richer sequences by using source code rather than the command line.
For JavaScript
const composer = require('@ibm-functions/composer')
module.exports = composer.seq('action1', 'action2')
For Python
import composer
def main():
return composer.sequence('action1', 'action2')
You aren't limited to chaining together functions in Composer. Composer includes a family of JavaScript or Python based combinators that enhance the expressiveness of sequences. You can see common examples in the following sections.
Error handling for a sequence
You can add error handling to a sequence by using try-catch-finally
blocks. In this example, you surround the sequence with a try. The handleError
code executes if either action returns an error.
For JavaScript
const composer = require('@ibm-functions/composer')
module.exports = composer.try(
composer.seq('action1', 'action2'),
'handleError')
For Python
import composer
def main():
return composer.do(composer.sequence('action1', 'action2'),
'handleError')
Conditional branching for a sequence
You can create a branched sequence by using if-then-else
. This example demonstrates an if-then-else
. action1
returns a boolean. If true
, then action2
is executed, otherwise action3
is executed. Note action3
is optional and can be omitted for if-then
.
For JavaScript
const composer = require('@ibm-functions/composer')
module.exports = composer.if('action1', 'action2', 'action3')
For Python
import composer
def main():
return composer.when('action1', 'action2', 'action3')
Loops in Composer
You can create looping constructs in Composer. In this example, action2
executes as long as action1
returns true
. Composer limits the total number of steps you can execute in a composed sequence. The
current limit is 20.
For JavaScript
const composer = require('@ibm-functions/composer')
module.exports = composer.while('action1', 'action2')
For Python
import composer
def main():
return composer.loop('action1', 'action2')
Inline definition of Actions within a composition
You can define actions within the composition code itself. In this example, you create the action definition inline with the composition that is named hello
by using the composer.action()
.
For JavaScript
const composer = require('@ibm-functions/composer')
module.exports = composer.seq('action1',
composer.action('hello', {
action: function () { return { message: 'Hello!' } }
}))
For Python
import composer
def hello(args):
return { 'message': 'hello' }
def main():
return composer.sequence(
'action1',
composer.action('hello', hello)
)
Using other combinator definitions
See the documentation for Composer on Apache OpenWhisk (JavaScript or Python) for the full list of combinators definitions.