exceptional_synchrony 1.2.0 → 1.4.0.pre.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f13da539398611f0cfabb6439072114ef3904d89028205ee79bd7c17cb439ca
4
- data.tar.gz: 1089857cd4e512dd3717b403163a3f74d53bc2cf0902bd13890fb842c7a9644b
3
+ metadata.gz: 7337c98f6e124b7e27327707ad7996bea893fe5c005ae57627e855ec35c77ff4
4
+ data.tar.gz: 2603dc05990ab4c3f257409382f8fc6453f8e22446a82a1ad9841564b509994e
5
5
  SHA512:
6
- metadata.gz: bb0ce260721a479fe42118cfe78c5e06a45e36801e7d3cc25eb823baeff7693c46071bb07e314e3f51aad2b5ed3d61373219c1015b2f9cc0ff28bd1a116f8bb7
7
- data.tar.gz: 81ed89b82782b3f80494b999efeb3d629834c1a4ab1e9e31ab446e4e7a58da0d915252e6f3e401945e1f2be82c20bc3d1f59e34667805180199ee0c2758f91fd
6
+ metadata.gz: bd0b2894a70161f7162c465aacf315cada6748267d88590bb943d3c68ad382f0ed1b910224738f54b1a1ada219f894b9fd64bcb2f06c7f3b95f0c9b3efb1d218
7
+ data.tar.gz: b9b7c5fde46b71d32651108b855f4396517e32a73915b1e3bc09e258a5bcee678d3946ca3fc6c768eef1deebc0edaa66e4e41898b3a08a6d95e993c0bc12339e
data/CHANGELOG.md CHANGED
@@ -5,10 +5,15 @@ Inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
5
  Note: This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  All notable changes to this project will be documented in this file.
8
- ## [1.1.1] - 2020-05-03
9
- - Replace hobo_support with invoca_utils
10
8
 
11
- [1.1.1]: https://github.com/Invoca/exceptional_synchrony/compare/v1.1.0...v1.1.1
9
+ ## [1.4.0] - UNRELEASED
10
+ ### Added
11
+ - Added `:faraday_adapter` option to `EventMachineProxy#run` with a default of `:em_synchrony`
12
+ so that the reactor does not get blocked when using `Faraday` connections
13
+
14
+ ## [1.3.0] - 2021-02-04
15
+ ### Added
16
+ - Extend `EMP.defer` to have a new keyword argument, `wait_for_result` for the callers to control whether they should should block until the background thread returns. To preserve existing behavior, this option defaults to `true`, so `EMP.defer` will block in order to return the value (or raise an exception) from the deferred block. Callers can pass `wait_for_result: false` if they do not want to block.
12
17
 
13
18
  ## [1.2.0] - 2020-06-02
14
19
  ### Changed
@@ -21,4 +26,9 @@ All notable changes to this project will be documented in this file.
21
26
  We expect that outer edge handler to log the exception chain (the wrapper plus nested `cause` exception(s))
22
27
  and exit the process with a non-0 status code.
23
28
 
29
+ ## [1.1.1] - 2020-05-03
30
+ - Replace hobo_support with invoca_utils
31
+
32
+ [1.3.0]: https://github.com/Invoca/exceptional_synchrony/compare/v1.2.0...v1.3.0
24
33
  [1.2.0]: https://github.com/Invoca/exceptional_synchrony/compare/v1.1.1...v1.2.0
34
+ [1.1.1]: https://github.com/Invoca/exceptional_synchrony/compare/v1.1.0...v1.1.1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- exceptional_synchrony (1.2.0)
4
+ exceptional_synchrony (1.4.0.pre.2)
5
5
  em-http-request
6
6
  em-synchrony
7
7
  eventmachine
@@ -11,48 +11,49 @@ PATH
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- actionmailer (6.0.3.1)
15
- actionpack (= 6.0.3.1)
16
- actionview (= 6.0.3.1)
17
- activejob (= 6.0.3.1)
14
+ actionmailer (6.1.1)
15
+ actionpack (= 6.1.1)
16
+ actionview (= 6.1.1)
17
+ activejob (= 6.1.1)
18
+ activesupport (= 6.1.1)
18
19
  mail (~> 2.5, >= 2.5.4)
19
20
  rails-dom-testing (~> 2.0)
20
- actionpack (6.0.3.1)
21
- actionview (= 6.0.3.1)
22
- activesupport (= 6.0.3.1)
23
- rack (~> 2.0, >= 2.0.8)
21
+ actionpack (6.1.1)
22
+ actionview (= 6.1.1)
23
+ activesupport (= 6.1.1)
24
+ rack (~> 2.0, >= 2.0.9)
24
25
  rack-test (>= 0.6.3)
