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
@@ -1,31 +1,35 @@
|
|
1
|
+
require 'concurrent'
|
1
2
|
require 'reacto/subscriptions/operation_subscription'
|
2
3
|
|
3
4
|
module Reacto
|
4
5
|
module Operations
|
5
6
|
class Merge
|
6
|
-
def initialize(
|
7
|
-
@
|
8
|
-
|
7
|
+
def initialize(trackables, delay_error: false)
|
8
|
+
@trackables = trackables
|
9
|
+
|
10
|
+
@close_notifications =
|
11
|
+
Concurrent::AtomicFixnum.new(@trackables.size + 1)
|
9
12
|
@lock = Mutex.new
|
10
13
|
@delay_error = delay_error
|
11
14
|
end
|
12
15
|
|
13
16
|
def call(tracker)
|
14
|
-
|
17
|
+
error = nil
|
18
|
+
|
19
|
+
close = -> () do
|
15
20
|
@lock.synchronize do
|
16
|
-
@close_notifications
|
17
|
-
|
18
|
-
@error.nil? ? tracker.on_close : tracker.on_error(@error)
|
21
|
+
if @close_notifications.decrement == 0
|
22
|
+
error.nil? ? tracker.on_close : tracker.on_error(error)
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
26
|
+
|
22
27
|
err =
|
23
28
|
if @delay_error
|
24
|
-
|
29
|
+
-> (er) do
|
25
30
|
@lock.synchronize do
|
26
|
-
|
27
|
-
@close_notifications
|
28
|
-
tracker.on_error(@error) if @close_notifications == 0
|
31
|
+
error = er
|
32
|
+
tracker.on_error(error) if @close_notifications.decrement == 0
|
29
33
|
end
|
30
34
|
end
|
31
35
|
else
|
@@ -33,15 +37,12 @@ module Reacto
|
|
33
37
|
end
|
34
38
|
|
35
39
|
sub = Subscriptions::OperationSubscription.new(
|
36
|
-
tracker,
|
37
|
-
close: close,
|
38
|
-
error: err
|
40
|
+
tracker, close: close, error: err
|
39
41
|
)
|
40
42
|
|
41
|
-
@trackable.send(:do_track, sub)
|
43
|
+
@trackables.each { |trackable| trackable.send(:do_track, sub) }
|
42
44
|
sub
|
43
45
|
end
|
44
46
|
end
|
45
47
|
end
|
46
48
|
end
|
47
|
-
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class OperationOnLabeled
|
6
|
+
def initialize(label, action, op: :map, **args)
|
7
|
+
@op = op
|
8
|
+
@action = action
|
9
|
+
@label = label
|
10
|
+
@args = args
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(tracker)
|
14
|
+
value = -> (v) do
|
15
|
+
to_emit =
|
16
|
+
if v.is_a?(LabeledTrackable) && v.label == @label
|
17
|
+
v.send(@op, **@args, &@action)
|
18
|
+
else
|
19
|
+
v
|
20
|
+
end
|
21
|
+
|
22
|
+
tracker.on_value(to_emit)
|
23
|
+
end
|
24
|
+
|
25
|
+
Subscriptions::OperationSubscription.new(tracker, value: value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'reacto/behaviours'
|
2
|
+
require 'reacto/subscriptions/operation_subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Operations
|
6
|
+
class Partition
|
7
|
+
def initialize(predicate, executor: nil)
|
8
|
+
@predicate = predicate
|
9
|
+
@executor = executor
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(tracker)
|
13
|
+
true_array = []
|
14
|
+
false_array = []
|
15
|
+
|
16
|
+
behavior = -> (val) do
|
17
|
+
if @predicate.call(val)
|
18
|
+
true_array << val
|
19
|
+
else
|
20
|
+
false_array << val
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
error = -> (e) do
|
25
|
+
emit_trackables(tracker, true_array, false_array)
|
26
|
+
tracker.on_error(e)
|
27
|
+
end
|
28
|
+
|
29
|
+
close = -> () do
|
30
|
+
emit_trackables(tracker, true_array, false_array)
|
31
|
+
tracker.on_close
|
32
|
+
end
|
33
|
+
|
34
|
+
Subscriptions::OperationSubscription.new(
|
35
|
+
tracker, value: behavior, error: error, close: close
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def emit_trackables(tracker, true_array, false_array)
|
40
|
+
true_trackable = LabeledTrackable.new(
|
41
|
+
true, @executor, &Behaviours.enumerable(true_array)
|
42
|
+
)
|
43
|
+
false_trackable = LabeledTrackable.new(
|
44
|
+
false, @executor, &Behaviours.enumerable(false_array)
|
45
|
+
)
|
46
|
+
|
47
|
+
tracker.on_value(true_trackable)
|
48
|
+
tracker.on_value(false_trackable)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class RescueAndReplaceError
|
6
|
+
def initialize(action)
|
7
|
+
@action = action
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(tracker)
|
11
|
+
error = -> (e) do
|
12
|
+
trackable = @action.call(e)
|
13
|
+
|
14
|
+
trackable.send(:do_track, tracker)
|
15
|
+
end
|
16
|
+
|
17
|
+
Subscriptions::OperationSubscription.new(tracker, error: error)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class Retry
|
6
|
+
def initialize(behaviour, retries = 1)
|
7
|
+
@behaviour = behaviour
|
8
|
+
@retries = retries
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(tracker)
|
12
|
+
error = ->(e) do
|
13
|
+
@retries = @retries - 1
|
14
|
+
|
15
|
+
if @retries < 0
|
16
|
+
tracker.on_error(e)
|
17
|
+
else
|
18
|
+
@behaviour.call(self.call(tracker))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Subscriptions::OperationSubscription.new(tracker, error: error)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class RetryWhen
|
6
|
+
def initialize(behaviour, predicate)
|
7
|
+
@behaviour = behaviour
|
8
|
+
@predicate = predicate
|
9
|
+
@retries = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(tracker)
|
13
|
+
@retries[tracker] ||= 0
|
14
|
+
|
15
|
+
error = -> (e) do
|
16
|
+
should_retry = @predicate.call(e, @retries[tracker])
|
17
|
+
|
18
|
+
if should_retry
|
19
|
+
@retries[tracker] += 1
|
20
|
+
@behaviour.call(self.call(tracker))
|
21
|
+
else
|
22
|
+
tracker.on_error(e)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Subscriptions::OperationSubscription.new(tracker, error: error)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -8,18 +8,14 @@ module Reacto
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def call(tracker)
|
11
|
-
|
11
|
+
behaviour = -> (v) do
|
12
12
|
if @filter.call(v)
|
13
13
|
tracker.on_value(v)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
Subscriptions::OperationSubscription.new(
|
18
|
-
tracker,
|
19
|
-
value: on_value
|
20
|
-
)
|
17
|
+
Subscriptions::OperationSubscription.new(tracker, value: behaviour)
|
21
18
|
end
|
22
19
|
end
|
23
20
|
end
|
24
21
|
end
|
25
|
-
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class Slice
|
6
|
+
TYPES = %i(before after)
|
7
|
+
|
8
|
+
def initialize(predicate, type: :after)
|
9
|
+
unless TYPES.include?(type)
|
10
|
+
raise ArgumentError.new(
|
11
|
+
"Type #{type} not supported. " \
|
12
|
+
"Supported types are #{TYPES.join(', ')}"
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
@type = type
|
17
|
+
@predicate = predicate
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(tracker)
|
21
|
+
buffer = []
|
22
|
+
|
23
|
+
behaviour = -> (val) do
|
24
|
+
buffer << val if @type == :after
|
25
|
+
|
26
|
+
if @predicate.call(val)
|
27
|
+
tracker.on_value(Trackable.enumerable(buffer))
|
28
|
+
buffer = []
|
29
|
+
end
|
30
|
+
|
31
|
+
buffer << val if @type == :before
|
32
|
+
end
|
33
|
+
|
34
|
+
error = -> (e) do
|
35
|
+
tracker.on_value(Trackable.enumerable(buffer)) unless buffer.empty?
|
36
|
+
tracker.on_error(e)
|
37
|
+
end
|
38
|
+
|
39
|
+
close = -> () do
|
40
|
+
tracker.on_value(Trackable.enumerable(buffer)) unless buffer.empty?
|
41
|
+
tracker.on_close
|
42
|
+
end
|
43
|
+
|
44
|
+
Subscriptions::OperationSubscription.new(
|
45
|
+
tracker, value: behaviour, error: error, close: close
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'reacto/constants'
|
2
|
+
require 'reacto/subscriptions/operation_subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Operations
|
6
|
+
class SliceWhen
|
7
|
+
def initialize(predicate)
|
8
|
+
@predicate = predicate
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(tracker)
|
12
|
+
previous = NO_VALUE
|
13
|
+
buffer = []
|
14
|
+
|
15
|
+
behaviour = -> (val) do
|
16
|
+
if previous != NO_VALUE && @predicate.call(previous, val)
|
17
|
+
tracker.on_value(Trackable.enumerable(buffer))
|
18
|
+
buffer = []
|
19
|
+
end
|
20
|
+
|
21
|
+
buffer << val
|
22
|
+
previous = val
|
23
|
+
end
|
24
|
+
|
25
|
+
error = -> (e) do
|
26
|
+
tracker.on_value(Trackable.enumerable(buffer)) unless buffer.empty?
|
27
|
+
tracker.on_error(e)
|
28
|
+
end
|
29
|
+
|
30
|
+
close = -> () do
|
31
|
+
tracker.on_value(Trackable.enumerable(buffer)) unless buffer.empty?
|
32
|
+
tracker.on_close
|
33
|
+
end
|
34
|
+
|
35
|
+
Subscriptions::OperationSubscription.new(
|
36
|
+
tracker, value: behaviour, error: error, close: close
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class SplitLabeled
|
6
|
+
def initialize(label, chose_label, executor = nil)
|
7
|
+
@label = label
|
8
|
+
@chose_label = chose_label
|
9
|
+
@executor = executor
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(tracker)
|
13
|
+
value = -> (v) do
|
14
|
+
if v.is_a?(LabeledTrackable) && v.label == @label
|
15
|
+
action = -> (labeled_trackable) do
|
16
|
+
tracker.on_value(labeled_trackable)
|
17
|
+
end
|
18
|
+
|
19
|
+
v.group_by_label(executor: @executor, &@chose_label)
|
20
|
+
.on(value: action)
|
21
|
+
else
|
22
|
+
tracker.on_value(v)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Subscriptions::OperationSubscription.new(
|
27
|
+
tracker, value: value
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -9,30 +9,25 @@ module Reacto
|
|
9
9
|
end
|
10
10
|
|
11
11
|
@how_many_to_take = how_many_to_take
|
12
|
-
@taken = 0
|
13
|
-
@closed = false
|
14
12
|
end
|
15
13
|
|
16
14
|
def call(tracker)
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
taken = 0
|
16
|
+
closed = false
|
17
|
+
|
18
|
+
behaviour = -> (value) do
|
19
|
+
return if closed
|
20
|
+
if taken < @how_many_to_take
|
20
21
|
tracker.on_value(value)
|
21
|
-
|
22
|
+
taken += 1
|
22
23
|
else
|
23
|
-
|
24
|
+
closed = true
|
24
25
|
tracker.on_close
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
28
|
-
Subscriptions::OperationSubscription.new(
|
29
|
-
tracker,
|
30
|
-
value: behaviour
|
31
|
-
)
|
29
|
+
Subscriptions::OperationSubscription.new(tracker, value: behaviour)
|
32
30
|
end
|
33
31
|
end
|
34
32
|
end
|
35
33
|
end
|
36
|
-
|
37
|
-
|
38
|
-
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class TakeWhile
|
6
|
+
def initialize(predicate)
|
7
|
+
@predicate = predicate
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(tracker)
|
11
|
+
closed = false
|
12
|
+
|
13
|
+
behaviour = -> (value) do
|
14
|
+
return if closed
|
15
|
+
|
16
|
+
if @predicate.call(value)
|
17
|
+
tracker.on_value(value)
|
18
|
+
else
|
19
|
+
closed = true
|
20
|
+
tracker.on_close
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Subscriptions::OperationSubscription.new(tracker, value: behaviour)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|