Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Rack middleware ensuring at most once requests for mutating endpoints.

License

NotificationsYou must be signed in to change notification settings

qonto/idempotent-request

Repository files navigation

Gem VersionCI Status

Idempotent Request

Rack middleware ensuring at most once requests for mutating endpoints.

Installation

Add this line to your application's Gemfile:

gem'idempotent-request'

And then execute:

$ bundle

Or install it yourself as:

$ gem install idempotent-request

How it works

  1. Front-end generates a uniquekey then a user goes to a specific route (for example, transfer page).
  2. When user clicks "Submit" button, thekey is sent in the headeridempotency-key and back-end stores server response into redis.
  3. All the consecutive requests with thekey 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.

Configuration

# application.rbconfig.middleware.useIdempotentRequest::Middleware,storage:IdempotentRequest::RedisStorage.new(::Redis.current,expire_time:1.day),policy:YOUR_CLASS

To define a policy, whether a request should be idempotent, you have to provider a class with the following interface:

classPolicyattr_reader:requestdefinitialize(request)@request=requestenddefshould?# request is Rack::Request classendend

Example of integration for rails

# application.rbconfig.middleware.useIdempotentRequest::Middleware,storage:IdempotentRequest::RedisStorage.new(::Redis.current,expire_time:1.day),policy:IdempotentRequest::Policyconfig.idempotent_routes=[{controller::'v1/transfers',action::create},]
# lib/idempotent-request/policy.rbmoduleIdempotentRequestclassPolicyattr_reader:requestdefinitialize(request)@request=requestenddefshould?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_symendendendend

Use ActiveSupport::Notifications to read events

# config/initializers/idempotent_request.rbActiveSupport::Notifications.subscribe('idempotent.request')do |name,start,finish,request_id,payload|notification=payload[:request].env['idempotent.request']ifnotification['read']Rails.logger.info"IdempotentRequest: Hit cached response from key#{notification['key']}, response:#{notification['read']}"elsifnotification['write']Rails.logger.info"IdempotentRequest: Write: key#{notification['key']}, status:#{notification['write'][0]}, headers:#{notification['write'][1]}, unlocked?#{notification['unlocked']}"elsifnotification['concurrent_request_response']Rails.logger.warn"IdempotentRequest: Concurrent request detected with key#{notification['key']}"endend

Custom options

# application.rbconfig.middleware.useIdempotentRequest::Middleware,header_key:'X-Qonto-Idempotency-Key',# by default Idempotency-keypolicy:IdempotentRequest::Policy,callback:IdempotentRequest::RailsCallback,storage:IdempotentRequest::RedisStorage.new(::Redis.current,expire_time:1.day,namespace:'idempotency_keys'),conflict_response_status:409

Policy

Custom class to decide whether the request should be idempotent.

SeeExample of integration for rails

Storage

Where the response will be stored. Can be any class that implements the following interface:

defread(key)# read from a storageenddefwrite(key,payload)# write to a storageend

Callback

Get notified when a client sends a request with the same idempotency key:

classRailsCallbackattr_reader:requestdefinitialize(request)@request=requestenddefdetected(key:)Rails.logger.warn"IdempotentRequest request detected, key:#{key}"endend

Conflict response status

Define http status code that should be returned when a client sends concurrent requests with the same idempotency key.

Contributing

Bug reports and pull requests are welcome on GitHub athttps://github.com/[USERNAME]/idempotent-request. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to theContributor Covenant code of conduct.

License

The gem is available as open source under the terms of theMIT License.

Code of Conduct

Everyone interacting in the Idempotent::Request project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow thecode of conduct.

Releasing

To publish a new version to rubygems, update the version inlib/version.rb, and merge.

About

Rack middleware ensuring at most once requests for mutating endpoints.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp