protobuf 2.0.0.rc3 → 2.0.0.rc4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/lib/protobuf/cli.rb +1 -2
  2. data/lib/protobuf/{common/exceptions.rb → exceptions.rb} +0 -0
  3. data/lib/protobuf/field/base_field.rb +1 -1
  4. data/lib/protobuf/{common/logger.rb → logger.rb} +21 -0
  5. data/lib/protobuf/message/decoder.rb +2 -2
  6. data/lib/protobuf/message/encoder.rb +6 -4
  7. data/lib/protobuf/rpc/buffer.rb +2 -2
  8. data/lib/protobuf/rpc/client.rb +18 -18
  9. data/lib/protobuf/rpc/connectors/base.rb +3 -8
  10. data/lib/protobuf/rpc/connectors/common.rb +29 -28
  11. data/lib/protobuf/rpc/connectors/em_client.rb +9 -9
  12. data/lib/protobuf/rpc/connectors/eventmachine.rb +11 -9
  13. data/lib/protobuf/rpc/connectors/socket.rb +13 -17
  14. data/lib/protobuf/rpc/connectors/zmq.rb +13 -17
  15. data/lib/protobuf/rpc/error.rb +3 -3
  16. data/lib/protobuf/rpc/server.rb +41 -93
  17. data/lib/protobuf/rpc/servers/evented/server.rb +7 -9
  18. data/lib/protobuf/rpc/servers/evented_runner.rb +0 -11
  19. data/lib/protobuf/rpc/servers/socket/server.rb +8 -7
  20. data/lib/protobuf/rpc/servers/socket/worker.rb +22 -15
  21. data/lib/protobuf/rpc/servers/zmq/server.rb +3 -3
  22. data/lib/protobuf/rpc/servers/zmq/util.rb +1 -1
  23. data/lib/protobuf/rpc/servers/zmq/worker.rb +6 -15
  24. data/lib/protobuf/rpc/service.rb +145 -228
  25. data/lib/protobuf/rpc/service_dispatcher.rb +114 -0
  26. data/lib/protobuf/rpc/stat.rb +46 -33
  27. data/lib/protobuf/version.rb +1 -1
  28. data/lib/protobuf/{common/wire_type.rb → wire_type.rb} +0 -0
  29. data/spec/benchmark/tasks.rb +18 -18
  30. data/spec/functional/evented_server_spec.rb +3 -4
  31. data/spec/functional/socket_server_spec.rb +3 -3
  32. data/spec/functional/zmq_server_spec.rb +3 -3
  33. data/spec/lib/protobuf/{common/logger_spec.rb → logger_spec.rb} +46 -36
  34. data/spec/lib/protobuf/rpc/client_spec.rb +10 -58
  35. data/spec/lib/protobuf/rpc/connectors/base_spec.rb +1 -39
  36. data/spec/lib/protobuf/rpc/connectors/common_spec.rb +3 -6
  37. data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +0 -12
  38. data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +1 -6
  39. data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +94 -0
  40. data/spec/lib/protobuf/rpc/service_spec.rb +132 -45
  41. data/spec/spec_helper.rb +4 -3
  42. data/spec/support/server.rb +8 -4
  43. metadata +41 -35
@@ -1,7 +1,6 @@
1
1
  require 'thor'
2
- require 'pry'
3
2
  require 'protobuf/version'
4
- require 'protobuf/common/logger'
3
+ require 'protobuf/logger'
5
4
  require 'protobuf/rpc/servers/evented_runner'
6
5
  require 'protobuf/rpc/servers/socket_runner'
7
6
  require 'protobuf/rpc/servers/zmq_runner'
@@ -1,4 +1,4 @@
1
- require 'protobuf/common/wire_type'
1
+ require 'protobuf/wire_type'
2
2
  require 'protobuf/field/field_array'
3
3
 
4
4
  module Protobuf
@@ -53,13 +53,34 @@ module Protobuf
53
53
  module LogMethods
54
54
  [:debug, :info, :warn, :error, :fatal, :any, :add, :log].each do |m|
55
55
  define_method("log_#{m}") do |*params, &block|
56
+ params.map! { |message| sign_message(message) }
56
57
  Protobuf::Logger.__send__(m, *params, &block)
57
58
  end
58
59
  end
59
60
 