25
26
  rails-dom-testing (~> 2.0)
26
27
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
27
- actionview (6.0.3.1)
28
- activesupport (= 6.0.3.1)
28
+ actionview (6.1.1)
29
+ activesupport (= 6.1.1)
29
30
  builder (~> 3.1)
30
31
  erubi (~> 1.4)
31
32
  rails-dom-testing (~> 2.0)
32
33
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
33
- activejob (6.0.3.1)
34
- activesupport (= 6.0.3.1)
34
+ activejob (6.1.1)
35
+ activesupport (= 6.1.1)
35
36
  globalid (>= 0.3.6)
36
- activesupport (6.0.3.1)
37
+ activesupport (6.1.1)
37
38
  concurrent-ruby (~> 1.0, >= 1.0.2)
38
- i18n (>= 0.7, < 2)
39
- minitest (~> 5.1)
40
- tzinfo (~> 1.1)
41
- zeitwerk (~> 2.2, >= 2.2.2)
39
+ i18n (>= 1.6, < 2)
40
+ minitest (>= 5.1)
41
+ tzinfo (~> 2.0)
42
+ zeitwerk (~> 2.3)
42
43
  addressable (2.7.0)
43
44
  public_suffix (>= 2.0.2, < 5.0)
44
45
  ansi (1.5.0)
45
46
  builder (3.2.4)
46
47
  coderay (1.1.2)
47
- concurrent-ruby (1.1.6)
48
- contextual_logger (0.8.0)
48
+ concurrent-ruby (1.1.8)
49
+ contextual_logger (0.11.0)
49
50
  activesupport
50
51
  json
51
52
  cookiejar (0.3.3)
52
53
  crack (0.4.3)
53
54
  safe_yaml (~> 1.0.0)
54
55
  crass (1.0.6)
55
- em-http-request (1.1.5)
56
+ em-http-request (1.1.7)
56
57
  addressable (>= 2.3.4)
57
58
  cookiejar (!= 0.3.1)
58
59
  em-socksify (>= 0.3)
@@ -62,9 +63,9 @@ GEM
62
63
  eventmachine (>= 1.0.0.beta.4)
63
64
  em-synchrony (1.0.6)
64
65
  eventmachine (>= 1.0.0.beta.1)
65
- erubi (1.9.0)
66
+ erubi (1.10.0)
66
67
  eventmachine (1.2.7)
67
- exception_handling (2.4.3)
68
+ exception_handling (2.8.1)
68
69
  actionmailer (>= 4.2, < 7.0)
69
70
  actionpack (>= 4.2, < 7.0)
70
71
  activesupport (>= 4.2, < 7.0)
@@ -75,31 +76,33 @@ GEM
75
76
  activesupport (>= 4.2.0)
76
77
  hashdiff (1.0.1)
77
78
  http_parser.rb (0.6.0)
78
- i18n (1.8.2)
79
+ i18n (1.8.8)
79
80
  concurrent-ruby (~> 1.0)
80
- invoca-utils (0.3.0)
81
- json (2.3.0)
82
- loofah (2.5.0)
81
+ invoca-utils (0.4.1)
82
+ json (2.5.1)
83
+ loofah (2.9.0)
83
84
  crass (~> 1.0.2)
84
85
  nokogiri (>= 1.5.9)
85
86
  mail (2.7.1)
86
87
  mini_mime (>= 0.1.1)
87
88
  method_source (1.0.0)
88
89
  mini_mime (1.0.2)
89
- mini_portile2 (2.4.0)
90
+ mini_portile2 (2.5.0)
90
91
  minitest (5.14.0)
91
92
  minitest-reporters (1.4.2)
92
93
  ansi
93
94
  builder
94
95
  minitest (>= 5.0)
95
96
  ruby-progressbar
96
- nokogiri (1.10.9)
97
- mini_portile2 (~> 2.4.0)
97
+ nokogiri (1.11.1)
98
+ mini_portile2 (~> 2.5.0)
99
+ racc (~> 1.4)
98
100
  pry (0.13.1)
99
101
  coderay (~> 1.1)
100
102
  method_source (~> 1.0)
101
103
  public_suffix (4.0.4)
102
- rack (2.2.2)
104
+ racc (1.5.2)
105
+ rack (2.2.3)
103
106
  rack-test (1.1.0)
104
107
  rack (>= 1.0, < 3)
105
108
  rails-dom-testing (2.0.3)
@@ -112,14 +115,13 @@ GEM
112
115
  ruby-progressbar (1.10.1)
113
116
  safe_yaml (1.0.5)
114
117
  thor (1.0.1)
115
- thread_safe (0.3.6)
116
- tzinfo (1.2.7)
117
- thread_safe (~> 0.1)
118
+ tzinfo (2.0.4)
119
+ concurrent-ruby (~> 1.0)
118
120
  webmock (1.24.6)
