An open API service indexing awesome lists of open source software.

https://github.com/checkr/idempotent-requests

A server to enable request idempotency.
https://github.com/checkr/idempotent-requests

Last synced: 5 months ago
JSON representation

A server to enable request idempotency.

Awesome Lists containing this project

README

          

![CI workflow](https://github.com/checkr/idempotent-requests/actions/workflows/ci.yml/badge.svg)
![Release workflow](https://github.com/checkr/idempotent-requests/actions/workflows/release.yml/badge.svg)

# Idempotent Requests

Idempotent Requests Server provides [API](./docs/openapi.yaml) to allocate and record a captured request. It follows
behaviors described
in [IETF draft for standardized `Idempotency-Key` header](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-idempotency-key-header-00)
.

## Contract

[API contract](./docs/openapi.yaml)

## MongoDB access pattern

[More details on MongoDB access pattern](./docs/mongo_upsert.md)

## Idempotent Requests Client

We have implemented a client in a form of a [Kong Gateway](https://konghq.com/kong/)
Plugin - [`idempotent-requests`](https://github.com/checkr/kong-plugin-idempotent-requests).

## Configuration

| Config | Required | Default | Explanation |
| --- | --- | --- | --- |
| `MONGODB_URI` | yes | `mongodb://root:password123@localhost:27017` | URI to connect to MongoDB |
| `OPENTRACING_ENABLED` | no | `true` | Enable `opentracing` |
| `OPENTRACING_TRACER_IMPLEMENTATION` | no | `datadog` | [Use Datadog tracer implementation](https://docs.datadoghq.com/tracing/setup_overview/setup/go/?tab=containers) |

## Example topology

This example topology relies on Kong Gateway to intercept client requests.
A [Kong Plugin](https://github.com/checkr/kong-plugin-idempotent-requests) acts as a client to Idempotent Requests
Server.

### Data flow

![data_flow](./docs/example_data_flow.png)

### Sequence

[Source](./docs/sequence.md)

[![](https://mermaid.ink/img/eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG4gICAgYXV0b251bWJlclxuICAgIHBhcnRpY2lwYW50IGNsaWVudCBhcyBDbGllbnRcbiAgICBwYXJ0aWNpcGFudCBrb25nIGFzIEtvbmcgUHJveHlcbiAgICBwYXJ0aWNpcGFudCBwbHVnaW5fYWNjZXNzIGFzIFBsdWdpbjphY2Nlc3NcbiAgICBwYXJ0aWNpcGFudCBwbHVnaW5fcmVzcG9uc2UgYXMgUGx1Z2luOnJlc3BvbnNlXG4gICAgcGFydGljaXBhbnQgaXJzIGFzIElkZW1wb3RlbnQgUmVxdWVzdFxuICAgIHBhcnRpY2lwYW50IG1vbmdvIGFzIE1vbmdvREJcbiAgICBwYXJ0aWNpcGFudCBhcGkgYXMgQVBJIFNlcnZlclxuICAgIFxuICAgIE5vdGUgb3ZlciBwbHVnaW5fYWNjZXNzLHBsdWdpbl9yZXNwb25zZTogS29uZyBQbHVnaW4gcnVudGltZVxuICAgIFxuICAgIGNsaWVudCAtPj4gK2tvbmc6IEhUVFAgUE9TVCAvKiwgXCJJZGVtcG90ZW5jeS1LZXk6ICQodmFsdWUpXCJcbiAgICBrb25nIC0-PiArcGx1Z2luX2FjY2VzczogVHJpZ2dlciA6YWNjZXNzKClcbiAgICBwbHVnaW5fYWNjZXNzIC0-PiAraXJzOiBIVFRQIFBVVCAvY2FwdHVyZXNcbiAgICBpcnMgLT4-ICttb25nbzogSW5zZXJ0LCBpZiBub3QgZXhpc3RzXG5cbiAgICBhbHQgQW5vdGhlciByZXF1ZXN0IGNhcHR1cmUgd2FzIHJlY29yZGVkXG4gICAgICAgIG1vbmdvIC0tPj4gaXJzOiBjYXB0dXJlLnN0YXR1czogY29tcGxldGVkXG4gICAgICAgIGlycyAtLT4-IHBsdWdpbl9hY2Nlc3M6IDIwMCBPa1xuICAgICAgICBwbHVnaW5fYWNjZXNzIC0tPj4ga29uZzogU2V0IGtvbmcucmVzcG9uc2UgYW5kIGV4aXRcbiAgICAgICAga29uZyAtLT4-IGNsaWVudDogUmVzcG9uc2VcbiAgICBlbmRcbiAgICBcbiAgICBhbHQgQW5vdGhlciByZXF1ZXN0IGNhcHR1cmUgaXMgaW4tZmxpZ2h0XG4gICAgICAgIG1vbmdvIC0tPj4gaXJzOiBjYXB0dXJlLnN0YXR1czogY2FwdHVyZV9pc19pbl9mbGlnaHRcbiAgICAgICAgaXJzIC0tPj4gcGx1Z2luX2FjY2VzczogNDA5IENvbmZsaWN0XG4gICAgICAgIHBsdWdpbl9hY2Nlc3MgLS0-PiBrb25nOiBTZXQga29uZy5yZXNwb25zZSBhbmQgZXhpdFxuICAgICAgICBrb25nIC0tPj4gY2xpZW50OiA0MDkgQ29uZmxpY3RcbiAgICBlbmRcbiAgICBcbiAgICBhbHQgUmVjb3JkaW5nIGEgY2FwdHVyZSBmb3IgdGhlIHZlcnkgMXN0IHRpbWVcbiAgICAgICAgbW9uZ28gLS0-PiAtaXJzOiBjYXB0dXJlLnN0YXR1czogYWxsb2NhdGVkXG4gICAgICAgIGlycyAtLT4-IC1wbHVnaW5fYWNjZXNzOiAyMDIgQWNjZXB0ZWRcbiAgICAgICAgcGx1Z2luX2FjY2VzcyAtLT4-IC1rb25nOiA6YWNjZXNzKCkgZmluaXNoZWRcbiAgICBcbiAgICAgICAga29uZyAtPj4gK2FwaTogUHJveHkgdGhlIHJlcXVlc3RcbiAgICAgICAgYXBpIC0tPj4gLWtvbmc6IFJlc3BvbnNlXG4gICAgXG4gICAgICAgIGtvbmcgLT4-ICtwbHVnaW5fcmVzcG9uc2U6IFRyaWdnZXIgOnJlc3BvbnNlKClcbiAgICAgICAgcGx1Z2luX3Jlc3BvbnNlIC0-PiAraXJzOiBIVFRQIFBPU1QgL2NhcHR1cmVzXG4gICAgICAgIGlycyAtPj4gK21vbmdvOiBVcGRhdGUgdGhlIGNhcHR1cmUgZG9jdW1lbnQsIGlmZiBjYXB0dXJlLnN0YXR1cyBpcyBcImFsbG9jYXRlZFwiXG4gICAgICAgIG1vbmdvIC0tPj4gLWlyczogT2tcbiAgICAgICAgaXJzIC0tPj4gLXBsdWdpbl9yZXNwb25zZTogMjAwIE9rXG4gICAgICAgIHBsdWdpbl9yZXNwb25zZSAtLT4-IC1rb25nOiA6cmVzcG9uc2UoKSBjb21wbGV0ZWRcbiAgICBcbiAgICAgICAga29uZyAtLT4-IC1jbGllbnQ6IFJlc3BvbnNlXG4gICAgZW5kICIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0In0sInVwZGF0ZUVkaXRvciI6ZmFsc2UsImF1dG9TeW5jIjp0cnVlLCJ1cGRhdGVEaWFncmFtIjpmYWxzZX0)](https://mermaid.live/edit/#eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG4gICAgYXV0b251bWJlclxuICAgIHBhcnRpY2lwYW50IGNsaWVudCBhcyBDbGllbnRcbiAgICBwYXJ0aWNpcGFudCBrb25nIGFzIEtvbmcgUHJveHlcbiAgICBwYXJ0aWNpcGFudCBwbHVnaW5fYWNjZXNzIGFzIFBsdWdpbjphY2Nlc3NcbiAgICBwYXJ0aWNpcGFudCBwbHVnaW5fcmVzcG9uc2UgYXMgUGx1Z2luOnJlc3BvbnNlXG4gICAgcGFydGljaXBhbnQgaXJzIGFzIElkZW1wb3RlbnQgUmVxdWVzdFxuICAgIHBhcnRpY2lwYW50IG1vbmdvIGFzIE1vbmdvREJcbiAgICBwYXJ0aWNpcGFudCBhcGkgYXMgQVBJIFNlcnZlclxuICAgIFxuICAgIE5vdGUgb3ZlciBwbHVnaW5fYWNjZXNzLHBsdWdpbl9yZXNwb25zZTogS29uZyBQbHVnaW4gcnVudGltZVxuICAgIFxuICAgIGNsaWVudCAtPj4gK2tvbmc6IEhUVFAgUE9TVCAvKiwgXCJJZGVtcG90ZW5jeS1LZXk6ICQodmFsdWUpXCJcbiAgICBrb25nIC0-PiArcGx1Z2luX2FjY2VzczogVHJpZ2dlciA6YWNjZXNzKClcbiAgICBwbHVnaW5fYWNjZXNzIC0-PiAraXJzOiBIVFRQIFBVVCAvY2FwdHVyZXNcbiAgICBpcnMgLT4-ICttb25nbzogSW5zZXJ0LCBpZiBub3QgZXhpc3RzXG5cbiAgICBhbHQgQW5vdGhlciByZXF1ZXN0IGNhcHR1cmUgd2FzIHJlY29yZGVkXG4gICAgICAgIG1vbmdvIC0tPj4gaXJzOiBjYXB0dXJlLnN0YXR1czogY29tcGxldGVkXG4gICAgICAgIGlycyAtLT4-IHBsdWdpbl9hY2Nlc3M6IDIwMCBPa1xuICAgICAgICBwbHVnaW5fYWNjZXNzIC0tPj4ga29uZzogU2V0IGtvbmcucmVzcG9uc2UgYW5kIGV4aXRcbiAgICAgICAga29uZyAtLT4-IGNsaWVudDogUmVzcG9uc2VcbiAgICBlbmRcbiAgICBcbiAgICBhbHQgQW5vdGhlciByZXF1ZXN0IGNhcHR1cmUgaXMgaW4tZmxpZ2h0XG4gICAgICAgIG1vbmdvIC0tPj4gaXJzOiBjYXB0dXJlLnN0YXR1czogY2FwdHVyZV9pc19pbl9mbGlnaHRcbiAgICAgICAgaXJzIC0tPj4gcGx1Z2luX2FjY2VzczogNDA5IENvbmZsaWN0XG4gICAgICAgIHBsdWdpbl9hY2Nlc3MgLS0-PiBrb25nOiBTZXQga29uZy5yZXNwb25zZSBhbmQgZXhpdFxuICAgICAgICBrb25nIC0tPj4gY2xpZW50OiA0MDkgQ29uZmxpY3RcbiAgICBlbmRcbiAgICBcbiAgICBhbHQgUmVjb3JkaW5nIGEgY2FwdHVyZSBmb3IgdGhlIHZlcnkgMXN0IHRpbWVcbiAgICAgICAgbW9uZ28gLS0-PiAtaXJzOiBjYXB0dXJlLnN0YXR1czogYWxsb2NhdGVkXG4gICAgICAgIGlycyAtLT4-IC1wbHVnaW5fYWNjZXNzOiAyMDIgQWNjZXB0ZWRcbiAgICAgICAgcGx1Z2luX2FjY2VzcyAtLT4-IC1rb25nOiA6YWNjZXNzKCkgZmluaXNoZWRcbiAgICBcbiAgICAgICAga29uZyAtPj4gK2FwaTogUHJveHkgdGhlIHJlcXVlc3RcbiAgICAgICAgYXBpIC0tPj4gLWtvbmc6IFJlc3BvbnNlXG4gICAgXG4gICAgICAgIGtvbmcgLT4-ICtwbHVnaW5fcmVzcG9uc2U6IFRyaWdnZXIgOnJlc3BvbnNlKClcbiAgICAgICAgcGx1Z2luX3Jlc3BvbnNlIC0-PiAraXJzOiBIVFRQIFBPU1QgL2NhcHR1cmVzXG4gICAgICAgIGlycyAtPj4gK21vbmdvOiBVcGRhdGUgdGhlIGNhcHR1cmUgZG9jdW1lbnQsIGlmZiBjYXB0dXJlLnN0YXR1cyBpcyBcImFsbG9jYXRlZFwiXG4gICAgICAgIG1vbmdvIC0tPj4gLWlyczogT2tcbiAgICAgICAgaXJzIC0tPj4gLXBsdWdpbl9yZXNwb25zZTogMjAwIE9rXG4gICAgICAgIHBsdWdpbl9yZXNwb25zZSAtLT4-IC1rb25nOiA6cmVzcG9uc2UoKSBjb21wbGV0ZWRcbiAgICBcbiAgICAgICAga29uZyAtLT4-IC1jbGllbnQ6IFJlc3BvbnNlXG4gICAgZW5kICIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6ZmFsc2V9)

## Running Integration Tests Locally

```shell
docker-compose -f docker-compose.yml \
-f docker-compose.server.yml \
-f docker-compose.integration.yml \
up --exit-code-from integration-test
```