Class: OctaSpace::Middleware::UrlRotator
- Inherits:
-
Object
- Object
- OctaSpace::Middleware::UrlRotator
- Defined in:
- lib/octaspace/middleware/url_rotator.rb
Overview
Thread-safe round-robin URL rotator with automatic failover
When multiple base_urls are configured, requests are distributed across all healthy URLs. Failed URLs enter a cooldown period before being re-admitted to the rotation.
Constant Summary collapse
- FAILURE_COOLDOWN =
Seconds a failed URL is excluded from rotation
30
Instance Method Summary collapse
-
#available_urls ⇒ Array<String>
Currently healthy URLs (excluding cooldown).
-
#initialize(urls) ⇒ UrlRotator
constructor
A new instance of UrlRotator.
-
#mark_failed(url) ⇒ Object
Mark a URL as temporarily failed.
-
#mark_success(url) ⇒ Object
Mark a URL as recovered (remove from failed list).
-
#next_url ⇒ String
Next available URL (round-robin), falls back to first if all failed.
-
#reset! ⇒ Object
Reset state — useful in tests.
-
#stats ⇒ Hash
Diagnostic stats.
Constructor Details
#initialize(urls) ⇒ UrlRotator
Returns a new instance of UrlRotator.
25 26 27 28 29 30 |
# File 'lib/octaspace/middleware/url_rotator.rb', line 25 def initialize(urls) @urls = urls.dup.freeze @counter = 0 @failed = {} # url => Time failed_at @mutex = Mutex.new end |
Instance Method Details
#available_urls ⇒ Array<String>
Returns currently healthy URLs (excluding cooldown).
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/octaspace/middleware/url_rotator.rb', line 57 def available_urls now = Time.now @mutex.synchronize do @urls.reject do |url| failed_at = @failed[url] next false unless failed_at if now - failed_at < FAILURE_COOLDOWN true else @failed.delete(url) false end end end end |
#mark_failed(url) ⇒ Object
Mark a URL as temporarily failed
46 47 48 |
# File 'lib/octaspace/middleware/url_rotator.rb', line 46 def mark_failed(url) @mutex.synchronize { @failed[url] = Time.now } end |
#mark_success(url) ⇒ Object
Mark a URL as recovered (remove from failed list)
52 53 54 |
# File 'lib/octaspace/middleware/url_rotator.rb', line 52 def mark_success(url) @mutex.synchronize { @failed.delete(url) } end |
#next_url ⇒ String
Returns next available URL (round-robin), falls back to first if all failed.
33 34 35 36 37 38 39 40 41 42 |
# File 'lib/octaspace/middleware/url_rotator.rb', line 33 def next_url available = available_urls return @urls.first if available.empty? @mutex.synchronize do idx = @counter % available.size @counter += 1 available[idx] end end |
#reset! ⇒ Object
Reset state — useful in tests
84 85 86 87 88 89 |
# File 'lib/octaspace/middleware/url_rotator.rb', line 84 def reset! @mutex.synchronize do @counter = 0 @failed.clear end end |
#stats ⇒ Hash
Returns diagnostic stats.
75 76 77 78 79 80 81 |
# File 'lib/octaspace/middleware/url_rotator.rb', line 75 def stats { total: @urls.size, available: available_urls.size, failed: @mutex.synchronize { @failed.keys } } end |