class Fly::RegionalDatabase::ReplayableRequestMiddleware
Public Class Methods
new(app)
click to toggle source
# File lib/fly-ruby/regional_database.rb, line 43 def initialize(app) @app = app end
Public Instance Methods
call(env)
click to toggle source
# File lib/fly-ruby/regional_database.rb, line 59 def call(env) request = Rack::Request.new(env) # Does this request satisfiy a condition for replaying in the primary region? # # 1. Its HTTP method matches those configured for automatic replay # 2. It arrived before the threshold defined by the last write request. # This threshold helps avoid the same client from missing its own # write due to replication lag. if Fly.configuration.in_secondary_region? if replayable_http_method?(request.request_method) return RegionalDatabase.replay_in_primary_region!(state: "http_method") elsif within_replay_threshold?(request.cookies[Fly.configuration.replay_threshold_cookie]) return RegionalDatabase.replay_in_primary_region!(state: "threshold") end end status, headers, body = @app.call(env) response = Rack::Response.new(body, status, headers) replay_state = replay_request_state(request.get_header("HTTP_FLY_REPLAY_SRC")) # Request was replayed, but not by a threshold, so set a threshold within which # all requests should be replayed to the primary region if replay_state && replay_state != "threshold" response.set_cookie( Fly.configuration.replay_threshold_cookie, Time.now.to_i + Fly.configuration.replay_threshold_in_seconds ) end response.finish end
replay_request_state(header_value)
click to toggle source
# File lib/fly-ruby/regional_database.rb, line 55 def replay_request_state(header_value) header_value&.scan(/(.*?)=(.*?)($|;)/)&.detect { |v| v[0] == "state" }&.at(1) end
replayable_http_method?(http_method)
click to toggle source
# File lib/fly-ruby/regional_database.rb, line 51 def replayable_http_method?(http_method) Fly.configuration.replay_http_methods.include?(http_method) end
within_replay_threshold?(threshold)
click to toggle source
# File lib/fly-ruby/regional_database.rb, line 47 def within_replay_threshold?(threshold) threshold && (threshold.to_i - Time.now.to_i) > 0 end