# cookiecutter-python-swf
Cookiecutter allows us to template out our boilerplate so you can easily create a new SWF flows project.

## Setup and Usage
You have two options for using this repo.

### Option 1 - Create boilerplate directly from Github

1) Create a Python env and activate it
```
$ pyvenv ./env
$ . env/bin/activate
```
2) Install cookiecutter
```
$ pip install cookiecutter==1.5.1
```

3) Create a new microservice boilerplate
```
$ cookiecutter git@github.com:theorchard/cookiecutter-python-swf
```

4) Follow the three prompts to enter your repo_name, app_name and your flow_name.
* **repo_name**: Repository name of your project. `swf` prefix will be added automatically for you repo name.
For example, `accounting-aggregation` will become `swf-accounting-aggregation`.
* **app_name**: Name of project directory which will also be used for imports.
* **flow_name**: Name of initial flow in the repo, you can add other flows later manually. For example `revenue_aggregation`.

If you'd like to use the template without any prompts:
```
$ cookiecutter --no-input git@github.com:theorchard/cookiecutter-python-swf repo_name=accounting-aggregation app_name=accounting_aggregation flow_name=revenue_aggregation
```

5) You can now deactivate your cookiecutter env
```
$ deactivate
```

6) Go to your new project. So, if you set "accounting-aggregation" for repo_name in step 4, you can:
```
$ cd swf-accounting-aggregation
```

7) Push up your new project to an empty Github repo and start coding!


### Option 2 - Fork cookiecutter-flask-eb
You will use this option when you want to contribute to the boilerplate.

```
$ pyvenv ./env
$ . env/bin/activate
$ pip install -r requirements.txt
```

To build a new project, run the following and follow the prompts.
```
$ cookiecutter .
```

All configuration values are stored in cookiecutter.json in this project.
You will be asked to fill out two prompts:
* **repo_name**: Repository name of your project. `swf` prefix will be added automatically for you repo name.
For example, `accounting-aggregation` will become `swf-accounting-aggregation`.
* **app_name**: Name of project directory which will also be used for imports.
* **flow_name**: Name of initial flow in the repo, you can add other flows later manually. For example `revenue_aggregation`.

## Created SWF project

After you execute `cookiecutter` command you will have fully working project. But first setup your environment.

### Setup python dependencies

1) Create a Python env and activate it
```
$ pyvenv ./swf_project_env
$ . swf_project_env/bin/activate
```
2) Install requirements
```
$ pip install -r requirements.txt
$ pip install -r requirements-test.txt
```
3) Setup the project
```
$ python setup.py develop
```
This step will also allow you to use `garcon` command.

### Setup environment variables

#### .env.shadow

`.env.shadow` is a template environment variable script that exports keys and values necessary for successful connectivity, paths, etc. You will need to copy this file to .env and populate the necessary keys.

```
$ cp .env.shadow .env
```
##### Environment variables description:

`Environment` is used to define default SWF domain name.
`AWS_ACCESS_KEY_ID` is your AWS access key id.
`AWS_SECRET_ACCESS_KEY` is your AWS secret access key.
`DEV_SWF_DOMAIN` is used to define dev SWF domain name if `Environment` is `dev`.

##### Export environment variables

After you provided required values for each environment variable in `.env` file, you need to export it by `source` command.
```
$ source .env
```

### Run  project

Now you should be able to run the flow.
First you have to run decider process and at least one worker process.

```
$ python decider {flow_name}
```

```
$ python worker {flow_name}
```

Once the processes were started you can run flow execution in SWF.

```
$ python exec {flow_name}
```

As an alternative you can also use the [garcon-activity-local](https://github.com/theorchard/garcon-contrib/tree/master/contrib-cli) CLI tool.

## Gotchas

The SWF API has a limit of 32,768 characters on the data size of a task's result, meaning that you can't pass a large payload between tasks. (See: [https://docs.aws.amazon.com/amazonswf/latest/developerguide/swf-dg-limits.html#swf-dg-limits-tasks](https://docs.aws.amazon.com/amazonswf/latest/developerguide/swf-dg-limits.html#swf-dg-limits-tasks))
