reacto 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +32 -0
- data/README.md +1 -0
- data/lib/reacto/behaviours.rb +50 -0
- data/lib/reacto/constants.rb +7 -0
- data/lib/reacto/executors.rb +31 -0
- data/lib/reacto/operations/buffer.rb +80 -0
- data/lib/reacto/operations/concat.rb +23 -0
- data/lib/reacto/operations/diff.rb +36 -0
- data/lib/reacto/operations/drop.rb +41 -0
- data/lib/reacto/operations/drop_errors.rb +15 -0
- data/lib/reacto/operations/flat_map.rb +26 -0
- data/lib/reacto/operations/flatten.rb +26 -0
- data/lib/reacto/operations/inject.rb +43 -0
- data/lib/reacto/operations/last.rb +31 -0
- data/lib/reacto/operations/map.rb +38 -0
- data/lib/reacto/operations/merge.rb +47 -0
- data/lib/reacto/operations/prepend.rb +19 -0
- data/lib/reacto/operations/select.rb +25 -0
- data/lib/reacto/operations/take.rb +38 -0
- data/lib/reacto/operations/throttle.rb +60 -0
- data/lib/reacto/operations/track_on.rb +18 -0
- data/lib/reacto/operations/uniq.rb +22 -0
- data/lib/reacto/operations.rb +23 -0
- data/lib/reacto/resources/executor_resource.rb +19 -0
- data/lib/reacto/resources.rb +1 -0
- data/lib/reacto/subscriptions/buffered_subscription.rb +52 -0
- data/lib/reacto/subscriptions/combining_last_subscription.rb +22 -0
- data/lib/reacto/subscriptions/combining_subscription.rb +8 -0
- data/lib/reacto/subscriptions/composite_subscription.rb +82 -0
- data/lib/reacto/subscriptions/executor_subscription.rb +63 -0
- data/lib/reacto/subscriptions/flat_map_subscription.rb +20 -0
- data/lib/reacto/subscriptions/inner_subscription.rb +47 -0
- data/lib/reacto/subscriptions/operation_subscription.rb +25 -0
- data/lib/reacto/subscriptions/simple_subscription.rb +80 -0
- data/lib/reacto/subscriptions/subscription.rb +21 -0
- data/lib/reacto/subscriptions/subscription_wrapper.rb +16 -0
- data/lib/reacto/subscriptions/tracker_subscription.rb +76 -0
- data/lib/reacto/subscriptions/zipping_subscription.rb +43 -0
- data/lib/reacto/subscriptions.rb +27 -0
- data/lib/reacto/trackable.rb +317 -0
- data/lib/reacto/tracker.rb +33 -0
- data/lib/reacto/version.rb +4 -0
- data/lib/reacto.rb +10 -0
- data/reacto.gemspec +27 -0
- data/spec/reacto/create_trackable_spec.rb +245 -0
- data/spec/reacto/executors_and_trackable_spec.rb +32 -0
- data/spec/reacto/operations/track_on_spec.rb +20 -0
- data/spec/reacto/trackable/buffer_spec.rb +58 -0
- data/spec/reacto/trackable/throttle_spec.rb +15 -0
- data/spec/reacto/trackable/zip_spec.rb +25 -0
- data/spec/reacto/trackable_spec.rb +417 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/helpers.rb +16 -0
- metadata +150 -0
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
require 'reacto/constants'
|
3
|
+
require 'reacto/subscriptions/operation_subscription'
|
4
|
+
|
5
|
+
module Reacto
|
6
|
+
module Operations
|
7
|
+
class Throttle
|
8
|
+
def initialize(delay)
|
9
|
+
@delay = delay
|
10
|
+
@last = NO_VALUE
|
11
|
+
@ready = false
|
12
|
+
@error = NO_VALUE
|
13
|
+
@close = false
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(tracker)
|
17
|
+
close = -> () { @close = true }
|
18
|
+
error = lambda do |e|
|
19
|
+
delay_task(tracker) unless @ready
|
20
|
+
@error = e
|
21
|
+
end
|
22
|
+
value = lambda do |v|
|
23
|
+
delay_task(tracker) unless @ready
|
24
|
+
@last = v
|
25
|
+
end
|
26
|
+
|
27
|
+
Subscriptions::OperationSubscription.new(
|
28
|
+
tracker,
|
29
|
+
value: value,
|
30
|
+
close: close,
|
31
|
+
error: error
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def finish
|
38
|
+
@task.shutdown if @task
|
39
|
+
end
|
40
|
+
|
41
|
+
def delay_task(tracker)
|
42
|
+
@task = Concurrent::TimerTask.new(execution_interval: @delay) do
|
43
|
+
if @error != NO_VALUE
|
44
|
+
tracker.on_error(@error)
|
45
|
+
finish
|
46
|
+
elsif @close
|
47
|
+
tracker.on_close
|
48
|
+
finish
|
49
|
+
elsif @last != NO_VALUE
|
50
|
+
tracker.on_value(@last)
|
51
|
+
@last = NO_VALUE
|
52
|
+
end
|
53
|
+
end
|
54
|
+
@task.execute
|
55
|
+
@ready = true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'reacto/subscriptions/executor_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class TrackOn
|
6
|
+
def initialize(executor)
|
7
|
+
@executor = executor
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(tracker)
|
11
|
+
Subscriptions::ExecutorSubscription.new(
|
12
|
+
tracker, @executor
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class Uniq
|
6
|
+
def passed
|
7
|
+
@passed ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(tracker)
|
11
|
+
value = lambda do |v|
|
12
|
+
unless passed[v]
|
13
|
+
passed[v] = true
|
14
|
+
tracker.on_value(v)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Subscriptions::OperationSubscription.new(tracker, value: value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'reacto/operations/map'
|
2
|
+
require 'reacto/operations/select'
|
3
|
+
require 'reacto/operations/inject'
|
4
|
+
require 'reacto/operations/diff'
|
5
|
+
require 'reacto/operations/drop'
|
6
|
+
require 'reacto/operations/drop_errors'
|
7
|
+
require 'reacto/operations/take'
|
8
|
+
require 'reacto/operations/last'
|
9
|
+
require 'reacto/operations/track_on'
|
10
|
+
require 'reacto/operations/prepend'
|
11
|
+
require 'reacto/operations/concat'
|
12
|
+
require 'reacto/operations/merge'
|
13
|
+
require 'reacto/operations/buffer'
|
14
|
+
require 'reacto/operations/uniq'
|
15
|
+
require 'reacto/operations/flatten'
|
16
|
+
require 'reacto/operations/throttle'
|
17
|
+
require 'reacto/operations/flat_map'
|
18
|
+
|
19
|
+
module Reacto
|
20
|
+
module Operations
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Reacto
|
2
|
+
module Resources
|
3
|
+
class ExecutorResource
|
4
|
+
def initialize(executor, threads: [])
|
5
|
+
@executor = executor
|
6
|
+
@threads = threads
|
7
|
+
end
|
8
|
+
def cleanup
|
9
|
+
@executor.shutdown
|
10
|
+
@executor = nil
|
11
|
+
|
12
|
+
@threads.each do |thread|
|
13
|
+
Thread.kill(thread)
|
14
|
+
end
|
15
|
+
@threads = []
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'reacto/resources/executor_resource'
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Reacto
|
2
|
+
module Subscriptions
|
3
|
+
class BufferedSubscription < SimpleSubscription
|
4
|
+
include Subscription
|
5
|
+
|
6
|
+
attr_accessor :current_index, :buffer, :last_error
|
7
|
+
|
8
|
+
def initialize(parent)
|
9
|
+
@parent = parent
|
10
|
+
@closed = false
|
11
|
+
@active = false
|
12
|
+
|
13
|
+
@buffer = Hash.new(NO_VALUE)
|
14
|
+
@current_index = 0
|
15
|
+
@last_error = nil
|
16
|
+
|
17
|
+
open = lambda do
|
18
|
+
@active = true
|
19
|
+
@parent.on_open
|
20
|
+
end
|
21
|
+
|
22
|
+
value = lambda do |v|
|
23
|
+
@buffer[@current_index] = v
|
24
|
+
@current_index += 1
|
25
|
+
|
26
|
+
@parent.on_value(v)
|
27
|
+
end
|
28
|
+
|
29
|
+
error = lambda do |e|
|
30
|
+
@last_error = e
|
31
|
+
@parent.on_error(e)
|
32
|
+
end
|
33
|
+
|
34
|
+
close = lambda do
|
35
|
+
@closed = true
|
36
|
+
@parent.on_close
|
37
|
+
end
|
38
|
+
|
39
|
+
super(open: open, value: value, error: error, close: close)
|
40
|
+
end
|
41
|
+
|
42
|
+
def active?
|
43
|
+
@active
|
44
|
+
end
|
45
|
+
|
46
|
+
def closed?
|
47
|
+
@closed
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'reacto/constants'
|
2
|
+
require 'reacto/subscriptions/composite_subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Subscriptions
|
6
|
+
class CombiningLastSubscription < CompositeSubscription
|
7
|
+
def subscribed?
|
8
|
+
@subscriptions.all? { |s| s.subscribed? }
|
9
|
+
end
|
10
|
+
|
11
|
+
def after_on_value(_)
|
12
|
+
return if @subscriptions.map(&:last_value).any? { |vl| vl == NO_VALUE }
|
13
|
+
@subscriptions.each { |sub| sub.last_value = NO_VALUE }
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_close
|
17
|
+
return unless subscribed?
|
18
|
+
@subscriber.on_close
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'reacto/constants'
|
2
|
+
require 'reacto/subscriptions/subscription'
|
3
|
+
require 'reacto/subscriptions/inner_subscription'
|
4
|
+
|
5
|
+
module Reacto
|
6
|
+
module Subscriptions
|
7
|
+
class CompositeSubscription
|
8
|
+
include Subscription
|
9
|
+
|
10
|
+
def initialize(combinator, subscriber)
|
11
|
+
@combinator = combinator
|
12
|
+
@subscriptions = []
|
13
|
+
@subscriber = subscriber
|
14
|
+
end
|
15
|
+
|
16
|
+
def subscribed?
|
17
|
+
@subscriptions.any? { |s| s.subscribed? }
|
18
|
+
end
|
19
|
+
|
20
|
+
def unsubscribe
|
21
|
+
@subscriptions.each(&:unsubscribe)
|
22
|
+
@subscriptions = []
|
23
|
+
end
|
24
|
+
|
25
|
+
def add(_)
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_resource(_)
|
29
|
+
end
|
30
|
+
|
31
|
+
def on_open
|
32
|
+
return unless subscribed?
|
33
|
+
return unless @subscriptions.any? { |s| !s.active? }
|
34
|
+
@subscriber.on_open
|
35
|
+
end
|
36
|
+
|
37
|
+
def waiting?
|
38
|
+
@subscriptions.map(&:last_value).any? { |v| v == NO_VALUE }
|
39
|
+
end
|
40
|
+
|
41
|
+
def on_value(val)
|
42
|
+
return unless subscribed?
|
43
|
+
return if waiting?
|
44
|
+
|
45
|
+
on_value_subscriptions(val)
|
46
|
+
after_on_value(val)
|
47
|
+
end
|
48
|
+
|
49
|
+
def on_value_subscriptions(_)
|
50
|
+
@subscriber.on_value(
|
51
|
+
@combinator.call(*@subscriptions.map(&:last_value))
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
def after_on_value(_)
|
56
|
+
#nothing by default
|
57
|
+
end
|
58
|
+
|
59
|
+
def on_error(e)
|
60
|
+
# Introduce a multi-error and not call on_error right away when there is
|
61
|
+
# an error and an option is set?
|
62
|
+
return unless subscribed?
|
63
|
+
@subscriber.on_error(e)
|
64
|
+
end
|
65
|
+
|
66
|
+
def on_close
|
67
|
+
return unless subscribed?
|
68
|
+
return unless @subscriptions.any? { |s| !s.closed? }
|
69
|
+
|
70
|
+
@subscriber.on_close
|
71
|
+
unsubscribe
|
72
|
+
end
|
73
|
+
|
74
|
+
def subscription!
|
75
|
+
subscription = InnerSubscription.new(self)
|
76
|
+
@subscriptions << subscription
|
77
|
+
|
78
|
+
subscription
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'reacto/subscriptions/subscription'
|
2
|
+
require 'reacto/tracker'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Subscriptions
|
6
|
+
class ExecutorSubscription
|
7
|
+
include Subscription
|
8
|
+
|
9
|
+
def initialize(subscription, executor)
|
10
|
+
@executor = executor
|
11
|
+
@wrapped = subscription
|
12
|
+
@closed = false
|
13
|
+
end
|
14
|
+
|
15
|
+
def subscribed?
|
16
|
+
unsubscribe unless @wrapped.subscribed?
|
17
|
+
|
18
|
+
@executor.running?
|
19
|
+
end
|
20
|
+
|
21
|
+
def unsubscribe
|
22
|
+
@wrapped.unsubscribe
|
23
|
+
|
24
|
+
@executor.post(&@executor.method(:shutdown))
|
25
|
+
end
|
26
|
+
|
27
|
+
def add(subscription)
|
28
|
+
@wrapped.add(subscription)
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_resource(resource)
|
32
|
+
@wrapped.add_resource(resource)
|
33
|
+
end
|
34
|
+
|
35
|
+
def on_open
|
36
|
+
@executor.post(&@wrapped.method(:on_open))
|
37
|
+
end
|
38
|
+
|
39
|
+
def on_value(v)
|
40
|
+
return if !subscribed? || @closed
|
41
|
+
|
42
|
+
@executor.post(v, &@wrapped.method(:on_value))
|
43
|
+
end
|
44
|
+
|
45
|
+
def on_close
|
46
|
+
return if !subscribed? || @closed
|
47
|
+
|
48
|
+
@executor.post(&@wrapped.method(:on_close))
|
49
|
+
@executor.post(&method(:unsubscribe))
|
50
|
+
@closed = true
|
51
|
+
end
|
52
|
+
|
53
|
+
def on_error(error)
|
54
|
+
return if !subscribed? || @closed
|
55
|
+
|
56
|
+
@executor.post(error, &@wrapped.method(:on_error))
|
57
|
+
unsubscribe
|
58
|
+
@closed = true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'reacto/constants'
|
2
|
+
require 'reacto/subscriptions/composite_subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Subscriptions
|
6
|
+
class FlatMapSubscription < CompositeSubscription
|
7
|
+
def initialize(subscriber)
|
8
|
+
super(nil, subscriber)
|
9
|
+
end
|
10
|
+
|
11
|
+
def waiting?
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_value_subscriptions(v)
|
16
|
+
@subscriber.on_value(v)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Reacto
|
2
|
+
module Subscriptions
|
3
|
+
class InnerSubscription < SimpleSubscription
|
4
|
+
include Subscription
|
5
|
+
|
6
|
+
attr_accessor :last_value, :last_error
|
7
|
+
|
8
|
+
def initialize(parent)
|
9
|
+
@parent = parent
|
10
|
+
@closed = false
|
11
|
+
@active = false
|
12
|
+
@last_value = NO_VALUE
|
13
|
+
@last_error = nil
|
14
|
+
|
15
|
+
open = lambda do
|
16
|
+
@active = true
|
17
|
+
@parent.on_open
|
18
|
+
end
|
19
|
+
|
20
|
+
value = lambda do |v|
|
21
|
+
@last_value = v
|
22
|
+
@parent.on_value(v)
|
23
|
+
end
|
24
|
+
|
25
|
+
error = lambda do |e|
|
26
|
+
@last_error = e
|
27
|
+
@parent.on_error(e)
|
28
|
+
end
|
29
|
+
|
30
|
+
close = lambda do
|
31
|
+
@closed = true
|
32
|
+
@parent.on_close
|
33
|
+
end
|
34
|
+
|
35
|
+
super(open: open, value: value, error: error, close: close)
|
36
|
+
end
|
37
|
+
|
38
|
+
def active?
|
39
|
+
@active
|
40
|
+
end
|
41
|
+
|
42
|
+
def closed?
|
43
|
+
@closed
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'reacto/subscriptions/subscription'
|
2
|
+
require 'reacto/tracker'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Subscriptions
|
6
|
+
class OperationSubscription < Reacto::Tracker
|
7
|
+
extend Forwardable
|
8
|
+
include Subscription
|
9
|
+
|
10
|
+
delegate ['subscribed?', :unsubscribe, :add, :add_resource] => :@wrapped
|
11
|
+
|
12
|
+
def initialize(
|
13
|
+
subscription,
|
14
|
+
open: subscription.method(:on_open),
|
15
|
+
value: subscription.method(:on_value),
|
16
|
+
error: subscription.method(:on_error),
|
17
|
+
close: subscription.method(:on_close)
|
18
|
+
)
|
19
|
+
super(open: open, value: value, error: error, close: close)
|
20
|
+
|
21
|
+
@wrapped = subscription
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'reacto/constants'
|
2
|
+
require 'reacto/subscriptions/subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Subscriptions
|
6
|
+
class SimpleSubscription
|
7
|
+
include Subscription
|
8
|
+
|
9
|
+
def initialize(
|
10
|
+
open: NO_ACTION,
|
11
|
+
value: NO_ACTION,
|
12
|
+
error: DEFAULT_ON_ERROR,
|
13
|
+
close: NO_ACTION
|
14
|
+
)
|
15
|
+
@open = open
|
16
|
+
@value = value
|
17
|
+
@error = error
|
18
|
+
@close = close
|
19
|
+
|
20
|
+
@subscribed = true
|
21
|
+
@subscriptions = []
|
22
|
+
@resources = []
|
23
|
+
end
|
24
|
+
|
25
|
+
def subscribed?
|
26
|
+
@subscribed
|
27
|
+
end
|
28
|
+
|
29
|
+
def unsubscribe
|
30
|
+
@subscriptions.each(&:unsubscribe)
|
31
|
+
@subscribed = false
|
32
|
+
@resources.each(&:cleanup)
|
33
|
+
@resources = []
|
34
|
+
end
|
35
|
+
|
36
|
+
def add(subscription)
|
37
|
+
return unless subscribed?
|
38
|
+
|
39
|
+
@subscriptions << subscription
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_resource(resource)
|
43
|
+
return unless subscribed?
|
44
|
+
|
45
|
+
@resources << resource
|
46
|
+
end
|
47
|
+
|
48
|
+
def on_open
|
49
|
+
return unless subscribed?
|
50
|
+
|
51
|
+
@open.call
|
52
|
+
@subscriptions.each(&:on_open)
|
53
|
+
end
|
54
|
+
|
55
|
+
def on_value(v)
|
56
|
+
return unless subscribed?
|
57
|
+
|
58
|
+
@value.call(v)
|
59
|
+
@subscriptions.each { |s| s.on_value(v) }
|
60
|
+
end
|
61
|
+
|
62
|
+
def on_error(e)
|
63
|
+
return unless subscribed?
|
64
|
+
|
65
|
+
@error.call(error)
|
66
|
+
@subscriptions.each { |s| s.on_error(e) }
|
67
|
+
unsubscribe
|
68
|
+
end
|
69
|
+
|
70
|
+
def on_close
|
71
|
+
return unless subscribed?
|
72
|
+
|
73
|
+
@close.call
|
74
|
+
@subscriptions.each(&:on_close)
|
75
|
+
unsubscribe
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Reacto
|
2
|
+
module Subscriptions
|
3
|
+
module Subscription
|
4
|
+
def subscribed?
|
5
|
+
raise NotImplementedError.new('Abstract method!')
|
6
|
+
end
|
7
|
+
|
8
|
+
def unsubscribe
|
9
|
+
raise NotImplementedError.new('Abstract method!')
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(subscription)
|
13
|
+
raise NotImplementedError.new('Abstract method!')
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_resource(resource)
|
17
|
+
raise NotImplementedError.new('Abstract method!')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'reacto/subscriptions/subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Subscriptions
|
5
|
+
class SubscriptionWrapper
|
6
|
+
extend Forwardable
|
7
|
+
include Subscription
|
8
|
+
|
9
|
+
delegate ['subscribed?', :unsubscribe, :add, :add_resource] => :@wrapped
|
10
|
+
|
11
|
+
def initialize(wrapped)
|
12
|
+
@wrapped = wrapped
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'reacto/subscriptions/subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Subscriptions
|
5
|
+
class TrackerSubscription
|
6
|
+
include Subscription
|
7
|
+
|
8
|
+
def initialize(notification_tracker, trackable)
|
9
|
+
@notification_tracker = notification_tracker
|
10
|
+
@trackable = trackable
|
11
|
+
|
12
|
+
@subscribed = true
|
13
|
+
@subscriptions = []
|
14
|
+
@resources = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def subscribed?
|
18
|
+
@subscribed
|
19
|
+
end
|
20
|
+
|
21
|
+
def unsubscribe
|
22
|
+
@subscriptions.each(&:unsubscribe)
|
23
|
+
|
24
|
+
@trackable.off(@notification_tracker)
|
25
|
+
|
26
|
+
@trackable = nil
|
27
|
+
@notification_tracker = nil
|
28
|
+
@subscribed = false
|
29
|
+
@resources.each(&:cleanup)
|
30
|
+
@resources = []
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_resource(resource)
|
34
|
+
return unless subscribed?
|
35
|
+
|
36
|
+
@resources << resource
|
37
|
+
end
|
38
|
+
|
39
|
+
def add(subscription)
|
40
|
+
return unless subscribed?
|
41
|
+
|
42
|
+
@subscriptions << subscription
|
43
|
+
end
|
44
|
+
|
45
|
+
def on_open
|
46
|
+
return unless subscribed?
|
47
|
+
|
48
|
+
@notification_tracker.on_open
|
49
|
+
@subscriptions.each(&:on_open)
|
50
|
+
end
|
51
|
+
|
52
|
+
def on_value(v)
|
53
|
+
return unless subscribed?
|
54
|
+
|
55
|
+
@notification_tracker.on_value(v)
|
56
|
+
@subscriptions.each { |s| s.on_value(v) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def on_error(e)
|
60
|
+
return unless subscribed?
|
61
|
+
|
62
|
+
@notification_tracker.on_error(e)
|
63
|
+
@subscriptions.each { |s| s.on_error(e) }
|
64
|
+
unsubscribe
|
65
|
+
end
|
66
|
+
|
67
|
+
def on_close
|
68
|
+
return unless subscribed?
|
69
|
+
|
70
|
+
@notification_tracker.on_close
|
71
|
+
@subscriptions.each(&:on_close)
|
72
|
+
unsubscribe
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|