61
+ # When included, also extend the LogMethods module for class access.
60
62
  def self.included(base)
61
63
  base.extend(LogMethods)
62
64
  end
65
+
66
+ # We often want to log an exception, so let's make that a core
67
+ # concern of the logger.
68
+ #
69
+ def log_exception(ex)
70
+ log_error { ex.message }
71
+ log_error { ex.backtrace[0..5].join("\n") }
72
+ log_debug { ex.backtrace.join("\n") }
73
+ end
74
+
75
+ def log_signature
76
+ @_log_signature ||= "[#{self.class == Class ? self.name : self.class.name}]"
77
+ end
78
+
79
+ def sign_message(message)
80
+ "#{log_signature} #{message}"
81
+ end
82
+
63
83
  end
84
+
64
85
  end
65
86
  end
@@ -1,5 +1,5 @@
1
- require 'protobuf/common/wire_type'
2
- require 'protobuf/common/exceptions'
1
+ require 'protobuf/wire_type'
2
+ require 'protobuf/exceptions'
3
3
 
4
4
  module Protobuf
5
5
 
@@ -1,5 +1,5 @@
1
- require 'protobuf/common/wire_type'
2
- require 'protobuf/common/exceptions'
1
+ require 'protobuf/wire_type'
2
+ require 'protobuf/exceptions'
3
3
 
4
4
  module Protobuf
5
5
 
@@ -10,8 +10,10 @@ module Protobuf
10
10
  # Encode +message+ and write to +stream+.
11
11
  def encode(stream, message)
12
12
  # FIXME make this not as ghetto
13
- raise NotInitializedError, "Message %s is not initialized (one or more fields is improperly set): %s" % [message.class.name, JSON.parse(message.to_json)] unless message.initialized?
14
-
13
+ unless message.initialized?
14
+ raise NotInitializedError, "Message #{message.class.name} is not initialized (one or more fields is improperly set): #{JSON.parse(message.to_json)}"
15
+ end
16
+
15
17
  message.each_field do |field, value|
16
18
  next unless message.has_field?(field.name)
17
19
 
@@ -32,7 +32,7 @@ module Protobuf
32
32
  end
33
33
 
34
34
  @size = @data.length
35
- '%d-%s' % [@size, @data]
35
+ "#{@size}-#{@data}"
36
36
  end
37
37
 
38
38
  def <<(data)
@@ -63,7 +63,7 @@ module Protobuf
63
63
  def get_data_size
64
64
  if @size == 0 || @data.match(SIZE_REGEX)
65
65
  sliced_size = @data.slice!(SIZE_REGEX)
66
- @size = sliced_size.gsub('-', '').to_i unless(sliced_size.nil?)
66
+ @size = sliced_size.gsub('-', '').to_i unless sliced_size.nil?
67
67
  end
68
68
  end
69
69
 
@@ -1,6 +1,6 @@
1
1
  require 'forwardable'
2
2
  require 'protobuf'
3
- require 'protobuf/common/logger'
3
+ require 'protobuf/logger'
4
4
  require 'protobuf/rpc/error'
5
5
  require 'protobuf/rpc/connector'
6
6
 
@@ -10,7 +10,7 @@ module Protobuf
10
10
  extend Forwardable
11
11
  include Protobuf::Logger::LogMethods
12
12
 
13
- delegate [:options, :complete_cb, :success_cb, :failure_cb, :async?] => :@connector
13
+ delegate [:options, :complete_cb, :success_cb, :failure_cb] => :@connector
14
14
  attr_reader :connector
15
15
 
16
16
  # Create a new client with default options (defined in ClientConnection)
@@ -29,15 +29,14 @@ module Protobuf
29
29
  def initialize(opts={})
30
30
  raise "Invalid client configuration. Service must be defined." if opts[:service].nil?
31
31
  @connector = Connector.connector_for_client.new(opts)
32
- log_debug { "[#{log_signature}] Initialized with options: %s" % opts.inspect }
32
+ log_debug { sign_message("Initialized with options: #{opts.inspect}") }
33
33
  end
34
34
 
35
35
  def log_signature
36
- @log_signature ||= "client-#{self.class}"
36
+ @_log_signature ||= "client-#{self.class}"
37
37
  end
38
38
 
39
39
  # Set a complete callback on the client to return the object (self).
40
- # Callback is called regardless of :async setting.
41
40
  #
