reacto 0.1.0 → 1.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 +4 -4
- data/.gitignore +2 -0
- data/README.md +932 -11
- data/doc/reactive_programming_with_reacto.md +238 -0
- data/lib/reacto.rb +70 -0
- data/lib/reacto/behaviours.rb +24 -1
- data/lib/reacto/constants.rb +4 -1
- data/lib/reacto/executors.rb +8 -10
- data/lib/reacto/labeled_trackable.rb +14 -2
- data/lib/reacto/operations.rb +23 -2
- data/lib/reacto/operations/act.rb +69 -0
- data/lib/reacto/operations/append.rb +45 -0
- data/lib/reacto/operations/blocking_enumerable.rb +40 -0
- data/lib/reacto/operations/buffer.rb +1 -4
- data/lib/reacto/operations/chunk.rb +81 -0
- data/lib/reacto/operations/chunk_while.rb +56 -0
- data/lib/reacto/operations/cycle.rb +27 -0
- data/lib/reacto/operations/delay_each.rb +75 -0
- data/lib/reacto/operations/depend_on.rb +4 -5
- data/lib/reacto/operations/diff.rb +8 -10
- data/lib/reacto/operations/drop.rb +6 -8
- data/lib/reacto/operations/drop_while.rb +23 -0
- data/lib/reacto/operations/each_collect.rb +57 -0
- data/lib/reacto/operations/each_with_object.rb +31 -0
- data/lib/reacto/operations/extremums.rb +54 -0
- data/lib/reacto/operations/find_index.rb +28 -0
- data/lib/reacto/operations/flat_map.rb +2 -2
- data/lib/reacto/operations/flatten.rb +2 -7
- data/lib/reacto/operations/flatten_labeled.rb +44 -0
- data/lib/reacto/operations/{label.rb → group_by_label.rb} +1 -1
- data/lib/reacto/operations/include.rb +40 -0
- data/lib/reacto/operations/inject.rb +15 -9
- data/lib/reacto/operations/map.rb +15 -13
- data/lib/reacto/operations/merge.rb +17 -16
- data/lib/reacto/operations/operation_on_labeled.rb +29 -0
- data/lib/reacto/operations/partition.rb +52 -0
- data/lib/reacto/operations/prepend.rb +0 -3
- data/lib/reacto/operations/rescue_and_replace_error.rb +21 -0
- data/lib/reacto/operations/retry.rb +26 -0
- data/lib/reacto/operations/retry_when.rb +30 -0
- data/lib/reacto/operations/select.rb +2 -6
- data/lib/reacto/operations/slice.rb +50 -0
- data/lib/reacto/operations/slice_when.rb +41 -0
- data/lib/reacto/operations/split_labeled.rb +32 -0
- data/lib/reacto/operations/take.rb +9 -14
- data/lib/reacto/operations/take_while.rb +28 -0
- data/lib/reacto/operations/throttle.rb +2 -3
- data/lib/reacto/operations/track_on.rb +1 -3
- data/lib/reacto/shared_trackable.rb +2 -5
- data/lib/reacto/subscriptions/buffered_subscription.rb +10 -9
- data/lib/reacto/subscriptions/executor_subscription.rb +12 -4
- data/lib/reacto/subscriptions/tracker_subscription.rb +0 -4
- data/lib/reacto/subscriptions/zipping_subscription.rb +0 -1
- data/lib/reacto/trackable.rb +429 -64
- data/lib/reacto/version.rb +1 -1
- data/reacto.gemspec +2 -3
- data/spec/reacto/labeled_trackable_spec.rb +17 -0
- data/spec/reacto/trackable/act_spec.rb +15 -0
- data/spec/reacto/trackable/all_spec.rb +38 -0
- data/spec/reacto/trackable/any_spec.rb +39 -0
- data/spec/reacto/trackable/append_spec.rb +38 -0
- data/spec/reacto/trackable/buffer_spec.rb +11 -15
- data/spec/reacto/trackable/chunk_spec.rb +86 -0
- data/spec/reacto/trackable/chunk_while_spec.rb +22 -0
- data/spec/reacto/trackable/class_level/combine_last_spec.rb +1 -3
- data/spec/reacto/trackable/class_level/interval_spec.rb +4 -6
- data/spec/reacto/trackable/class_level/make_spec.rb +0 -15
- data/spec/reacto/trackable/{zip_spec.rb → class_level/zip_spec.rb} +0 -2
- data/spec/reacto/trackable/concat_spec.rb +12 -12
- data/spec/reacto/trackable/count_spec.rb +38 -0
- data/spec/reacto/trackable/cycle_spec.rb +14 -0
- data/spec/reacto/trackable/delay_each_spec.rb +18 -0
- data/spec/reacto/trackable/depend_on_spec.rb +6 -9
- data/spec/reacto/trackable/diff_spec.rb +3 -5
- data/spec/reacto/trackable/drop_errors_spec.rb +1 -3
- data/spec/reacto/trackable/drop_while_spec.rb +15 -0
- data/spec/reacto/trackable/each_cons_spec.rb +53 -0
- data/spec/reacto/trackable/each_slice_spec.rb +37 -0
- data/spec/reacto/trackable/each_with_index_spec.rb +33 -0
- data/spec/reacto/trackable/each_with_object_spec.rb +26 -0
- data/spec/reacto/trackable/entries_spec.rb +25 -0
- data/spec/reacto/trackable/execute_on_spec.rb +33 -0
- data/spec/reacto/trackable/find_index_spec.rb +31 -0
- data/spec/reacto/trackable/find_spec.rb +34 -0
- data/spec/reacto/trackable/first_spec.rb +36 -0
- data/spec/reacto/trackable/flat_map_latest_spec.rb +5 -5
- data/spec/reacto/trackable/flat_map_spec.rb +25 -0
- data/spec/reacto/trackable/flatten_labeled_spec.rb +48 -0
- data/spec/reacto/trackable/grep_spec.rb +29 -0
- data/spec/reacto/trackable/grep_v_spec.rb +23 -0
- data/spec/reacto/trackable/{label_spec.rb → group_by_label_spec.rb} +4 -11
- data/spec/reacto/trackable/include_spec.rb +23 -0
- data/spec/reacto/trackable/inject_spec.rb +30 -4
- data/spec/reacto/trackable/lift_spec.rb +1 -3
- data/spec/reacto/trackable/map_spec.rb +17 -3
- data/spec/reacto/trackable/max_by_spec.rb +12 -0
- data/spec/reacto/trackable/max_spec.rb +19 -0
- data/spec/reacto/trackable/merge_spec.rb +6 -7
- data/spec/reacto/trackable/min_by_spec.rb +12 -0
- data/spec/reacto/trackable/min_spec.rb +19 -0
- data/spec/reacto/trackable/minmax_by_spec.rb +12 -0
- data/spec/reacto/trackable/minmax_spec.rb +19 -0
- data/spec/reacto/trackable/none_spec.rb +38 -0
- data/spec/reacto/trackable/on_spec.rb +11 -4
- data/spec/reacto/trackable/one_spec.rb +38 -0
- data/spec/reacto/trackable/partition_spec.rb +23 -0
- data/spec/reacto/trackable/prepend_spec.rb +1 -3
- data/spec/reacto/trackable/reject_spec.rb +21 -0
- data/spec/reacto/trackable/rescue_and_replace_error_spec.rb +48 -0
- data/spec/reacto/trackable/rescue_and_replace_error_with_spec.rb +26 -0
- data/spec/reacto/trackable/retry_spec.rb +50 -0
- data/spec/reacto/trackable/retry_when_spec.rb +33 -0
- data/spec/reacto/trackable/select_spec.rb +18 -7
- data/spec/reacto/trackable/slice_after_spec.rb +38 -0
- data/spec/reacto/trackable/slice_before_spec.rb +38 -0
- data/spec/reacto/trackable/slice_when_spec.rb +26 -0
- data/spec/reacto/trackable/sort_by_spec.rb +16 -0
- data/spec/reacto/trackable/sort_spec.rb +23 -0
- data/spec/reacto/trackable/split_labeled_spec.rb +37 -0
- data/spec/reacto/trackable/take_while_spec.rb +16 -0
- data/spec/reacto/trackable/throttle_spec.rb +2 -3
- data/spec/reacto/trackable/track_on_spec.rb +2 -3
- data/spec/reacto/trackable/uniq_spec.rb +2 -4
- data/spec/support/helpers.rb +9 -1
- metadata +135 -25
- data/Gemfile.lock +0 -32
- data/lib/reacto/operations/cache.rb +0 -53
- data/spec/reacto/trackable/cache_spec.rb +0 -64
@@ -10,15 +10,16 @@ module Reacto
|
|
10
10
|
end
|
11
11
|
|
12
12
|
@how_many_to_drop = how_many_to_drop
|
13
|
-
@dropped = 0
|
14
13
|
@offset = offset
|
15
14
|
end
|
16
15
|
|
17
16
|
def call(tracker)
|
18
|
-
|
19
|
-
@dropped += 1
|
17
|
+
dropped = 0
|
20
18
|
|
21
|
-
|
19
|
+
behaviour = -> (value) do
|
20
|
+
dropped += 1
|
21
|
+
|
22
|
+
if dropped > @how_many_to_drop
|
22
23
|
if @offset != NO_VALUE
|
23
24
|
if @offset <= 0
|
24
25
|
tracker.on_close
|
@@ -31,10 +32,7 @@ module Reacto
|
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
34
|
-
Subscriptions::OperationSubscription.new(
|
35
|
-
tracker,
|
36
|
-
value: behaviour
|
37
|
-
)
|
35
|
+
Subscriptions::OperationSubscription.new(tracker, value: behaviour)
|
38
36
|
end
|
39
37
|
end
|
40
38
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class DropWhile
|
6
|
+
def initialize(predicate)
|
7
|
+
@predicate = predicate
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(tracker)
|
11
|
+
done = false
|
12
|
+
|
13
|
+
behaviour = -> (value) do
|
14
|
+
done = !@predicate.call(value) unless done
|
15
|
+
|
16
|
+
tracker.on_value(value) if done
|
17
|
+
end
|
18
|
+
|
19
|
+
Subscriptions::OperationSubscription.new(tracker, value: behaviour)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'reacto/constants'
|
2
|
+
require 'reacto/subscriptions/operation_subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Operations
|
6
|
+
class EachCollect
|
7
|
+
def initialize(
|
8
|
+
n,
|
9
|
+
reset_action: -> (_) { [] }, collect_action: nil,
|
10
|
+
init_action: NO_ACTION, on_error: nil, on_close: nil
|
11
|
+
)
|
12
|
+
@n = n
|
13
|
+
@reset_action = reset_action
|
14
|
+
@collect_action = collect_action
|
15
|
+
@init_action = init_action
|
16
|
+
|
17
|
+
@error = on_error
|
18
|
+
@close = on_close
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(tracker)
|
22
|
+
current = []
|
23
|
+
@init_action.call
|
24
|
+
|
25
|
+
unless @collect_action
|
26
|
+
@collect_action = -> (value, collection) { collection << value }
|
27
|
+
end
|
28
|
+
|
29
|
+
error = @error ? @error : ->(e) do
|
30
|
+
tracker.on_value(current) unless current.empty?
|
31
|
+
tracker.on_error(e)
|
32
|
+
end
|
33
|
+
close = @close ? @close : ->() do
|
34
|
+
tracker.on_value(current) unless current.empty?
|
35
|
+
tracker.on_close
|
36
|
+
end
|
37
|
+
|
38
|
+
error = error == NO_ACTION ? tracker.method(:on_error) : error
|
39
|
+
close = close == NO_ACTION ? tracker.method(:on_close) : close
|
40
|
+
|
41
|
+
behaviour = -> (value) do
|
42
|
+
@collect_action.call(value, current)
|
43
|
+
|
44
|
+
if current.size == @n
|
45
|
+
tracker.on_value(current)
|
46
|
+
|
47
|
+
current = @reset_action.call(current)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
Subscriptions::OperationSubscription.new(
|
52
|
+
tracker, value: behaviour, error: error, close: close
|
53
|
+
)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class EachWithObject
|
6
|
+
def initialize(action, obj)
|
7
|
+
@action = action
|
8
|
+
@obj = obj
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(tracker)
|
12
|
+
memo = @obj
|
13
|
+
|
14
|
+
close = -> () do
|
15
|
+
tracker.on_value(memo)
|
16
|
+
tracker.on_close
|
17
|
+
end
|
18
|
+
|
19
|
+
error = -> (e) do
|
20
|
+
tracker.on_value(memo)
|
21
|
+
tracker.on_error(e)
|
22
|
+
end
|
23
|
+
|
24
|
+
Subscriptions::OperationSubscription.new(
|
25
|
+
tracker,
|
26
|
+
value: -> (v) { @action.call(v, memo) }, error: error, close: close
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class Extremums
|
6
|
+
AVAILABLE_TYPES = %i(min max minmax)
|
7
|
+
|
8
|
+
def initialize(action: nil, by: nil, type: :max)
|
9
|
+
unless AVAILABLE_TYPES.include?(type)
|
10
|
+
raise ArgumentError.new(
|
11
|
+
"Type not supported, expecting one of #{AVAILABLE_TYPES.join(', ')}"
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
@action = action
|
16
|
+
@by = by
|
17
|
+
@type = type
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(tracker)
|
21
|
+
buffer = []
|
22
|
+
|
23
|
+
behaviour = -> (v) do
|
24
|
+
buffer << v
|
25
|
+
end
|
26
|
+
|
27
|
+
error = -> (e) do
|
28
|
+
emit_values(tracker, buffer)
|
29
|
+
tracker.on_error(e)
|
30
|
+
end
|
31
|
+
|
32
|
+
close = -> () do
|
33
|
+
emit_values(tracker, buffer)
|
34
|
+
tracker.on_close
|
35
|
+
end
|
36
|
+
|
37
|
+
Subscriptions::OperationSubscription.new(
|
38
|
+
tracker, error: error, value: behaviour, close: close
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def emit_values(tracker, buffer)
|
43
|
+
values =
|
44
|
+
if @by
|
45
|
+
buffer.send("#{@type.to_s}_by", &@by)
|
46
|
+
else
|
47
|
+
buffer.send(@type, &@action)
|
48
|
+
end
|
49
|
+
|
50
|
+
Array(values).each { |val| tracker.on_value(val) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class FindIndex
|
6
|
+
def initialize(predicate)
|
7
|
+
@predicate = predicate
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(tracker)
|
11
|
+
index = 0
|
12
|
+
|
13
|
+
behaviour = -> (value) do
|
14
|
+
found = @predicate.call(value)
|
15
|
+
|
16
|
+
if found
|
17
|
+
tracker.on_value(index)
|
18
|
+
tracker.on_close
|
19
|
+
else
|
20
|
+
index += 1
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Subscriptions::OperationSubscription.new(tracker, value: behaviour)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -10,13 +10,13 @@ module Reacto
|
|
10
10
|
|
11
11
|
def call(tracker)
|
12
12
|
subscription = Subscriptions::FlatMapSubscription.new(tracker)
|
13
|
-
value =
|
13
|
+
value = ->(v) do
|
14
14
|
trackable = @transform.call(v)
|
15
15
|
|
16
16
|
trackable.do_track subscription.subscription!
|
17
17
|
end
|
18
18
|
|
19
|
-
close =
|
19
|
+
close = ->() do
|
20
20
|
subscription.source_closed = true
|
21
21
|
return unless subscription.closed?
|
22
22
|
|
@@ -3,9 +3,8 @@ require 'reacto/subscriptions/operation_subscription'
|
|
3
3
|
module Reacto
|
4
4
|
module Operations
|
5
5
|
class Flatten
|
6
|
-
|
7
6
|
def call(tracker)
|
8
|
-
behaviour =
|
7
|
+
behaviour = -> (value) do
|
9
8
|
if value.kind_of?(Array)
|
10
9
|
value.flatten.each do |sub_value|
|
11
10
|
tracker.on_value(sub_value)
|
@@ -15,12 +14,8 @@ module Reacto
|
|
15
14
|
end
|
16
15
|
end
|
17
16
|
|
18
|
-
Subscriptions::OperationSubscription.new(
|
19
|
-
tracker,
|
20
|
-
value: behaviour
|
21
|
-
)
|
17
|
+
Subscriptions::OperationSubscription.new(tracker, value: behaviour)
|
22
18
|
end
|
23
19
|
end
|
24
20
|
end
|
25
21
|
end
|
26
|
-
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
require 'reacto/constants'
|
4
|
+
require 'reacto/subscriptions/operation_subscription'
|
5
|
+
|
6
|
+
module Reacto
|
7
|
+
module Operations
|
8
|
+
class FlattenLabeled
|
9
|
+
def initialize(accumulator = nil, initial = NO_VALUE)
|
10
|
+
@accumulator = accumulator
|
11
|
+
@initial = initial
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(tracker)
|
15
|
+
value = -> (v) do
|
16
|
+
unless v.is_a?(LabeledTrackable)
|
17
|
+
tracker.on_error(ArgumentError.new(
|
18
|
+
'Trackable#flatten_labeled expects all values emitted by the ' \
|
19
|
+
'source Trackable to be LabeledTrackable instances.'
|
20
|
+
))
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
labeled_trackable =
|
25
|
+
if @accumulator.nil?
|
26
|
+
v.first
|
27
|
+
else
|
28
|
+
v.inject(@initial, &@accumulator).last
|
29
|
+
end
|
30
|
+
|
31
|
+
accumulated = []
|
32
|
+
labeled_trackable.on(value: ->(val) { accumulated << val })
|
33
|
+
tracker.on_value(
|
34
|
+
OpenStruct.new({ label: v.label, value: accumulated.first })
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
Subscriptions::OperationSubscription.new(
|
39
|
+
tracker, value: value
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'reacto/constants'
|
2
|
+
require 'reacto/subscriptions/operation_subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Operations
|
6
|
+
class Include
|
7
|
+
def initialize(value)
|
8
|
+
@value = value
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(tracker)
|
12
|
+
includes = false
|
13
|
+
|
14
|
+
behaviour = -> (val) do
|
15
|
+
if @value == val
|
16
|
+
includes = true
|
17
|
+
|
18
|
+
tracker.on_value(includes)
|
19
|
+
tracker.on_close
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
close = -> () do
|
24
|
+
tracker.on_value(includes) unless includes
|
25
|
+
tracker.on_close
|
26
|
+
end
|
27
|
+
|
28
|
+
error = -> (e) do
|
29
|
+
tracker.on_value(includes) unless includes
|
30
|
+
tracker.on_error(e)
|
31
|
+
end
|
32
|
+
|
33
|
+
Subscriptions::OperationSubscription.new(
|
34
|
+
tracker, value: behaviour, error: error, close: close
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
@@ -4,15 +4,16 @@ require 'reacto/subscriptions/operation_subscription'
|
|
4
4
|
module Reacto
|
5
5
|
module Operations
|
6
6
|
class Inject
|
7
|
-
|
8
7
|
def initialize(injector, initial = NO_VALUE)
|
9
8
|
@injector = injector
|
10
|
-
@
|
11
|
-
@has_values = false
|
9
|
+
@initial = initial
|
12
10
|
end
|
13
11
|
|
14
12
|
def call(tracker)
|
15
|
-
|
13
|
+
@current = @initial
|
14
|
+
@has_values = false
|
15
|
+
|
16
|
+
inject = -> (v) do
|
16
17
|
if @current == NO_VALUE
|
17
18
|
@current = v
|
18
19
|
else
|
@@ -23,7 +24,7 @@ module Reacto
|
|
23
24
|
tracker.on_value(@current)
|
24
25
|
end
|
25
26
|
|
26
|
-
close =
|
27
|
+
close = -> () do
|
27
28
|
unless @has_values || @current == NO_VALUE
|
28
29
|
tracker.on_value(@current)
|
29
30
|
end
|
@@ -31,13 +32,18 @@ module Reacto
|
|
31
32
|
tracker.on_close
|
32
33
|
end
|
33
34
|
|
35
|
+
error = -> (e) do
|
36
|
+
unless @has_values || @current == NO_VALUE
|
37
|
+
tracker.on_value(@current)
|
38
|
+
end
|
39
|
+
|
40
|
+
tracker.on_error(e)
|
41
|
+
end
|
42
|
+
|
34
43
|
Subscriptions::OperationSubscription.new(
|
35
|
-
tracker,
|
36
|
-
value: inject,
|
37
|
-
close: close
|
44
|
+
tracker, value: inject, close: close, error: error
|
38
45
|
)
|
39
46
|
end
|
40
47
|
end
|
41
48
|
end
|
42
49
|
end
|
43
|
-
|
@@ -11,20 +11,22 @@ module Reacto
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def call(tracker)
|
14
|
-
error =
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
error =
|
15
|
+
if @error
|
16
|
+
-> (e) { tracker.on_error(@error.call(e)) }
|
17
|
+
else
|
18
|
+
tracker.method(:on_error)
|
19
|
+
end
|
19
20
|
|
20
|
-
close =
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
close =
|
22
|
+
if @close
|
23
|
+
-> () do
|
24
|
+
tracker.on_value(@close.call)
|
25
|
+
tracker.on_close
|
26
|
+
end
|
27
|
+
else
|
28
|
+
tracker.method(:on_close)
|
29
|
+
end
|
28
30
|
|
29
31
|
Subscriptions::OperationSubscription.new(
|
30
32
|
tracker,
|