Module: Hibiki
- Defined in:
- lib/hibiki/dsl.rb,
lib/hibiki/root.rb,
lib/hibiki/batch.rb,
lib/hibiki/state.rb,
lib/hibiki/effect.rb,
lib/hibiki/derived.rb,
lib/hibiki/version.rb,
lib/hibiki/reactive.rb,
lib/hibiki/tracking.rb
Defined Under Namespace
Modules: DSL, Observer, Owner, Reactive, Trackable
Classes: Derived, Effect, Root, State
Constant Summary
collapse
- VERSION =
"0.1.0"
Class Method Summary
collapse
Class Method Details
.batch ⇒ Object
18
19
20
21
22
23
24
25
26
27
|
# File 'lib/hibiki/batch.rb', line 18
def batch
Thread.current[:hibiki_batch_depth] = batch_depth + 1
yield
ensure
depth = batch_depth - 1
Thread.current[:hibiki_batch_depth] = depth
flush_effects if depth.zero?
end
|
.batching? ⇒ Boolean
29
|
# File 'lib/hibiki/batch.rb', line 29
def batching? = batch_depth.positive?
|
.current_observer ⇒ Object
14
|
# File 'lib/hibiki/tracking.rb', line 14
def current_observer = Fiber[:hibiki_observer]
|
.current_owner ⇒ Object
Solid keeps Owner separate from Listener: only effects own, and a lazy
derived computing mid-effect must not steal ownership of effects its
block creates. Hence a second slot rather than reusing the observer's.
32
|
# File 'lib/hibiki/tracking.rb', line 32
def current_owner = Fiber[:hibiki_owner]
|
.error_handler ⇒ Object
Where effect errors raised during a flush go (Solid's handleError):
a callable receiving (error, effect). With a handler set the flush
never raises; a raising handler propagates — we don't swallow it.
Ractor-local, not a module ivar (IsolationError off the main Ractor)
and not Thread.current (configuration set once, e.g. in an
initializer, must be visible to threads spawned later). Per-Ractor
fits the one-independent-world-per-Ractor model.
40
|
# File 'lib/hibiki/batch.rb', line 40
def error_handler = Ractor.current[:hibiki_error_handler]
|
.error_handler=(handler) ⇒ Object
42
43
44
|
# File 'lib/hibiki/batch.rb', line 42
def error_handler=(handler)
Ractor.current[:hibiki_error_handler] = handler
end
|
.on_cleanup(&block) ⇒ Object
Solid's onCleanup: registers on the current OWNER, not the listener —
a lazy derived computing mid-effect registers cleanups on the effect,
matching how effects created there are adopted. The block runs before
the owner's next rerun and on dispose. Outside any owner it can never
run; mirror Solid and warn rather than raise.
47
48
49
50
51
52
53
|
# File 'lib/hibiki/tracking.rb', line 47
def on_cleanup(&block)
owner = current_owner
return warn("Hibiki.on_cleanup: no current owner (effect or root); the cleanup can never run") unless owner
owner.add_cleanup(block)
block
end
|
.own(owner) ⇒ Object
34
35
36
37
38
39
40
|
# File 'lib/hibiki/tracking.rb', line 34
def own(owner)
prev = Fiber[:hibiki_owner]
Fiber[:hibiki_owner] = owner
yield
ensure
Fiber[:hibiki_owner] = prev
end
|
.root ⇒ Object
Hibiki.root { |root| ... } — build a graph inside an ownership scope;
tear the whole thing down later with root.dispose. Unlike Solid
(which returns the block's result and yields a dispose function) the
root itself is yielded AND returned: in Ruby the caller, not the
block, typically owns teardown.
44
|
# File 'lib/hibiki/root.rb', line 44
def root(&) = Root.new(&)
|
.schedule(effect) ⇒ Object
31
|
# File 'lib/hibiki/batch.rb', line 31
def schedule(effect) = (Thread.current[:hibiki_pending_effects] ||= Set.new) << effect
|
.track(observer) ⇒ Object
16
17
18
19
20
21
22
|
# File 'lib/hibiki/tracking.rb', line 16
def track(observer)
prev = Fiber[:hibiki_observer]
Fiber[:hibiki_observer] = observer
yield
ensure
Fiber[:hibiki_observer] = prev
end
|
.untrack ⇒ Object
Solid's untrack: reads inside the block register nothing. Only the
listener is suppressed — the owner slot is left alone, so effects
created under untrack are still adopted.
27
|
# File 'lib/hibiki/tracking.rb', line 27
def untrack(&) = track(nil, &)
|