42
41
  # client = Client.new(:service => WidgetService)
43
42
  # client.on_complete {|obj| ... }
@@ -57,7 +56,6 @@ module Protobuf
57
56
  # Set a failure callback on the client to return the
58
57
  # error returned by the service, if any. If this callback
59
58
  # is called, success_cb will NOT be called.
60
- # Callback is called regardless of :async setting.
61
59
  #
62
60
  # client = Client.new(:service => WidgetService)
63
61
  # client.on_failure {|err| ... }
@@ -68,7 +66,7 @@ module Protobuf
68
66
 
69
67
  def on_failure=(callable)
70
68
  if callable != nil && !callable.respond_to?(:call) && callable.arity != 1
71
- raise "callable must take a single argument and respond to :call"
69
+ raise "Callable must take a single argument and respond to :call"
72
70
  end
73
71
 
74
72
  @connector.failure_cb = callable
@@ -77,7 +75,6 @@ module Protobuf
77
75
  # Set a success callback on the client to return the
78
76
  # successful response from the service when it is returned.
79
77
  # If this callback is called, failure_cb will NOT be called.
80
- # Callback is called regardless of :async setting.
81
78
  #
82
79
  # client = Client.new(:service => WidgetService)
83
80
  # client.on_success {|res| ... }
@@ -88,7 +85,7 @@ module Protobuf
88
85
 
89
86
  def on_success=(callable)
90
87
  if callable != nil && !callable.respond_to?(:call) && callable.arity != 1
91
- raise "callable must take a single argument and respond to :call"
88
+ raise "Callable must take a single argument and respond to :call"
92
89
  end
93
90
 
94
91
  @connector.success_cb = callable
@@ -108,26 +105,29 @@ module Protobuf
108
105
  #
109
106
  def method_missing(method, *params)
110
107
  service = options[:service]
111
- unless service.rpcs[service].keys.include?(method)
112
- log_error { "[#{log_signature}] %s#%s not rpc method, passing to super" % [service.name, method.to_s] }
108
+ unless service.rpc_method?(method)
109
+ log_error { sign_message("#{service.name}##{method.to_s} not rpc method, passing to super") }
113
110
  super(method, *params)
114
111
  else
115
- log_debug { "[#{log_signature}] %s#%s" % [service.name, method.to_s] }
116
- rpc = service.rpcs[service][method.to_sym]
112
+ log_debug { sign_message("#{service.name}##{method.to_s}") }
113
+ rpc = service.rpcs[method.to_sym]
114
+
117
115
  options[:request_type] = rpc.request_type
118
- log_debug { "[#{log_signature}] Request Type: %s" % options[:request_type].name }
116
+ log_debug { sign_message("Request Type: #{options[:request_type].name}") }
117
+
119
118
  options[:response_type] = rpc.response_type
120
- log_debug { "[#{log_signature}] Response Type: %s" % options[:response_type].name }
119
+ log_debug { sign_message("Response Type: #{options[:response_type].name}") }
120
+
121
121
  options[:method] = method.to_s
122
122
  options[:request] = params[0].is_a?(Hash) ? options[:request_type].new(params[0]) : params[0]
123
- log_debug { "[#{log_signature}] Request Data: %s" % options[:request].inspect }
123
+ log_debug { sign_message("Request Data: #{options[:request].inspect}") }
124
124
 
125
125
  # Call client to setup on_success and on_failure event callbacks
126
126
  if block_given?
127
- log_debug { "[#{log_signature}] client setup callback given, invoking" }
127
+ log_debug { sign_message("client setup callback given, invoking") }
128
128
  yield(self)
129
129
  else
130
- log_debug { "[#{log_signature}] no block given for callbacks" }
130
+ log_debug { sign_message("no block given for callbacks") }
131
131
  end
132
132
 
133
133
  send_request
@@ -1,4 +1,4 @@
1
- require 'protobuf/common/logger'
1
+ require 'protobuf/logger'
2
2
  require 'protobuf/rpc/rpc.pb'
3
3
  require 'protobuf/rpc/buffer'
4
4
  require 'protobuf/rpc/error'
@@ -16,27 +16,22 @@ module Protobuf
16
16
  :request => nil, # The request object sent by the client
17
17
  :request_type => nil, # The request type expected by the client
