Class: Kameleoon::ClientReadiness
- Inherits:
-
Object
- Object
- Kameleoon::ClientReadiness
- Defined in:
- lib/kameleoon/client_readiness.rb
Overview
ClientReadiness tracks whether the SDK has successfully loaded its configuration
and exposes that state to KameleoonClient#wait_init and KameleoonClient#is_ready?:
- a successful fetch settles the state successfully;
- a failed fetch settles it with an
Exception::Initializationerror.
Readiness is monotonic: once the SDK is ready it stays ready, and a later failed fetch can never revert it. A failure reported before the first success does not prevent a subsequent successful retry from marking the SDK ready.
It is created on the thread that builds the client but settled from the background thread(s) performing configuration fetches, so it relies on Concurrent::Event (which allows cross-thread release).
Instance Method Summary collapse
-
#initialize(site_code, environment) ⇒ ClientReadiness
constructor
A new instance of ClientReadiness.
-
#mark_not_ready(cause) ⇒ Object
Reports a failed fetch with an
Exception::Initializationerror, but only while the SDK is not yet ready. -
#mark_ready ⇒ Object
Marks the SDK ready and releases all waiters.
-
#ready? ⇒ Boolean
This is the per-request hot path, so it is lock-free:
@readyis only ever flipped false -> true (readiness is monotonic), making a plain ivar read safe. -
#wait_with_timeout(timeout_second) ⇒ Kameleoon::Exception::Initialization?
Blocks until the readiness state is settled, but no longer than
timeout_second.
Constructor Details
#initialize(site_code, environment) ⇒ ClientReadiness
Returns a new instance of ClientReadiness.
47 48 49 50 51 52 53 |
# File 'lib/kameleoon/client_readiness.rb', line 47 def initialize(site_code, environment) @mutex = Mutex.new @state = State.new @ready = false @site_code = site_code @environment = environment end |
Instance Method Details
#mark_not_ready(cause) ⇒ Object
Reports a failed fetch with an Exception::Initialization error, but only while
the SDK is not yet ready. A failure never reverts an already-ready client and is
reported at most once, so the first reported cause is the one waiters observe.
79 80 81 82 83 84 85 86 |
# File 'lib/kameleoon/client_readiness.rb', line 79 def mark_not_ready(cause) @mutex.synchronize do unless @state.settled? @state.error = Exception::Initialization.new(@site_code, @environment, cause) @state.settle end # else: already ready, or the failure was already reported end end |
#mark_ready ⇒ Object
Marks the SDK ready and releases all waiters.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/kameleoon/client_readiness.rb', line 56 def mark_ready @mutex.synchronize do @ready = true if @state.settled? unless @state.error.nil? # Recovery after a failure: the failed state is left settled for its waiters, # and a fresh, ready state is published for the new ones. state = State.new state.settle @state = state end else @state.settle end end end |
#ready? ⇒ Boolean
This is the per-request hot path, so it is lock-free: @ready is only ever
flipped false -> true (readiness is monotonic), making a plain ivar read safe.
At worst a reader briefly observes false while mark_ready is completing,
which is indistinguishable from calling a moment earlier.
96 97 98 |
# File 'lib/kameleoon/client_readiness.rb', line 96 def ready? @ready end |
#wait_with_timeout(timeout_second) ⇒ Kameleoon::Exception::Initialization?
Blocks until the readiness state is settled, but no longer than timeout_second.
Returns the result of the configuration fetch: nil once the SDK is ready, or the
Exception::Initialization error the fetch failure was reported with (fail-fast -
it does not wait for background retries). If no fetch result is available within
the timeout, returns an Exception::Initialization error caused by the expired
timeout. A non-positive timeout expires immediately unless a result is already
available. An expired timeout does not settle the readiness state: once the SDK
becomes ready, a subsequent call returns nil.
111 112 113 114 115 116 117 118 119 |
# File 'lib/kameleoon/client_readiness.rb', line 111 def wait_with_timeout(timeout_second) state = current_state return state.error if state.settled? return timeout_failure(timeout_second) if timeout_second <= 0 return state.error if state.wait(timeout_second) timeout_failure(timeout_second) end |