tbobm / machinery

Workflow processing inspired by AWS State Machines. Define workflows, register services and start processing events.
Apache License 2.0
4 stars 0 forks source link
api event-driven flask python state-machine

machinery

CI

State-aware workflow orchestrator.

This project aims to bring stateful workflows, by defining a list of actions representing multiple microservices.

Define a suite of actions to process events, abstract intelligence for your microservices.

Once defined, use your workflows to process your Events.

Example

We have 3 microservices:

Suppose we want to process some text by making it uppercase and reversing it.

We will define the following definitions:

Then, we can define a Workflow in examples/definitions/workflow-process-text.json.

After having created our Workflow, we can send our first Event !

We will send the content of examples/definitions/event-text.json

Goals

Development

The recommended approach is to use virtualenv to install the API's dependencies.

$ pip install virtualenv
$ python -m virtualenv venv
$ source venv/bin/activate
$ pip install -r requirements_dev.txt
$ pip install -e .

In order to ease iterations, some helpers scripts are available.

start the database

Starts a background MongoDB container in host networking mode.

$ ./run-background-service.sh

run the api in development mode

Start the Flask Application in development + debug mode.

$ ./run_app 
 * Serving Flask app 'machinery.api:create_app' (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on all addresses.
   WARNING: This is a development server. Do not use it in a production deployment.

Testing

Every testing-related dependency is listed in the requirements_dev.txt file.

$ pip install -r requirements_dev.txt

Unit tests

This project implements unittests using pytest.

In a configured environment, run the following command:

$ pytest

Linting

This project is linted using pylint

In a configured environment, run the following command:

$ pylint machinery

Functional tests

This API is tested using Postman/Newman. (newman: Getting Started)

Assets are available in the ./postman directory and expect the API to be accessible at http://localhost:5000. This can be achieved using the ./run_app script.

Example:

$ npm install newman
$ ./node_modules/newman/bin/newman.js run ./postman/Machinery.postman_collection.json -e postman/Machinery\ -\ Local.postman_env.json 
newman

Machinery

→ Create a Service
  POST http://localhost:5000/s [201 CREATED, 197B, 38ms]
  ✓  Status code is 201
  ✓  Response contains a service_id

┌─────────────────────────┬──────────────────┬──────────────────┐
│                         │         executed │           failed │
├─────────────────────────┼──────────────────┼──────────────────┤
│              iterations │                1 │                0 │
├─────────────────────────┼──────────────────┼──────────────────┤
│                requests │                1 │                0 │
├─────────────────────────┼──────────────────┼──────────────────┤
│            test-scripts │                1 │                0 │
├─────────────────────────┼──────────────────┼──────────────────┤
│      prerequest-scripts │                0 │                0 │
├─────────────────────────┼──────────────────┼──────────────────┤
│              assertions │                2 │                0 │
├─────────────────────────┴──────────────────┴──────────────────┤
│ total run duration: 70ms                                      │
├───────────────────────────────────────────────────────────────┤
│ total data received: 47B (approx)                             │
├───────────────────────────────────────────────────────────────┤
│ average response time: 38ms [min: 38ms, max: 38ms, s.d.: 0µs] │
└───────────────────────────────────────────────────────────────┘

A Note on functional tests

As this Python project is to be considered to be a POC to define the required feature set for the "production-grade" version of Machinery, this testing part is the most important than any other tests.

The next version probably will not be written in Python and this contract will allow to quickly develop a stable version.

Being able to define a usable API is the current goal for Machinery.

Components

API (WIP)

Could be divided into Consumer API and Management API.

Data structures

Service

{
    "name": "upper",
    "address": "http://upper.local:5000/",
    "inputs": [
         {
            "name": "message",
            "type": "string",
            "description": "The text to transform"
        }
    ],
    "outputs": [
         {
            "name": "message",
            "type": "string",
            "description": "The transformed text, in uppercase"
        }
    ]
}

input:

output: TBD (service-id, ack date)

Event

POST /e/<workflow-id>

{
    "data": {
        "message": "The Sun will rise in the morning !"
    }
}

POSTing an Event will return an event-id, an ack date and a status. input:

Workflow

{
    "name": "process-text",
    "services": ["upper", "reverse", "space-counter"],
    "inputs": [
         {
            "name": "message",
            "type": "string",
            "description": "The text to process"
        }
    ],
    "outputs": [
         {
            "name": "message",
            "type": "string",
            "description": "The processed text"
        },
         {
            "name": "space_count",
            "type": "int",
            "description": "The number of spaces"
        }
    ],
    "operations": [ ]
}

input:

output: TBD (workflow-id, ack date)