<!--
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
-->

# Compositions

Composer makes it possible to assemble actions into rich workflows called
_compositions_. An example composition is described in
[../README.md](../README.md).

## Control flow

Compositions can express the control flow of typical a sequential imperative
programming language: sequences, conditionals, loops, structured error handling.
This control flow is specified using _combinator_ methods such as:
- `composer.sequence(firstAction, secondAction)`
- `composer.if(conditionAction, consequentAction, alternateAction)`
- `composer.try(bodyAction, handlerAction)`

Combinators are described in [COMBINATORS.md](COMBINATORS.md).

## Composition objects

Combinators return composition objects, i.e., instances of the `Composition`
class.

## Parameter objects and error objects

A composition, like any action, accepts a JSON dictionary (the _input parameter
object_) and produces a JSON dictionary (the _output parameter object_). An
output parameter object with an `error` field is an _error object_. A
composition _fails_ if it produces an error object.

By convention, an error object returned by a composition is stripped from all
fields except from the `error` field. This behavior is consistent with the
OpenWhisk action semantics, e.g., the action with code `function main() { return
{ error: 'KO', message: 'OK' } }` outputs `{ error: 'KO' }`.

Error objects play a specific role as they interrupt the normal flow of
execution, akin to exceptions in traditional programming languages. For
instance, if a component of a sequence returns an error object, the remainder of
the sequence is not executed. Moreover, if the sequence is enclosed in an error
handling composition like a `composer.try(sequence, handler)` combinator, the
execution continues with the error handler.

### Reserved parameter name

The field name `$composer` is reserved for composer internal use. Compositions
and composed actions should not expect or return parameter objects with a
top-level field named `$composer`.

## Data flow

The invocation of a composition triggers a series of computations (possibly
empty, e.g., for the empty sequence) obtained by chaining the components of the
composition along the path of execution. The input parameter object for the
composition is the input parameter object of the first component in the chain.
The output parameter object of a component in the chain is typically the input
parameter object for the next component if any or the output parameter object
for the composition if this is the final component in the chain.

For example, the composition `composer.sequence('triple', 'increment')` invokes
the `increment` action on the output of the `triple` action.

Some combinators however are designed to alter the default flow of data. For
instance, the `composer.merge('myAction')` composition merges the input and
output parameter objects of `myAction`.

## Components

Components of a compositions can be actions, Python functions, or
compositions.

Python functions can be viewed as simple, anonymous actions that do not need
to be deployed and managed separately from the composition they belong to.
Functions are typically used to alter a parameter object between two actions
that expect different schemas, as in:
```javascript
composer.sequence('getUserNameAndPassword', params => ({ key = btoa(params.user + ':' + params.password) }), 'authenticate')
```
Combinators can be nested, e.g.,
```javascript
composer.if('isEven', 'half', composer.sequence('triple', 'increment'))
```
Compositions can reference other compositions by name. For instance, assuming we
deploy the sequential composition of the `triple` and `increment` actions as the
composition `tripleAndIncrement`, the following code behaves identically to the
previous example:
```javascript
composer.if('isEven', 'half', 'tripleAndIncrement')
```
The behavior of this last composition would be altered if we redefine the
`tripleAndIncrement` composition to do something else, whereas the first example
would not be affected.

## Embedded action definitions

A composition can embed the definitions of none, some, or all the composed
actions as illustrated in [demo.js](../samples/demo.js):
```javascript
composer.if(
    composer.action('authenticate', { action: function ({ password }) { return { value: password === 'abc123' } } }),
    composer.action('success', { action: function () { return { message: 'success' } } }),
    composer.action('failure', { action: function () { return { message: 'failure' } } }))
)
```
Deploying such a composition deploys the embedded actions.

## Conductor actions

Compositions are implemented by means of OpenWhisk [conductor
actions](https://github.com/apache/openwhisk/blob/master/docs/conductors.md).
Compositions have all the attributes and capabilities of an action, e.g.,
default parameters, limits, blocking invocation, web export. Execution
[traces](https://github.com/apache/openwhisk/blob/master/docs/conductors.md#activations)
and
[limits](https://github.com/apache/openwhisk/blob/master/docs/conductors.md#limits)
of compositions follow from conductor actions.
