IBM Cloud Docs
Composer

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

  1. Install the Composer library Node.js package by using the Node Package Manager.

    npm install -g @ibm-functions/composer
    
  2. 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.

  1. Install the Composer library.

    pip3 install git+https://github.com/ibm-functions/composer-python.git
    
  2. 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

  1. Log in to IBM Cloud and install the IBM Cloud and the Cloud Functions CLI.
  2. Set up and target a namespace.

To run a composition, follow these steps

  1. 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).

  2. Compile the Composer source code into a JSON file.

    • JavaScript

      compose demo.js > demo.json
      
    • Python

      pycompose demo.py > demo.json
      
  3. Deploy the code to Cloud Functions. Include the -w flag to overwrite any existing deployment that is named demo.

    • JavaScript

      deploy demo demo.json -w
      
    • Python

      pydeploy demo demo.json -w
      
  4. 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')

Sequence with two actions.
Figure 1. Sequence with two actions

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')

Sequence with error handling.
Figure 2. Sequence with error handling

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')

Sequence with conditional branching.
Figure 3. Sequence with conditional branching

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')

Sequence with while loop.
Figure 4. Sequence with while loop

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

Sequence with inline action definition.
Figure 5. Sequence with inline action definition

Using other combinator definitions

See the documentation for Composer on Apache OpenWhisk (JavaScript or Python) for the full list of combinators definitions.