update readme

This commit is contained in:
Dmytro Zakharov 2018-01-22 18:54:39 +01:00
parent b82e271caa
commit 2d5542f256
2 changed files with 109 additions and 12 deletions

116
README.md
View File

@ -1,8 +1,6 @@
# Idempotent::Request
# Idempotent Request
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/idempotent/request`. To experiment with that code, run `bin/console` for an interactive prompt.
TODO: Delete this and the text above, and describe your gem
Rack middleware ensuring at most once requests for mutating endpoints.
## Installation
@ -20,15 +18,115 @@ Or install it yourself as:
$ gem install idempotent-request
## Usage
## How it works
TODO: Write usage instructions here
1. Front-end generates a unique `key` then a user goes to a specific route (for example, transfer page).
2. When user clicks "Submit" button, the `key` is sent in the header `idempotency-key` and back-end stores server response into redis.
3. All the consecutive requests with the `key` won't be executer by the server and the result of previous response (2) will be fetched from redis.
4. Once the user leaves or refreshes the page, front-end should re-generate the key.
## Development
## Configuration
```ruby
# application.rb
config.middleware.use IdempotentRequest::Middleware,
storage: IdempotentRequest::RedisStorage.new(::Redis.current, expire_time: 1.day),
policy: YOUR_CLASS
```
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
To define a policy, whether a request should be idempotent, you have to provider a class with the following interface:
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
```ruby
class Policy
attr_reader :request
def initialize(request)
@request = request
end
def should?
# request is Rack::Request class
end
end
```
### Example of integration for rails
```ruby
# application.rb
config.middleware.use IdempotentRequest::Middleware,
storage: IdempotentRequest::RedisStorage.new(::Redis.current, expire_time: 1.day),
policy: IdempotentRequest::Policy
config.idempotent_routes = [
{ controller: :'v1/transfers', action: :create },
]
```
```ruby
# lib/idempotent-request/policy.rb
module IdempotentRequest
class Policy
attr_reader :request
def initialize(request)
@request = request
end
def should?
route = Rails.application.routes.recognize_path(request.path, method: request.request_method)
Rails.application.config.idempotent_routes.any? do |idempotent_route|
idempotent_route[:controller] == route[:controller].to_sym &&
idempotent_route[:action] == route[:action].to_sym
end
end
end
end
```
## Custom options
```ruby
# application.rb
config.middleware.use IdempotentRequest::Middleware,
header_key: 'X-Qonto-Idempotency-Key', # by default Idempotency-key
policy: IdempotentRequest::Policy,
callback: IdempotentRequest::RailsCallback,
storage: IdempotentRequest::RedisStorage.new(::Redis.current, expire_time: 1.day, namespace: 'idempotency_keys')
```
### Policy
Custom class to decide whether the request should be idempotent.
See *Example of integration for rails*
### Storage
Where the response will be stored. Can be any class that implements the following interface:
```ruby
def read(key)
# read from a storage
end
def write(key, payload)
# write to a storage
end
```
### Callback
Get notified when the client sends a request with the same idempotency key:
```ruby
class RailsCallback < Callback
def detected(key:)
# `request` is also available
Rails.logger.warn "IdempotentRequest request detected, key: #{key}"
end
end
```
## Contributing

View File

@ -9,9 +9,8 @@ Gem::Specification.new do |spec|
spec.authors = ['Dmytro Zakharov']
spec.email = ['dmytro@qonto.eu']
spec.summary = %q{Write a short summary, because Rubygems requires one.}
spec.description = %q{Write a longer description or delete this line.}
spec.homepage = "TODO: Put your gem's website or public repo URL here."
spec.summary = %q{Rack middleware ensuring at most once requests for mutating endpoints.}
spec.homepage = 'https://github.com/qonto/idempotent-request'
spec.license = 'MIT'
spec.files = `git ls-files -z`.split("\x0").reject do |f|