mirror of
https://github.com/ditkrg/idempotent-request.git
synced 2026-01-22 13:56:45 +00:00
update readme
This commit is contained in:
parent
b82e271caa
commit
2d5542f256
116
README.md
116
README.md
@ -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
|
||||
|
||||
|
||||
@ -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|
|
||||
|
||||
Loading…
Reference in New Issue
Block a user