119
121
  addressable (>= 2.3.6)
120
122
  crack (>= 0.3.2)
121
123
  hashdiff
122
- zeitwerk (2.3.0)
124
+ zeitwerk (2.4.2)
123
125
 
124
126
  PLATFORMS
125
127
  ruby
data/Rakefile CHANGED
@@ -7,6 +7,7 @@ require 'rake/testtask'
7
7
  task default: :test
8
8
 
9
9
  Rake::TestTask.new do |t|
10
+ t.warning = false
10
11
  t.pattern = "test/**/*_test.rb"
11
12
  end
12
13
 
@@ -64,14 +64,24 @@ module ExceptionalSynchrony
64
64
  @proxy_class.next_tick { } #Fake out EventMachine's epoll mechanism so we don't block until timers fire
65
65
  end
66
66
 
67
+ def defers_finished?
68
+ @proxy_class.defers_finished?
69
+ end
70
+
67
71
  def connect(server, port = nil, handler = nil, *args, &block)
68
72
  @proxy_class.connect(server, port, handler, *args, &block)
69
73
  end
70
74
 
75
+ # This method starts the EventMachine reactor.
71
76
  # The on_error option has these possible values:
72
77
  # :log - log any rescued StandardError exceptions and continue
73
78
  # :raise - raise FatalRunError for any rescued StandardError exceptions
74
- def run(on_error: :log, &block)
79
+ # The faraday_adapter option has these possible values that only apply if Faraday connections are in use:
80
+ # :em_synchrony - for use when EM::Synchrony is being used in all threads of the given process
81
+ # :net_http - for use when EM::Synchrony is being used in only some threads of the given process;
82
+ # in this case requests made over the Faraday connection will block the reactor
83
+ def run(on_error: :log, faraday_adapter: :em_synchrony, &block)
84
+ configure_faraday(faraday_adapter)
75
85
  case on_error
76
86
  when :log then run_with_error_logging(&block)
77
87
  when :raise then run_with_error_raising(&block)
@@ -79,16 +89,21 @@ module ExceptionalSynchrony
79
89
  end
80
90
  end
81
91
 
82
- def defer(context, &block)
83
- deferrable = EventMachine::DefaultDeferrable.new
84
-
85
- callback = -> (result) { deferrable.succeed(result) }
86
-
87
- EventMachine.defer(nil, callback) { CallbackExceptions.return_exception(&block) }
88
-
89
- EventMachine::Synchrony.sync(deferrable)
92
+ # This method will execute the block on the background thread pool
93
+ # By default, it will block the caller until the background thread has finished, so that the result can be returned
94
+ # :wait_for_result - setting this to false will prevent the caller from being blocked by this deferred work
95
+ def defer(context, wait_for_result: true, &block)
96
+ if wait_for_result
97
+ deferrable = EventMachine::DefaultDeferrable.new
98
+ callback = -> (result) { deferrable.succeed(result) }
90
99
 
91
- CallbackExceptions.map_deferred_result(deferrable)
100
+ EventMachine.defer(nil, callback) { CallbackExceptions.return_exception(&block) }
101
+ EventMachine::Synchrony.sync(deferrable)
102
+ CallbackExceptions.map_deferred_result(deferrable)
103
+ else
104
+ EventMachine.defer { ExceptionHandling.ensure_completely_safe("defer", &block) }
105
+ nil
106
+ end
92
107
  end
93
108
 
94
109
  def reactor_running?
@@ -124,6 +139,13 @@ module ExceptionalSynchrony
124
139
 
125
140
  private
126
141
 
142
+ def configure_faraday(adapter)
143
+ if defined?(Faraday)
144
+ adapter.in?([:em_synchrony, :net_http]) or raise ArgumentError, "Invalid faraday_adapter: #{adapter.inspect}"
145
+ Faraday.default_adapter = adapter
146
+ end
147
+ end
148
+
127
149
  def run_with_error_logging(&block)
128
150
  ensure_completely_safe("run_with_error_logging") do
129
151
  if @proxy_class.respond_to?(:synchrony)
@@ -1,3 +1,3 @@
1
1
  module ExceptionalSynchrony
2
- VERSION = '1.2.0'
2
+ VERSION = '1.4.0.pre.2'
3
3
  end
@@ -24,6 +24,14 @@ describe ExceptionalSynchrony::EventMachineProxy do
24
24
  end
25
25
  end
26
26
 
27
+ def stop_em_after_defers_finish!(em)
28
+ check_finished_counter = 0
29
+ em.add_periodic_timer(0.1) do
30
+ (check_finished_counter += 1) > 20 and raise "defer never finished!"
31
+ em.defers_finished? and em.stop
32
+ end
33
+ end
34
+
27
35
  before do