18
18
  :response_type => nil, # The response type expected by the client
19
- :async => false, # Whether or not to block a client call, this is actually handled by client.rb
20
19
  :timeout => 30 # The default timeout for the request, also handled by client.rb
21
20
  }
22
21
 
23
22
  class Base
24
23
  include Protobuf::Logger::LogMethods
25
-
24
+
26
25
  attr_reader :options
27
26
  attr_accessor :success_cb, :failure_cb, :complete_cb
28
27
 
29
28
  def initialize(options)
30
29
  @options = DEFAULT_OPTIONS.merge(options)
31
30
  end
32
-
31
+
33
32
  def send_request
34
33
  raise 'If you inherit a Connector from Base you must implement send_request'
35
34
  end
36
-
37
- def async?
38
- !!@options[:async]
39
- end
40
35
  end
41
36
  end
42
37
  end
@@ -12,23 +12,23 @@ module Protobuf
12
12
  end
13
13
 
14
14
  def complete
15
- @stats.end
16
- @stats.log_stats
17
- log_debug { "[#{log_signature}] Response proceessing complete" }
15
+ @stats.stop
16
+ log_info { @stats.to_s }
17
+ log_debug { sign_message('Response proceessing complete') }
18
18
  @complete_cb.call(self) unless @complete_cb.nil?
19
- rescue
20
- log_error { "[#{log_signature}] Complete callback error encountered: %s" % $!.message }
21
- log_error { "[#{log_signature}] %s" % $!.backtrace.join("\n") }
19
+ rescue => e
20
+ log_error { sign_message('Complete callback error encountered') }
21
+ log_exception(e)
22
22
  raise
23
23
  end
24
24
 
25
25
  def data_callback(data)
26
- log_debug { "[#{log_signature}] Using data_callback" }
26
+ log_debug { sign_message('Using data_callback') }
27
27
  @used_data_callback = true
28
28
  @data = data
29
29
  end
30
30
 
31
- # All failures should be routed through this method
31
+ # All failures should be routed through this method.
32
32
  #
33
33
  # @param [Symbol] code The code we're using (see ::Protobuf::Socketrpc::ErrorReason)
34
34
  # @param [String] message The error message
@@ -36,35 +36,36 @@ module Protobuf
36
36
  @error = ClientError.new
37
37
  @error.code = code.is_a?(Symbol) ? Protobuf::Socketrpc::ErrorReason.values[code] : code
38
38
  @error.message = message
39
- log_debug { "[#{log_signature}] Server failed request (invoking on_failure): %s" % @error.inspect }
39
+ log_debug { sign_message("Server failed request (invoking on_failure): #{@error.inspect}") }
40
40
 
41
41
  @failure_cb.call(@error) unless @failure_cb.nil?
42
- rescue
43
- log_error { "[#{log_signature}] Failure callback error encountered: %s" % $!.message }
44
- log_error { "[#{log_signature}] %s" % $!.backtrace.join("\n") }
42
+ rescue => e
43
+ log_error { sign_message("Failure callback error encountered") }
44
+ log_exception(e)
45
45
  raise
46
46
  ensure
47
47
  complete
48
48
  end
49
49
 
50
50
  def initialize_stats
51
- @stats = Protobuf::Rpc::Stat.new(:CLIENT, true)
51
+ @stats = Protobuf::Rpc::Stat.new(:CLIENT)
52
52
  @stats.server = [@options[:port], @options[:host]]
53
53
  @stats.service = @options[:service].name
54
54
  @stats.method = @options[:method].to_s
55
55
  rescue => ex
56
+ log_exception(ex)
56
57
  fail(:RPC_ERROR, "Invalid stats configuration. #{ex.message}")
57
58
  end
58
59
 
59
60
  def log_signature
60
- @log_signature ||= "client-#{self.class}"
61
+ @_log_signature ||= "client-#{self.class}"
61
62
  end
62
63
 
63
64
  def parse_response
64
65
  # Close up the connection as we no longer need it
65
66
  close_connection
66
67
 
67
- log_debug { "[#{log_signature}] Parsing response from server (connection closed)" }
68
+ log_debug { sign_message("Parsing response from server (connection closed)") }
68
69
 
69
70
  # Parse out the raw response
70
71
  response_wrapper = Protobuf::Socketrpc::Response.new
