|
| 1 | +<!-- |
| 2 | +title: 'Ruby AWS Ruby Step Functions' |
| 3 | +description: 'Ruby example that make usage of AWS Step Functions with AWS Lambda, DynamoDB and Step Functions flows.' |
| 4 | +layout: Doc |
| 5 | +framework: v2 |
| 6 | +platform: AWS |
| 7 | +language: Ruby |
| 8 | +authorLink: 'https://github.com/pigius' |
| 9 | +authorName: 'Daniel Aniszkiewicz' |
| 10 | +authorAvatar: 'https://avatars1.githubusercontent.com/u/8863200?s=200&v=4' |
| 11 | +--> |
| 12 | +# Serverless AWS Ruby Step Functions |
| 13 | + |
| 14 | +This is an example of using `AWS Step Functions` `Standard` Workflow Type. It uses `AWS Lambda`, `DynamoDB` (create and update, 2 separate databases), and `flows` from `Step Functions`. |
| 15 | + |
| 16 | + |
| 17 | +## Diagram |
| 18 | + |
| 19 | + |
| 20 | + |
| 21 | +The workflow used as an example is organising a holiday for example out of town. |
| 22 | + |
| 23 | +Here we have two dynamodb tables: |
| 24 | + |
| 25 | +- `tickets` table for tickets |
| 26 | +- `parking-lot-spaces` table for parking spaces |
| 27 | + |
| 28 | + |
| 29 | +The workflow first creates a record for us to buy a ticket, and to book a parking space (as Parallel state), and then waits for the day on which the tour is to take place (Wait State timestamp as check_in_date), and it checks the weather. |
| 30 | + |
| 31 | +Depending on the weather, the workflow is successful if the weather is good. Otherwise (bad weather), both the ticket and the parking space are cancelled. |
| 32 | + |
| 33 | +This can be considered a Saga pattern. |
| 34 | + |
| 35 | + |
| 36 | + |
| 37 | +## Setup |
| 38 | + |
| 39 | +`npm install` to install all needed packages. |
| 40 | + |
| 41 | +## Deployment |
| 42 | + |
| 43 | +In order to deploy the service run: |
| 44 | + |
| 45 | +```bash |
| 46 | +sls deploy |
| 47 | +``` |
| 48 | + |
| 49 | +for deploying with a specific `profile` (located in `~/.aws/credentials`) you can simply use the command: |
| 50 | + |
| 51 | +```bash |
| 52 | +AWS_PROFILE=YOUR_PROFILE_NAME sls deploy |
| 53 | +``` |
| 54 | + |
| 55 | +for deploying to the specific stage, let's say `staging` do: |
| 56 | + |
| 57 | +```bash |
| 58 | +sls deploy --stage staging |
| 59 | +``` |
| 60 | + |
| 61 | +The expected result should be similar to: |
| 62 | + |
| 63 | +```bash |
| 64 | +Serverless: Packaging service... |
| 65 | +Serverless: Excluding development dependencies... |
| 66 | +Serverless: Clearing previous build ruby layer build |
| 67 | +[ '2.2' ] |
| 68 | +Serverless: Installing gem using local bundler |
| 69 | +Serverless: Zipping the gemfiles to ../examples/aws-ruby-step-functions/.serverless/ruby_layer/gemLayer.zip |
| 70 | +Serverless: Configuring Layer and GEM_PATH to the functions |
| 71 | +✓ State machine "myStateMachine" definition is valid |
| 72 | +Serverless: Uploading CloudFormation file to S3... |
| 73 | +Serverless: Uploading artifacts... |
| 74 | +Serverless: Uploading service serverless-ruby-step-functions.zip file to S3 (1.03 MB)... |
| 75 | +Serverless: Uploading service gemLayer.zip file to S3 (640.83 KB)... |
| 76 | +Serverless: Validating template... |
| 77 | +Serverless: Updating Stack... |
| 78 | +Serverless: Checking Stack update progress... |
| 79 | +................................................................................. |
| 80 | +Serverless: Stack update finished... |
| 81 | +Service Information |
| 82 | +service: serverless-ruby-step-functions |
| 83 | +stage: dev |
| 84 | +region: us-east-1 |
| 85 | +stack: aws-ruby-step-functions-dev |
| 86 | +resources: 23 |
| 87 | +api keys: |
| 88 | + None |
| 89 | +endpoints: |
| 90 | + None |
| 91 | +functions: |
| 92 | + buy-ticket: aws-ruby-step-functions-dev-buy-ticket |
| 93 | + reserve-parking-lot-space: aws-ruby-step-functions-dev-reserve-parking-lot-space |
| 94 | + return-ticket: aws-ruby-step-functions-dev-return-ticket |
| 95 | + release-parking-space: aws-ruby-step-functions-dev-release-parking-space |
| 96 | + check-weather: aws-ruby-step-functions-dev-check-weather |
| 97 | +layers: |
| 98 | + gem: arn:aws:lambda:YOUR_REGION:XXXXXXXXXXX:layer:aws-ruby-step-functions-dev-ruby-bundle:59 |
| 99 | +``` |
| 100 | + |
| 101 | +## Usage |
| 102 | + |
| 103 | + |
| 104 | +After the deployment, go to the AWS Dashboard, and enter Step Functions page. You will see a newly created state machine. |
| 105 | + |
| 106 | +Open the `organize-nice-weekend-state-machine` state machine and click on `Start Execution`. You need to provide the input in the JSON schema. |
| 107 | + |
| 108 | +Example: |
| 109 | + |
| 110 | +``` JSON |
| 111 | +{ |
| 112 | + "first_name": "Daniel", |
| 113 | + "last_name": "Ani", |
| 114 | + "check_in_date": "2021-07-11T19:35:07+00:00", |
| 115 | + "check_out_date": "2021-07-11T19:35:07+00:00", |
| 116 | + "driver_plate": "RUBY" |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | + |
| 121 | + |
| 122 | +The `check_in_date` is the most important one. Without it, the state machine will be failed (it's needed for the purpose of the Wait state). |
| 123 | + |
| 124 | + |
| 125 | + |
| 126 | + |
| 127 | +Later on, simply start the excecution. |
| 128 | + |
| 129 | +You can watch live as the change between states takes place. It is also possible to view every parameter going in and out of each state. |
| 130 | + |
| 131 | +The` weather` attribute is returned randomly (either `good` or `bad`), so sometimes you need several executions of the state machine to get a failed execution. |
| 132 | + |
| 133 | + |
| 134 | + |
| 135 | +To check created records check your DynamoDB tables (both for tickets, and parking lot spaces). In both cases, you will see that for failure executions, the `current_status` for records, will be changed to `canceled`. |
| 136 | + |
| 137 | +Happy Path (good weather) |
| 138 | + |
| 139 | + |
| 140 | + |
| 141 | +Unhappy path (bad weather) |
| 142 | + |
| 143 | + |
| 144 | + |
| 145 | + |
| 146 | +## Log retention |
| 147 | + |
| 148 | +The log retention is setup for 30 days. To change it simply change the value of this attribute in `serverless.yml` file: |
| 149 | + |
| 150 | + |
| 151 | +``` bash |
| 152 | +logRetentionInDays: 30 |
| 153 | +``` |
| 154 | + |
| 155 | +## Advanced configuration |
| 156 | +More options (like alerting in case of failed excecutions), could be found in the plugin [repository](https://github.com/serverless-operations/serverless-step-functions). |
| 157 | + |
| 158 | +## Structure |
| 159 | + |
| 160 | +| Path | Explanation | |
| 161 | +|----------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |
| 162 | +| `./src` | All code for the project. | |
| 163 | +| `./src/handlers/buy_ticket` | Lambda function for creating a ticket. | |
| 164 | +| `./src/handlers/return_ticket` | Lambda function for returning the ticket. | |
| 165 | +| `./src/handlers/reserve_parking_lot_space` | Lambda function for reserving the parking lot space. | |
| 166 | +| `./src/handlers/release_parking_space` | Lambda function for releasing the parking spaceticket. | |
| 167 | +| `./src/handlers/check_weather` | Lambda function for checking weather. | |
| 168 | +| `./src/common/` | Space for common, reusable pieces of code. | |
| 169 | +| `./src/common/adapters/dynamo_db_adapter.rb` | Adapter for communication with DynamoDB with the usage of AWS SDK for Ruby. Used for creating new records and updating existing ones. | |
| 170 | +| `./src/common/services/ticket_service.rb` | The service object pattern is widely used within ruby/rails developers. In our case used for all things related to tickets, so creating and updating records within DynamoDB. | |
| 171 | +| `./src/common/adapters/reserve_parking_service.rb` | In our case used for all things related to parking reservations, so creating and updating records within DynamoDB. | |
| 172 | + |
| 173 | +## Serverless plugins |
| 174 | + |
| 175 | +For this example, there are two serverless plugins used: |
| 176 | + |
| 177 | +| Plugin | Explanation | |
| 178 | +|-----------------------|------------------------------------------------------------------------------------------------| |
| 179 | +| [serverless-ruby-layer](https://www.npmjs.com/package/serverless-ruby-layer) | For bundling ruby gems from `Gemfile` and deploys them to the lambda layer. | |
| 180 | +| [serverless-step-functions](https://www.npmjs.com/package/serverless-step-functions) | Serverless Framework plugin for AWS Step Functions. | |
| 181 | + |
| 182 | +## Ruby gems |
| 183 | + |
| 184 | +| Gem | Explanation | |
| 185 | +|--------------------|--------------------------------------------------------------------------------------------------------------------------------| |
| 186 | +| `aws-sdk-dynamodb` | It's a part of the AWS SDK for Ruby. Used for DynamoDB, in the case of this example - the creation of the new record. | |
| 187 | + |
| 188 | +## Remove service |
| 189 | + |
| 190 | +To remove the service do: |
| 191 | + |
| 192 | +```bash |
| 193 | +sls remove |
| 194 | +``` |
| 195 | +And the stack will be removed from the AWS. |
0 commit comments