28
36
  @em = ExceptionalSynchrony::EventMachineProxy.new(EventMachine, nil)
29
37
  @yielded_value = nil
@@ -78,18 +86,41 @@ describe ExceptionalSynchrony::EventMachineProxy do
78
86
  end
79
87
 
80
88
  describe "#defer" do
81
- it "should output its block's output when it doesn't raise an error" do
82
- ExceptionHandling.logger = Logger.new(STDERR)
89
+ before do
90
+ logger = Logger.new(STDERR)
91
+ logger.extend ContextualLogger::LoggerMixin
92
+ ExceptionHandling.logger = logger
93
+ end
83
94
 
95
+ it "should output its block's output when it doesn't raise an error, by default" do
84
96
  @em.run do
85
97
  assert_equal 12, @em.defer("#defer success") { 12 }
86
98
  @em.stop
87
99
  end
88
100
  end
89
101
 
90
- it "should raise an error when its block raises an error" do
91
- ExceptionHandling.logger = Logger.new(STDERR)
102
+ it "should not wait for its block to run if option is passed" do
103
+ @block_ran = false
104
+
105
+ @em.run do
106
+ assert_nil @em.defer("#defer success", wait_for_result: false) { @block_ran = true; 12 }
107
+ refute @block_ran
108
+ stop_em_after_defers_finish!(@em)
109
+ end
92
110
 
111
+ assert @block_ran
112
+ end
113
+
114
+ it "should handle exceptions when not waiting for its block to run" do
115
+ mock(ExceptionHandling).log_error(is_a(RuntimeError), "defer", {})
116
+
117
+ @em.run do
118
+ assert_nil @em.defer("#defer success", wait_for_result: false) { raise RuntimeError, "error in defer" }
119
+ stop_em_after_defers_finish!(@em)
120
+ end
121
+ end
122
+
123
+ it "should raise an error when its block raises an error" do
93
124
  @em.run do
94
125
  ex = assert_raises(ArgumentError) do
95
126
  @em.defer("#defer raising an error") { raise ArgumentError, "!!!" }
@@ -127,6 +158,42 @@ describe ExceptionalSynchrony::EventMachineProxy do
127
158
  end
128
159
  end
129
160
 
161
+ describe "run with faraday" do
162
+ before do
163
+ class Faraday
164
+ class << self
165
+ attr_reader :default_adapter
166
+
167
+ def default_adapter=(adapter)
168
+ @default_adapter = adapter
169
+ end
170
+ end
171
+
172
+ self.default_adapter = :net_http
173
+ end
174
+
175
+ assert_equal :net_http, Faraday.default_adapter
176
+ end
177
+
178
+ it "sets Faraday default_adapter to :em_synchrony by default if Faraday is defined" do
179
+ mock(@em).run_with_error_logging
180
+ @em.run
181
+ assert_equal :em_synchrony, Faraday.default_adapter
182
+ end
183
+
184
+ it "sets Faraday default_adapter to :net_http if Faraday is defined" do
185
+ mock(@em).run_with_error_logging
186
+ @em.run(faraday_adapter: :net_http)
187
+ assert_equal :net_http, Faraday.default_adapter
188
+ end
189
+
190
+ it "raise ArgumentError if the specified faraday_adapter is invalid" do
191
+ assert_raises(ArgumentError, "Invalid faraday_adapter: :bogus") do
192
+ @em.run(faraday_adapter: :bogus)
193
+ end
194
+ end
195
+ end
196
+
130
197
  { synchrony: SynchronyProxyMock, run: RunProxyMock }.each do |method, proxy_mock|
131
198
  describe "run" do
132
199
  before do
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exceptional_synchrony
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.4.0.pre.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Invoca
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2014-01-16 00:00:00.000000000 Z
@@ -115,7 +115,7 @@ licenses:
115
115
  metadata:
116
116
  source_code_uri: https://github.com/Invoca/exceptional_synchrony
117
117
  allowed_push_host: https://rubygems.org
118
- post_install_message:
118
+ post_install_message:
119
119
  rdoc_options: []
120
120
  require_paths:
121
121
  - lib
@@ -126,12 +126,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
126
126
  version: '0'
127
127
  required_rubygems_version: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ">="
129
+ - - ">"
130
130
  - !ruby/object:Gem::Version
131
- version: '0'
131
+ version: 1.3.1
132
132
  requirements: []
133
133
  rubygems_version: 3.0.3
134
- signing_key:
134
+ signing_key:
135
135
  specification_version: 4
136
136
  summary: Extensions to EventMachine/Synchrony to work well with exceptions
137
137
  test_files: []