@@ -72,13 +73,13 @@ module Protobuf
72
73
 
73
74
  # Determine success or failure based on parsed data
74
75
  if response_wrapper.has_field?(:error_reason)
75
- log_debug { "[#{log_signature}] Error response parsed" }
76
+ log_debug { sign_message("Error response parsed") }
76
77
 
77
78
  # fail the call if we already know the client is failed
78
79
  # (don't try to parse out the response payload)
79
80
  fail(response_wrapper.error_reason, response_wrapper.error)
80
81
  else
81
- log_debug { "[#{log_signature}] Successful response parsed" }
82
+ log_debug { sign_message("Successful response parsed") }
82
83
 
83
84
  # Ensure client_response is an instance
84
85
  response_type = @options[:response_type].new
@@ -96,8 +97,8 @@ module Protobuf
96
97
 
97
98
  def post_init
98
99
  send_data unless error?
99
- rescue
100
- fail(:RPC_ERROR, 'Connection error: %s' % $!.message)
100
+ rescue => e
101
+ fail(:RPC_ERROR, "Connection error: #{e.message}")
101
102
  end
102
103
 
103
104
  def rpc_request_data
@@ -108,8 +109,8 @@ module Protobuf
108
109
  :method_name => @options[:method].to_s,
109
110
  :request_proto => @options[:request].serialize_to_string
110
111
  ).serialize_to_string
111
- rescue
112
- fail :INVALID_REQUEST_PROTO, "Could not set request proto: #{$!.message}"
112
+ rescue => e
113
+ fail(:INVALID_REQUEST_PROTO, "Could not set request proto: #{e.message}")
113
114
  end
114
115
 
115
116
  def setup_connection
@@ -118,12 +119,12 @@ module Protobuf
118
119
  end
119
120
 
120
121
  def succeed(response)
121
- log_debug { "[#{log_signature}] Server succeeded request (invoking on_success)" }
122
+ log_debug { sign_message("Server succeeded request (invoking on_success)") }
122
123
  @success_cb.call(response) unless @success_cb.nil?
123
- rescue
124
- log_error { "[#{log_signature}] Success callback error encountered: %s" % $!.message }
125
- log_error { "[#{log_signature}] %s" % $!.backtrace.join("\n") }
126
- fail :RPC_ERROR, 'An exception occurred while calling on_success: %s' % $!.message
124
+ rescue => e
125
+ log_error { sign_message("Success callback error encountered") }
126
+ log_exception(e)
127
+ fail(:RPC_ERROR, "An exception occurred while calling on_success: #{e.message}")
127
128
  ensure
128
129
  complete
129
130
  end
@@ -132,13 +133,13 @@ module Protobuf
132
133
  unless @options[:request].class == @options[:request_type]
133
134
  expected = @options[:request_type].name
134
135
  actual = @options[:request].class.name
135
- fail :INVALID_REQUEST_PROTO, 'Expected request type to be type of %s, got %s instead' % [expected, actual]
136
+ fail(:INVALID_REQUEST_PROTO, "Expected request type to be type of #{expected}, got #{actual} instead")
136
137
  end
137
138
  end
138
139
 
139
140
  def verify_callbacks
140
141
  if !any_callbacks?
141
- log_debug { "[#{log_signature}] No callbacks set, using data_callback" }
142
+ log_debug { sign_message("No callbacks set, using data_callback") }
142
143
  @success_cb = @failure_cb = self.method(:data_callback)
143
144
  end
144
145
  end
@@ -19,9 +19,9 @@ module Protobuf
19
19
  @response_buffer = ::Protobuf::Rpc::Buffer.new(:read)
20
20
  verify_options
21
21
 
22
- log_debug { "[#{log_signature}] Client Initialized: %s" % options.inspect }
23
- rescue
24
- fail(:RPC_ERROR, 'Failed to initialize connection: %s' % $!.message)
22
+ log_debug { sign_message("Client Initialized: #{options.inspect}") }
23
+ rescue => e
24
+ fail(:RPC_ERROR, "Failed to initialize connection: #{e.message}")
25
25
  end
26
26
 
27
27
  ##
@@ -29,7 +29,7 @@ module Protobuf
29
29
  #
30
30
  def self.connect(options={})
31
31
  options = DEFAULT_OPTIONS.merge(options)
