concurrent_rails 0.3.0 → 0.3.1
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/lib/concurrent_rails/delay_adapter.rb +14 -12
- data/lib/concurrent_rails/future.rb +32 -30
- data/lib/concurrent_rails/future_adapter.rb +14 -12
- data/lib/concurrent_rails/multi.rb +36 -34
- data/lib/concurrent_rails/promises.rb +53 -51
- data/lib/concurrent_rails/railtie.rb +3 -1
- data/lib/concurrent_rails/testing.rb +28 -26
- data/lib/concurrent_rails/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9d92e4343775ab47bf053ce94e272124a6b703e4bfb087483c0ff6aa45257744
|
4
|
+
data.tar.gz: 43c84651bafee307b178694a5a3113d9e21d1a8c6995daccc8ffee5963e62170
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23726c05ee5c47a4cdfa911ae6ff537b87bb72c70cf71cb0ede046682951405c14a0d960dccd4dae0d79921fad335013f0a2afd5ca12b1f949030bdfa1cf983f
|
7
|
+
data.tar.gz: 7b40732c370731530f7295d4f9cb4f40ef7f50c07d9ff3a11e17e9101d78622c5005750d1894b78244536c34fcc87266ab81c31283230ef670948d1ca09b7d3e
|
@@ -1,21 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module ConcurrentRails
|
4
|
-
|
3
|
+
module ConcurrentRails
|
4
|
+
module DelayAdapter
|
5
|
+
extend ActiveSupport::Concern
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
class_methods do
|
8
|
+
def delay(*args, &task)
|
9
|
+
delay_on(:io, *args, &task)
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
def delay_on(executor, *args, &task)
|
13
|
+
new(executor).delay_on_rails(*args, &task)
|
14
|
+
end
|
13
15
|
end
|
14
|
-
end
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
def delay_on_rails(*args, &task)
|
18
|
+
@instance = rails_wrapped { delay_on(executor, *args, &task) }
|
18
19
|
|
19
|
-
|
20
|
+
self
|
21
|
+
end
|
20
22
|
end
|
21
23
|
end
|
@@ -1,47 +1,49 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
module ConcurrentRails
|
4
|
+
class Future
|
5
|
+
def initialize(executor: :io, &block)
|
6
|
+
@executor = executor
|
7
|
+
@future = run_on_rails(block)
|
8
|
+
ActiveSupport::Deprecation.warn('ConcurrentRails::Future is deprecated. See README for details')
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
def execute
|
12
|
+
future.execute
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
self
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
%i[value value!].each do |method_name|
|
18
|
+
define_method method_name do
|
19
|
+
permit_concurrent_loads do
|
20
|
+
future.__send__(method_name)
|
21
|
+
end
|
20
22
|
end
|
21
23
|
end
|
22
|
-
end
|
23
24
|
|
24
|
-
|
25
|
+
delegate :state, :reason, :rejected?, :complete?, :add_observer, to: :future
|
25
26
|
|
26
|
-
|
27
|
+
private
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
def run_on_rails(block)
|
30
|
+
@future = rails_wrapped do
|
31
|
+
Concurrent::Future.new(executor: executor) do
|
32
|
+
rails_wrapped(&block)
|
33
|
+
end
|
32
34
|
end
|
33
35
|
end
|
34
|
-
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
def rails_wrapped(&block)
|
38
|
+
Rails.application.executor.wrap(&block)
|
39
|
+
end
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
def permit_concurrent_loads(&block)
|
42
|
+
rails_wrapped do
|
43
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads(&block)
|
44
|
+
end
|
43
45
|
end
|
44
|
-
end
|
45
46
|
|
46
|
-
|
47
|
+
attr_reader :executor, :future
|
48
|
+
end
|
47
49
|
end
|
@@ -1,21 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module ConcurrentRails
|
4
|
-
|
3
|
+
module ConcurrentRails
|
4
|
+
module FutureAdapter
|
5
|
+
extend ActiveSupport::Concern
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
class_methods do
|
8
|
+
def future(*args, &task)
|
9
|
+
future_on(:io, *args, &task)
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
def future_on(executor, *args, &task)
|
13
|
+
new(executor).future_on_rails(*args, &task)
|
14
|
+
end
|
13
15
|
end
|
14
|
-
end
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
def future_on_rails(*args, &task)
|
18
|
+
@instance = rails_wrapped { future_on(executor, *args, &task) }
|
18
19
|
|
19
|
-
|
20
|
+
self
|
21
|
+
end
|
20
22
|
end
|
21
23
|
end
|
@@ -1,49 +1,51 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
module ConcurrentRails
|
4
|
+
class Multi
|
5
|
+
def self.enqueue(*actions, executor: :io)
|
6
|
+
raise ArgumentError, '#enqueue accepts `Proc`s only' unless actions.all?(Proc)
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
new(actions, executor).enqueue
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def initialize(actions, executor)
|
12
|
+
@actions = actions
|
13
|
+
@executor = executor
|
14
|
+
@exceptions = Concurrent::Array.new
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
def enqueue
|
18
|
+
@futures = actions.map do |action|
|
19
|
+
f = ConcurrentRails::Future.new(executor: executor, &action)
|
20
|
+
f.add_observer(self)
|
21
|
+
f.execute
|
22
|
+
end
|
23
|
+
|
24
|
+
self
|
21
25
|
end
|
22
26
|
|
23
|
-
|
24
|
-
|
27
|
+
def compute
|
28
|
+
futures.map(&:value)
|
29
|
+
end
|
25
30
|
|
26
|
-
|
27
|
-
|
28
|
-
|
31
|
+
def compute!
|
32
|
+
futures.map(&:value!)
|
33
|
+
end
|
29
34
|
|
30
|
-
|
31
|
-
|
32
|
-
|
35
|
+
def complete?
|
36
|
+
futures.all?(&:complete?)
|
37
|
+
end
|
33
38
|
|
34
|
-
|
35
|
-
|
36
|
-
|
39
|
+
def errors
|
40
|
+
@exceptions
|
41
|
+
end
|
37
42
|
|
38
|
-
|
39
|
-
@exceptions
|
40
|
-
end
|
43
|
+
private
|
41
44
|
|
42
|
-
|
45
|
+
def update(_time, _value, reason)
|
46
|
+
@exceptions << reason if reason
|
47
|
+
end
|
43
48
|
|
44
|
-
|
45
|
-
@exceptions << reason if reason
|
49
|
+
attr_reader :actions, :futures, :exceptions, :executor
|
46
50
|
end
|
47
|
-
|
48
|
-
attr_reader :actions, :futures, :exceptions, :executor
|
49
51
|
end
|
@@ -3,79 +3,81 @@
|
|
3
3
|
require 'concurrent_rails/future_adapter'
|
4
4
|
require 'concurrent_rails/delay_adapter'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
module ConcurrentRails
|
7
|
+
class Promises
|
8
|
+
include Concurrent::Promises::FactoryMethods
|
9
|
+
include ConcurrentRails::DelayAdapter
|
10
|
+
include ConcurrentRails::FutureAdapter
|
11
|
+
|
12
|
+
def initialize(executor)
|
13
|
+
@executor = executor
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
%i[value value!].each do |method_name|
|
17
|
+
define_method(method_name) do |timeout = nil, timeout_value = nil|
|
18
|
+
permit_concurrent_loads do
|
19
|
+
instance.public_send(method_name, timeout, timeout_value)
|
20
|
+
end
|
19
21
|
end
|
20
22
|
end
|
21
|
-
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
%i[then chain].each do |chainable|
|
25
|
+
define_method(chainable) do |*args, &task|
|
26
|
+
method = "#{chainable}_on"
|
27
|
+
@instance = rails_wrapped do
|
28
|
+
instance.public_send(method, executor, *args, &task)
|
29
|
+
end
|
30
|
+
|
31
|
+
self
|
28
32
|
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def touch
|
36
|
+
@instance = rails_wrapped { instance.touch }
|
29
37
|
|
30
38
|
self
|
31
39
|
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def touch
|
35
|
-
@instance = rails_wrapped { instance.touch }
|
36
40
|
|
37
|
-
|
38
|
-
|
41
|
+
def wait(timeout = nil)
|
42
|
+
result = permit_concurrent_loads { instance.__send__(:wait_until_resolved, timeout) }
|
39
43
|
|
40
|
-
|
41
|
-
|
44
|
+
timeout ? result : self
|
45
|
+
end
|
42
46
|
|
43
|
-
|
44
|
-
|
47
|
+
%i[on_fulfillment on_rejection on_resolution].each do |method|
|
48
|
+
define_method(method) do |*args, &callback_task|
|
49
|
+
rails_wrapped do
|
50
|
+
@instance = instance.__send__("#{method}_using", executor, *args, &callback_task)
|
51
|
+
end
|
45
52
|
|
46
|
-
|
47
|
-
define_method(method) do |*args, &callback_task|
|
48
|
-
rails_wrapped do
|
49
|
-
@instance = instance.__send__("#{method}_using", executor, *args, &callback_task)
|
53
|
+
self
|
50
54
|
end
|
51
55
|
|
52
|
-
|
53
|
-
|
56
|
+
define_method("#{method}!") do |*args, &callback_task|
|
57
|
+
rails_wrapped do
|
58
|
+
@instance = instance.__send__(:add_callback, "callback_#{method}", args, callback_task)
|
59
|
+
end
|
54
60
|
|
55
|
-
|
56
|
-
rails_wrapped do
|
57
|
-
@instance = instance.__send__(:add_callback, "callback_#{method}", args, callback_task)
|
61
|
+
self
|
58
62
|
end
|
59
|
-
|
60
|
-
self
|
61
63
|
end
|
62
|
-
end
|
63
64
|
|
64
|
-
|
65
|
+
delegate :state, :reason, :rejected?, :resolved?, :fulfilled?, to: :instance
|
65
66
|
|
66
|
-
|
67
|
+
attr_reader :executor
|
67
68
|
|
68
|
-
|
69
|
+
private
|
69
70
|
|
70
|
-
|
71
|
-
|
72
|
-
|
71
|
+
def rails_wrapped(&block)
|
72
|
+
Rails.application.executor.wrap(&block)
|
73
|
+
end
|
73
74
|
|
74
|
-
|
75
|
-
|
76
|
-
|
75
|
+
def permit_concurrent_loads(&block)
|
76
|
+
rails_wrapped do
|
77
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads(&block)
|
78
|
+
end
|
77
79
|
end
|
78
|
-
end
|
79
80
|
|
80
|
-
|
81
|
+
attr_reader :instance
|
82
|
+
end
|
81
83
|
end
|
@@ -1,39 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
class
|
5
|
-
|
3
|
+
module ConcurrentRails
|
4
|
+
class Testing
|
5
|
+
class << self
|
6
|
+
attr_reader :execution_mode
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
%w[immediate fake real].each do |test_mode|
|
9
|
+
define_method(test_mode) do |&task|
|
10
|
+
@execution_mode = test_mode
|
11
|
+
result = task.call
|
12
|
+
@execution_mode = :real
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
result
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
define_method("#{test_mode}!") do
|
18
|
+
@execution_mode = test_mode
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
define_method("#{test_mode}?") do
|
22
|
+
execution_mode == test_mode
|
23
|
+
end
|
22
24
|
end
|
23
25
|
end
|
24
|
-
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
module TestingFuture
|
28
|
+
def future(*args, &task)
|
29
|
+
if ConcurrentRails::Testing.immediate?
|
30
|
+
future_on(:immediate, *args, &task)
|
31
|
+
elsif ConcurrentRails::Testing.fake?
|
32
|
+
yield
|
33
|
+
else
|
34
|
+
super
|
35
|
+
end
|
34
36
|
end
|
35
37
|
end
|
36
|
-
end
|
37
38
|
|
38
|
-
|
39
|
+
ConcurrentRails::Promises.extend(TestingFuture)
|
40
|
+
end
|
39
41
|
end
|