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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 00345a7d238aab953495d04d30b70de59a43b452
|
4
|
+
data.tar.gz: bf82a8089e0b732e456c14a8100d8f8ecf260370
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 552be561f5bec4bc6ab3b75f1f814b5d326dbae95328e83334d17811fcc0a23a6259ae946905fed819700a62d2b61d7119d2f378eddc479bc2518def7308194b
|
7
|
+
data.tar.gz: 972a2db20596802f0957760eadf2b58901bcd20d08211f9332ef633fd1f707833a1ca4f0bc4a07b151c0e3bc1bdf4baea8c5b1e813500c8556a01f7541497766
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
reacto (0.0.0)
|
5
|
+
concurrent-ruby (~> 1.0.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
concurrent-ruby (1.0.0)
|
11
|
+
diff-lcs (1.2.5)
|
12
|
+
rspec (3.3.0)
|
13
|
+
rspec-core (~> 3.3.0)
|
14
|
+
rspec-expectations (~> 3.3.0)
|
15
|
+
rspec-mocks (~> 3.3.0)
|
16
|
+
rspec-core (3.3.2)
|
17
|
+
rspec-support (~> 3.3.0)
|
18
|
+
rspec-expectations (3.3.1)
|
19
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
20
|
+
rspec-support (~> 3.3.0)
|
21
|
+
rspec-mocks (3.3.2)
|
22
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
23
|
+
rspec-support (~> 3.3.0)
|
24
|
+
rspec-support (3.3.0)
|
25
|
+
|
26
|
+
PLATFORMS
|
27
|
+
ruby
|
28
|
+
|
29
|
+
DEPENDENCIES
|
30
|
+
bundler (~> 1.3)
|
31
|
+
reacto!
|
32
|
+
rspec (~> 3.3.0)
|
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# reacto
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Reacto
|
2
|
+
module Behaviours
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def with_close_and_error(tracker, &block)
|
6
|
+
begin
|
7
|
+
yield tracker if block_given?
|
8
|
+
tracker.on_close if tracker.subscribed?
|
9
|
+
rescue StandardError => error
|
10
|
+
tracker.on_error(error) if tracker.subscribed?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def single_tracker_value(tracker, value)
|
15
|
+
with_close_and_error(tracker) do |subscriber|
|
16
|
+
subscriber.on_value(value) if subscriber.subscribed?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def single_value(value)
|
21
|
+
lambda do |tracker|
|
22
|
+
with_close_and_error(tracker) do |subscriber|
|
23
|
+
subscriber.on_value(value) if subscriber.subscribed?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def integers_enumerator
|
29
|
+
Enumerator.new do |yielder|
|
30
|
+
n = 0
|
31
|
+
loop do
|
32
|
+
yielder.yield n
|
33
|
+
n = n + 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def array_repeat_enumerator(array)
|
39
|
+
size = array.size
|
40
|
+
|
41
|
+
Enumerator.new do |yielder|
|
42
|
+
n = 0
|
43
|
+
loop do
|
44
|
+
yielder.yield array[n % size]
|
45
|
+
n = n + 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'concurrent/executor/immediate_executor'
|
2
|
+
require 'concurrent/executor/cached_thread_pool'
|
3
|
+
require 'concurrent/executor/fixed_thread_pool'
|
4
|
+
|
5
|
+
module Reacto
|
6
|
+
module Executors
|
7
|
+
class CurrentExecutor
|
8
|
+
def post
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module_function
|
14
|
+
|
15
|
+
def immediate
|
16
|
+
Concurrent::ImmediateExecutor.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def current
|
20
|
+
Concurrent::ImmediateExecutor.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def io
|
24
|
+
Concurrent::CachedThreadPool.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def tasks
|
28
|
+
Concurrent::FixedThreadPool.new(4) # Number of cores here?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
require 'reacto/subscriptions/operation_subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Operations
|
6
|
+
class Buffer
|
7
|
+
def initialize(count: nil, delay: nil)
|
8
|
+
@count = count
|
9
|
+
@delay = delay
|
10
|
+
@buffer = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(tracker)
|
14
|
+
close = lambda do
|
15
|
+
finish(tracker)
|
16
|
+
tracker.on_close
|
17
|
+
end
|
18
|
+
error = lambda do |e|
|
19
|
+
finish(tracker)
|
20
|
+
tracker.on_error(e)
|
21
|
+
end
|
22
|
+
value = if !@count.nil? && @delay.nil?
|
23
|
+
count_buffer_behaviour(tracker)
|
24
|
+
elsif @count.nil? && !@delay.nil?
|
25
|
+
delay_buffer_behaviour(tracker)
|
26
|
+
elsif @count && @delay
|
27
|
+
count_and_delay_buffer_behaviour(tracker)
|
28
|
+
else
|
29
|
+
tracker.method(:on_value)
|
30
|
+
end
|
31
|
+
|
32
|
+
Subscriptions::OperationSubscription.new(
|
33
|
+
tracker,
|
34
|
+
value: value,
|
35
|
+
close: close,
|
36
|
+
error: error
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def finish(tracker)
|
43
|
+
@task.shutdown if @task
|
44
|
+
|
45
|
+
tracker.on_value(@buffer) unless @buffer.empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
def count_buffer_behaviour(tracker)
|
49
|
+
lambda do |value|
|
50
|
+
@buffer << value
|
51
|
+
|
52
|
+
if @buffer.size >= @count
|
53
|
+
tracker.on_value(@buffer)
|
54
|
+
@buffer = []
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def delay_task(tracker)
|
60
|
+
@task = Concurrent::TimerTask.new(execution_interval: @delay) do
|
61
|
+
unless @buffer.empty?
|
62
|
+
tracker.on_value(@buffer)
|
63
|
+
@buffer = []
|
64
|
+
end
|
65
|
+
end
|
66
|
+
@task.execute
|
67
|
+
end
|
68
|
+
|
69
|
+
def delay_buffer_behaviour(tracker)
|
70
|
+
delay_task(tracker)
|
71
|
+
-> (value) { @buffer << value }
|
72
|
+
end
|
73
|
+
|
74
|
+
def count_and_delay_buffer_behaviour(tracker)
|
75
|
+
delay_task(tracker)
|
76
|
+
count_buffer_behaviour(tracker)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class Concat
|
6
|
+
# TODO Continue on error flag!
|
7
|
+
def initialize(trackable)
|
8
|
+
@trackable = trackable
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(tracker)
|
12
|
+
Subscriptions::OperationSubscription.new(
|
13
|
+
tracker,
|
14
|
+
close: -> () { @trackable.send(:do_track, tracker) },
|
15
|
+
error: -> (e) {
|
16
|
+
tracker.on_error(e)
|
17
|
+
@trackable.send(:do_track, tracker)
|
18
|
+
}
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'reacto/constants'
|
2
|
+
require 'reacto/subscriptions/operation_subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Operations
|
6
|
+
class Diff
|
7
|
+
DEFAULT_FN = -> (a, b) { [a, b] }
|
8
|
+
|
9
|
+
def initialize(fn = DEFAULT_FN, initial = NO_VALUE)
|
10
|
+
@fn = fn
|
11
|
+
@prev = initial
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(tracker)
|
15
|
+
value = lambda do |v|
|
16
|
+
if @prev == NO_VALUE
|
17
|
+
@prev = v
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
current = @fn.call(@prev, v)
|
22
|
+
@prev = v
|
23
|
+
|
24
|
+
tracker.on_value(current)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
Subscriptions::OperationSubscription.new(
|
29
|
+
tracker,
|
30
|
+
value: value
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'reacto/constants'
|
2
|
+
require 'reacto/subscriptions/operation_subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Operations
|
6
|
+
class Drop
|
7
|
+
def initialize(how_many_to_drop, offset = NO_VALUE)
|
8
|
+
if how_many_to_drop < 0
|
9
|
+
raise ArgumentError.new('Attempt to drop negative size!')
|
10
|
+
end
|
11
|
+
|
12
|
+
@how_many_to_drop = how_many_to_drop
|
13
|
+
@dropped = 0
|
14
|
+
@offset = offset
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(tracker)
|
18
|
+
behaviour = lambda do |value|
|
19
|
+
@dropped += 1
|
20
|
+
|
21
|
+
if @dropped > @how_many_to_drop
|
22
|
+
if @offset != NO_VALUE
|
23
|
+
if @offset <= 0
|
24
|
+
tracker.on_close
|
25
|
+
return
|
26
|
+
else
|
27
|
+
@offset -= 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
tracker.on_value(value)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Subscriptions::OperationSubscription.new(
|
35
|
+
tracker,
|
36
|
+
value: behaviour
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
require 'reacto/subscriptions/flat_map_subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Operations
|
6
|
+
class FlatMap
|
7
|
+
def initialize(transform)
|
8
|
+
@transform = transform
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(tracker)
|
12
|
+
subscription = Subscriptions::FlatMapSubscription.new(tracker)
|
13
|
+
value = lambda do |v|
|
14
|
+
trackable = @transform.call(v)
|
15
|
+
|
16
|
+
trackable.do_track subscription.subscription!
|
17
|
+
end
|
18
|
+
|
19
|
+
Subscriptions::OperationSubscription.new(
|
20
|
+
tracker, value: value
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class Flatten
|
6
|
+
|
7
|
+
def call(tracker)
|
8
|
+
behaviour = lambda do |value|
|
9
|
+
if value.kind_of?(Array)
|
10
|
+
value.flatten.each do |sub_value|
|
11
|
+
tracker.on_value(sub_value)
|
12
|
+
end
|
13
|
+
else
|
14
|
+
tracker.on_value(value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Subscriptions::OperationSubscription.new(
|
19
|
+
tracker,
|
20
|
+
value: behaviour
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'reacto/constants'
|
2
|
+
require 'reacto/subscriptions/operation_subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Operations
|
6
|
+
class Inject
|
7
|
+
|
8
|
+
def initialize(injector, initial = NO_VALUE)
|
9
|
+
@injector = injector
|
10
|
+
@current = initial
|
11
|
+
@has_values = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(tracker)
|
15
|
+
inject = lambda do |v|
|
16
|
+
if @current == NO_VALUE
|
17
|
+
@current = v
|
18
|
+
else
|
19
|
+
@current = @injector.call(@current, v)
|
20
|
+
end
|
21
|
+
|
22
|
+
@has_values = true
|
23
|
+
tracker.on_value(@current)
|
24
|
+
end
|
25
|
+
|
26
|
+
close = lambda do
|
27
|
+
unless @has_values || @current == NO_VALUE
|
28
|
+
tracker.on_value(@current)
|
29
|
+
end
|
30
|
+
|
31
|
+
tracker.on_close
|
32
|
+
end
|
33
|
+
|
34
|
+
Subscriptions::OperationSubscription.new(
|
35
|
+
tracker,
|
36
|
+
value: inject,
|
37
|
+
close: close
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class Last
|
6
|
+
def initialize
|
7
|
+
@marker = {}
|
8
|
+
@prev = @marker
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(tracker)
|
12
|
+
close = lambda do
|
13
|
+
tracker.on_value(@prev) if @prev != @marker
|
14
|
+
tracker.on_close
|
15
|
+
end
|
16
|
+
error = lambda do |e|
|
17
|
+
tracker.on_value(@prev) if @prev != @marker
|
18
|
+
tracker.on_error(e)
|
19
|
+
end
|
20
|
+
|
21
|
+
Subscriptions::OperationSubscription.new(
|
22
|
+
tracker,
|
23
|
+
value: -> (v) { @prev = v },
|
24
|
+
error: error,
|
25
|
+
close: close
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'reacto/constants'
|
2
|
+
require 'reacto/subscriptions/operation_subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Operations
|
6
|
+
class Map
|
7
|
+
def initialize(mapping, error: nil, close: nil)
|
8
|
+
@mapping = mapping
|
9
|
+
@error = error
|
10
|
+
@close = close
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(tracker)
|
14
|
+
error = if @error
|
15
|
+
-> (e) { tracker.on_error(@error.call(e)) }
|
16
|
+
else
|
17
|
+
tracker.method(:on_error)
|
18
|
+
end
|
19
|
+
|
20
|
+
close = if @close
|
21
|
+
-> () do
|
22
|
+
tracker.on_value(@close.call)
|
23
|
+
tracker.on_close
|
24
|
+
end
|
25
|
+
else
|
26
|
+
tracker.method(:on_close)
|
27
|
+
end
|
28
|
+
|
29
|
+
Subscriptions::OperationSubscription.new(
|
30
|
+
tracker,
|
31
|
+
value: -> (v) { tracker.on_value(@mapping.call(v)) },
|
32
|
+
error: error,
|
33
|
+
close: close
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class Merge
|
6
|
+
def initialize(trackable, delay_error: false)
|
7
|
+
@trackable = trackable
|
8
|
+
@close_notifications = 2
|
9
|
+
@lock = Mutex.new
|
10
|
+
@delay_error = delay_error
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(tracker)
|
14
|
+
close = lambda do
|
15
|
+
@lock.synchronize do
|
16
|
+
@close_notifications -= 1
|
17
|
+
if @close_notifications == 0
|
18
|
+
@error.nil? ? tracker.on_close : tracker.on_error(@error)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
err =
|
23
|
+
if @delay_error
|
24
|
+
lambda do |er|
|
25
|
+
@lock.synchronize do
|
26
|
+
@error = er
|
27
|
+
@close_notifications -= 1
|
28
|
+
tracker.on_error(@error) if @close_notifications == 0
|
29
|
+
end
|
30
|
+
end
|
31
|
+
else
|
32
|
+
tracker.method(:on_error)
|
33
|
+
end
|
34
|
+
|
35
|
+
sub = Subscriptions::OperationSubscription.new(
|
36
|
+
tracker,
|
37
|
+
close: close,
|
38
|
+
error: err
|
39
|
+
)
|
40
|
+
|
41
|
+
@trackable.send(:do_track, sub)
|
42
|
+
sub
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class Prepend
|
6
|
+
attr_reader :enumerable
|
7
|
+
|
8
|
+
def initialize(enumerable)
|
9
|
+
@enumerable = enumerable
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(tracker)
|
13
|
+
enumerable.each { |value| tracker.on_value(value) }
|
14
|
+
tracker
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class Select
|
6
|
+
def initialize(filter)
|
7
|
+
@filter = filter
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(tracker)
|
11
|
+
on_value = lambda do |v|
|
12
|
+
if @filter.call(v)
|
13
|
+
tracker.on_value(v)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Subscriptions::OperationSubscription.new(
|
18
|
+
tracker,
|
19
|
+
value: on_value
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class Take
|
6
|
+
def initialize(how_many_to_take)
|
7
|
+
if how_many_to_take < 0
|
8
|
+
raise ArgumentError.new('Attempt to take negative size!')
|
9
|
+
end
|
10
|
+
|
11
|
+
@how_many_to_take = how_many_to_take
|
12
|
+
@taken = 0
|
13
|
+
@closed = false
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(tracker)
|
17
|
+
behaviour = lambda do |value|
|
18
|
+
return if @closed
|
19
|
+
if @taken < @how_many_to_take
|
20
|
+
tracker.on_value(value)
|
21
|
+
@taken += 1
|
22
|
+
else
|
23
|
+
@closed = true
|
24
|
+
tracker.on_close
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Subscriptions::OperationSubscription.new(
|
29
|
+
tracker,
|
30
|
+
value: behaviour
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
|