32
- log_debug { "[client-#{self}] Connecting to server: %s" % options.inspect }
32
+ log_debug { sign_message("Connecting to server: #{options.inspect}") }
33
33
  EM.connect(options[:host], options[:port], self, options)
34
34
  end
35
35
 
@@ -56,19 +56,19 @@ module Protobuf
56
56
  end
57
57
 
58
58
  def receive_data(data)
59
- log_debug { "[#{log_signature}] receive_data: %s" % data }
59
+ log_debug { sign_message("receive_data: #{data}") }
60
60
  @response_buffer << data
61
61
  @response_data = @response_buffer.data
62
- parse_response if(!@response_data.nil? && @response_buffer.flushed?)
62
+ parse_response if !@response_data.nil? && @response_buffer.flushed?
63
63
  end
64
64
 
65
65
  def send_data
66
66
  request_buffer = ::Protobuf::Rpc::Buffer.new(:write)
67
67
  request_buffer.set_data(@request_data)
68
- log_debug { "[#{log_signature}] sending data: #{request_buffer.inspect}" }
68
+ log_debug { sign_message("sending data: #{request_buffer.inspect}") }
69
69
  super(request_buffer.write)
70
- rescue
71
- fail(:RPC_ERROR, 'Connection error: %s' % $!.message)
70
+ rescue => e
71
+ fail(:RPC_ERROR, "Connection error: #{e.message}")
72
72
  end
73
73
 
74
74
  # overwriting this method for java because it's broken in eventmachine. See https://github.com/eventmachine/eventmachine/issues/14
@@ -11,17 +11,17 @@ module Protobuf
11
11
  f = Fiber.current
12
12
 
13
13
  ::EM.next_tick do
14
- log_debug { "[#{log_signature}] Scheduling EventMachine client request to be created on next tick" }
14
+ log_debug { sign_message('Scheduling EventMachine client request to be created on next tick') }
15
15
  cnxn = EMClient.connect(options, &ensure_cb)
16
16
  cnxn.on_success(&success_cb) if success_cb
17
17
  cnxn.on_failure(&ensure_cb)
18
- cnxn.on_complete { resume_fiber(f) } unless async?
18
+ cnxn.on_complete { resume_fiber(f) }
19
19
  cnxn.setup_connection
20
20
  cnxn.send_data
21
- log_debug { "[#{log_signature}] Connection scheduled" }
21
+ log_debug { sign_message('Connection scheduled') }
22
22
  end
23
23
 
24
- async? ? true : set_timeout_and_validate_fiber
24
+ set_timeout_and_validate_fiber
25
25
  end
26
26
  end
27
27
 
@@ -32,11 +32,11 @@ module Protobuf
32
32
  # don't want to swallow the black holes.
33
33
  #
34
34
  def ensure_cb
35
- @ensure_cb ||= (@failure_cb || lambda { |error| raise '%s: %s' % [error.code.name, error.message] } )
35
+ @ensure_cb ||= (@failure_cb || lambda { |error| raise "#{error.code.name}: #{error.message}" })
36
36
  end
37
37
 
38
38
  def log_signature
39
- @log_signature ||= "client-#{self.class}"
39
+ @_log_signature ||= "client-#{self.class}"
40
40
  end
41
41
 
42
42
  private
@@ -58,18 +58,20 @@ module Protobuf
58
58
  ::EM::cancel_timer(@timeout_timer)
59
59
  fib.resume(true)
60
60
  rescue => ex
61
- message = 'Synchronous client failed: %s' % ex.message
61
+ log_exception(ex)
62
+ message = "Synchronous client failed: #{ex.message}"
62
63
  error_stop_reactor(message)
63
64
  end
64
65
 
65
66
  def set_timeout_and_validate_fiber
66
67
  @timeout_timer = ::EM::add_timer(@options[:timeout]) do
67
- message = 'Client timeout of %d seconds expired' % @options[:timeout]
68
+ message = "Client timeout of #{@options[:timeout]} seconds expired"
68
69
  error_stop_reactor(message)
69
70
  end
70
71
 
71
72
  Fiber.yield
72
- rescue FiberError
73
+ rescue FiberError => ex
74
+ log_exception(ex)
73
75
  message = "Synchronous calls must be in 'EM.fiber_run' block"
74
76
  error_stop_reactor(message)
75
77
  end