Class: LiveKit::RegionFailoverMiddleware
- Inherits:
-
Faraday::Middleware
- Object
- Faraday::Middleware
- LiveKit::RegionFailoverMiddleware
- Defined in:
- lib/livekit/failover.rb
Overview
Faraday middleware that fails over to alternative LiveKit Cloud regions on a retryable error: any transport error or HTTP 5xx. A 4xx is returned immediately. The request body and headers are replayed intact against the next untried region, with exponential backoff.
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app, options = {}) ⇒ RegionFailoverMiddleware
constructor
A new instance of RegionFailoverMiddleware.
Constructor Details
#initialize(app, options = {}) ⇒ RegionFailoverMiddleware
Returns a new instance of RegionFailoverMiddleware.
147 148 149 150 151 152 153 |
# File 'lib/livekit/failover.rb', line 147 def initialize(app, = {}) super(app) @failover = .fetch(:failover, true) # +force+ / +backoff_base+ are internal test-only knobs. @force = .fetch(:force, false) @backoff_base = .fetch(:backoff_base, Failover::BACKOFF_BASE) end |
Instance Method Details
#call(env) ⇒ Object
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/livekit/failover.rb', line 155 def call(env) original_url = env.url.dup request_body = env.body # A per-request timeout override (e.g. for SIP dialing) travels as an # internal header; consume it so it isn't sent to the server. Otherwise # use the connection's configured timeout. timeout = env.request_headers.delete(Failover::TIMEOUT_HEADER)&.to_f timeout ||= env.request.timeout env.request.timeout = timeout if timeout request_headers = env.request_headers.dup max_attempts = Failover.attempts(@failover, original_url.host, @force, timeout) attempted = [Failover.host_key(original_url)] regions = nil current_url = original_url attempt = 0 loop do is_last = attempt + 1 >= max_attempts env.url = current_url env.body = request_body response = nil error = nil begin response = @app.call(env) rescue Faraday::Error => e error = e end # Success or a non-retryable 4xx is terminal. return response if response && response.status < 500 nxt = nil unless is_last regions ||= Failover.region_uris(original_url, request_headers) nxt = Failover.pick_next(regions, attempted) end if nxt.nil? return response if response raise error end reason = response ? "status #{response.status}" : (error&. || 'error') warn("livekit API request to #{current_url.host} failed (#{reason}), " \ "retrying with fallback url #{nxt}") sleep(@backoff_base * (2**attempt)) attempted << Failover.host_key(nxt) # Swap only the region's scheme/host/port, preserving the request path. current_url = original_url.dup current_url.scheme = nxt.scheme current_url.host = nxt.host current_url.port = nxt.port attempt += 1 end end |