thrift 0.2.0.4 → 0.4.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.
Files changed (45) hide show
  1. data/CHANGELOG +1 -13
  2. data/Manifest +11 -23
  3. data/Rakefile +8 -6
  4. data/ext/binary_protocol_accelerated.c +4 -53
  5. data/ext/compact_protocol.c +3 -53
  6. data/ext/extconf.rb +4 -18
  7. data/ext/struct.c +181 -130
  8. data/ext/struct.h +2 -44
  9. data/ext/thrift_native.c +3 -3
  10. data/lib/thrift.rb +6 -1
  11. data/lib/thrift/protocol/binary_protocol_accelerated.rb +5 -1
  12. data/lib/thrift/protocol/compact_protocol.rb +1 -0
  13. data/lib/thrift/server/nonblocking_server.rb +1 -2
  14. data/lib/thrift/struct.rb +46 -112
  15. data/lib/thrift/struct_union.rb +159 -0
  16. data/lib/thrift/transport/http_client_transport.rb +12 -6
  17. data/lib/thrift/transport/memory_buffer_transport.rb +2 -2
  18. data/lib/thrift/types.rb +1 -1
  19. data/lib/thrift/union.rb +179 -0
  20. data/spec/ThriftSpec.thrift +48 -0
  21. data/spec/binary_protocol_accelerated_spec.rb +18 -13
  22. data/spec/binary_protocol_spec_shared.rb +2 -2
  23. data/spec/compact_protocol_spec.rb +19 -3
  24. data/spec/http_client_spec.rb +17 -2
  25. data/spec/struct_spec.rb +34 -0
  26. data/spec/union_spec.rb +193 -0
  27. data/thrift.gemspec +11 -13
  28. metadata +36 -67
  29. data.tar.gz.sig +0 -2
  30. data/Makefile.am +0 -47
  31. data/benchmark/gen-rb/BenchmarkService.rb +0 -81
  32. data/benchmark/gen-rb/Benchmark_constants.rb +0 -11
  33. data/benchmark/gen-rb/Benchmark_types.rb +0 -10
  34. data/lib/thrift/protocol/binaryprotocol.rb +0 -213
  35. data/lib/thrift/protocol/binaryprotocolaccelerated.rb +0 -19
  36. data/lib/thrift/protocol/tbinaryprotocol.rb +0 -2
  37. data/lib/thrift/protocol/tprotocol.rb +0 -2
  38. data/lib/thrift/server/httpserver.rb +0 -44
  39. data/lib/thrift/server/nonblockingserver.rb +0 -278
  40. data/lib/thrift/server/thttpserver.rb +0 -2
  41. data/lib/thrift/server/tserver.rb +0 -2
  42. data/spec/gen-rb/NonblockingService.rb +0 -268
  43. data/spec/gen-rb/ThriftSpec_constants.rb +0 -11
  44. data/spec/gen-rb/ThriftSpec_types.rb +0 -134
  45. metadata.gz.sig +0 -0
data.tar.gz.sig DELETED
@@ -1,2 +0,0 @@
1
- Ť�E��1�].)� ��3i��s+�U������hc=D�����<��6^`�V�c"��\<�c�􅵌B��+��SLV���gOKxiڬ���œ�K|oa���rk�g�d���� ����FBQ�!���;��w��|�W(�6"���Ƹ�h����3�p!��oH��qh�����Q]+A=kM��d�-��E*�������M((KJm����qC��<�Ex���s����@���
2
- z�18
@@ -1,47 +0,0 @@
1
- #
2
- # Licensed to the Apache Software Foundation (ASF) under one
3
- # or more contributor license agreements. See the NOTICE file
4
- # distributed with this work for additional information
5
- # regarding copyright ownership. The ASF licenses this file
6
- # to you under the Apache License, Version 2.0 (the
7
- # "License"); you may not use this file except in compliance
8
- # with the License. You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing,
13
- # software distributed under the License is distributed on an
14
- # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
- # KIND, either express or implied. See the License for the
16
- # specific language governing permissions and limitations
17
- # under the License.
18
- #
19
-
20
- EXTRA_DIST = \
21
- CHANGELOG \
22
- Rakefile \
23
- Manifest \
24
- setup.rb \
25
- lib \
26
- ext \
27
- benchmark \
28
- script \
29
- spec
30
-
31
- all-local:
32
- $(RUBY) setup.rb config
33
- $(RUBY) setup.rb setup
34
-
35
- install-exec-hook:
36
- $(RUBY) setup.rb install
37
-
38
- # Make sure this doesn't fail if Ruby is not configured.
39
- clean-local:
40
- RUBY=$(RUBY) ; if test -z "$$RUBY" ; then RUBY=: ; fi ; \
41
- $$RUBY setup.rb clean
42
-
43
- check-local: all
44
- if HAVE_RSPEC
45
- rake spec
46
- endif
47
-
@@ -1,81 +0,0 @@
1
- #
2
- # Autogenerated by Thrift
3
- #
4
- # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5
- #
6
-
7
- require 'thrift'
8
- require 'thrift/protocol'
9
- require File.dirname(__FILE__) + '/Benchmark_types'
10
-
11
- module ThriftBenchmark
12
- module BenchmarkService
13
- class Client
14
- include ::Thrift::Client
15
-
16
- def fibonacci(n)
17
- send_fibonacci(n)
18
- return recv_fibonacci()
19
- end
20
-
21
- def send_fibonacci(n)
22
- send_message('fibonacci', Fibonacci_args, :n => n)
23
- end
24
-
25
- def recv_fibonacci()
26
- result = receive_message(Fibonacci_result)
27
- return result.success unless result.success.nil?
28
- raise Thrift::ApplicationException.new(Thrift::ApplicationException::MISSING_RESULT, 'fibonacci failed: unknown result')
29
- end
30
-
31
- end
32
-
33
- class Processor
34
- include ::Thrift::Processor
35
-
36
- def process_fibonacci(seqid, iprot, oprot)
37
- args = read_args(iprot, Fibonacci_args)
38
- result = Fibonacci_result.new()
39
- result.success = @handler.fibonacci(args.n)
40
- write_result(result, oprot, 'fibonacci', seqid)
41
- end
42
-
43
- end
44
-
45
- # HELPER FUNCTIONS AND STRUCTURES
46
-
47
- class Fibonacci_args
48
- include ::Thrift::Struct
49
- N = 1
50
-
51
- Thrift::Struct.field_accessor self, :n
52
- FIELDS = {
53
- N => {:type => Thrift::Types::BYTE, :name => 'n'}
54
- }
55
-
56
- def struct_fields; FIELDS; end
57
-
58
- def validate
59
- end
60
-
61
- end
62
-
63
- class Fibonacci_result
64
- include ::Thrift::Struct
65
- SUCCESS = 0
66
-
67
- Thrift::Struct.field_accessor self, :success
68
- FIELDS = {
69
- SUCCESS => {:type => Thrift::Types::I32, :name => 'success'}
70
- }
71
-
72
- def struct_fields; FIELDS; end
73
-
74
- def validate
75
- end
76
-
77
- end
78
-
79
- end
80
-
81
- end
@@ -1,11 +0,0 @@
1
- #
2
- # Autogenerated by Thrift
3
- #
4
- # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5
- #
6
-
7
- require 'thrift/protocol'
8
- require File.dirname(__FILE__) + '/Benchmark_types'
9
-
10
- module ThriftBenchmark
11
- end
@@ -1,10 +0,0 @@
1
- #
2
- # Autogenerated by Thrift
3
- #
4
- # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5
- #
6
-
7
- require 'thrift/protocol'
8
-
9
- module ThriftBenchmark
10
- end
@@ -1,213 +0,0 @@
1
- #
2
- # Copyright (c) 2006- Facebook
3
- # Distributed under the Apache Software License
4
- #
5
- # See accompanying file LICENSE or visit the Thrift site at:
6
- # http://developers.facebook.com/thrift/
7
- #
8
- # Author: Mark Slee <mcslee@facebook.com>
9
- #
10
- require 'thrift/protocol'
11
-
12
- module Thrift
13
- class BinaryProtocol < Protocol
14
- VERSION_MASK = 0xffff0000
15
- VERSION_1 = 0x80010000
16
- TYPE_MASK = 0x000000ff
17
-
18
- attr_reader :strict_read, :strict_write
19
-
20
- def initialize(trans, strict_read=true, strict_write=true)
21
- super(trans)
22
- @strict_read = strict_read
23
- @strict_write = strict_write
24
- end
25
-
26
- def write_message_begin(name, type, seqid)
27
- # this is necessary because we added (needed) bounds checking to
28
- # write_i32, and 0x80010000 is too big for that.
29
- if strict_write
30
- write_i16(VERSION_1 >> 16)
31
- write_i16(type)
32
- write_string(name)
33
- write_i32(seqid)
34
- else
35
- write_string(name)
36
- write_byte(type)
37
- write_i32(seqid)
38
- end
39
- end
40
-
41
- def write_field_begin(name, type, id)
42
- write_byte(type)
43
- write_i16(id)
44
- end
45
-
46
- def write_field_stop
47
- write_byte(Thrift::Types::STOP)
48
- end
49
-
50
- def write_map_begin(ktype, vtype, size)
51
- write_byte(ktype)
52
- write_byte(vtype)
53
- write_i32(size)
54
- end
55
-
56
- def write_list_begin(etype, size)
57
- write_byte(etype)
58
- write_i32(size)
59
- end
60
-
61
- def write_set_begin(etype, size)
62
- write_byte(etype)
63
- write_i32(size)
64
- end
65
-
66
- def write_bool(bool)
67
- write_byte(bool ? 1 : 0)
68
- end
69
-
70
- def write_byte(byte)
71
- trans.write([byte].pack('c'))
72
- end
73
-
74
- def write_i16(i16)
75
- trans.write([i16].pack('n'))
76
- end
77
-
78
- def write_i32(i32)
79
- raise RangeError if i32 < -2**31 || i32 >= 2**31
80
- trans.write([i32].pack('N'))
81
- end
82
-
83
- def write_i64(i64)
84
- hi = i64 >> 32
85
- lo = i64 & 0xffffffff
86
- trans.write([hi, lo].pack('N2'))
87
- end
88
-
89
- def write_double(dub)
90
- trans.write([dub].pack('G'))
91
- end
92
-
93
- def write_string(str)
94
- write_i32(str.length)
95
- trans.write(str)
96
- end
97
-
98
- def read_message_begin
99
- version = read_i32
100
- if version < 0
101
- if (version & VERSION_MASK != VERSION_1)
102
- raise ProtocolException.new(ProtocolException::BAD_VERSION, 'Missing version identifier')
103
- end
104
- type = version & TYPE_MASK
105
- name = read_string
106
- seqid = read_i32
107
- [name, type, seqid]
108
- else
109
- if strict_read
110
- raise ProtocolException.new(ProtocolException::BAD_VERSION, 'No version identifier, old protocol client?')
111
- end
112
- name = trans.read_all(version)
113
- type = read_byte
114
- seqid = read_i32
115
- [name, type, seqid]
116
- end
117
- end
118
-
119
- def read_field_begin
120
- type = read_byte
121
- if (type == Types::STOP)
122
- [nil, type, 0]
123
- else
124
- id = read_i16
125
- [nil, type, id]
126
- end
127
- end
128
-
129
- def read_map_begin
130
- ktype = read_byte
131
- vtype = read_byte
132
- size = read_i32
133
- [ktype, vtype, size]
134
- end
135
-
136
- def read_list_begin
137
- etype = read_byte
138
- size = read_i32
139
- [etype, size]
140
- end
141
-
142
- def read_set_begin
143
- etype = read_byte
144
- size = read_i32
145
- [etype, size]
146
- end
147
-
148
- def read_bool
149
- byte = read_byte
150
- byte != 0
151
- end
152
-
153
- def read_byte
154
- dat = trans.read_all(1)
155
- val = dat[0]
156
- if (val > 0x7f)
157
- val = 0 - ((val - 1) ^ 0xff)
158
- end
159
- val
160
- end
161
-
162
- def read_i16
163
- dat = trans.read_all(2)
164
- val, = dat.unpack('n')
165
- if (val > 0x7fff)
166
- val = 0 - ((val - 1) ^ 0xffff)
167
- end
168
- val
169
- end
170
-
171
- def read_i32
172
- dat = trans.read_all(4)
173
- val, = dat.unpack('N')
174
- if (val > 0x7fffffff)
175
- val = 0 - ((val - 1) ^ 0xffffffff)
176
- end
177
- val
178
- end
179
-
180
- def read_i64
181
- dat = trans.read_all(8)
182
- hi, lo = dat.unpack('N2')
183
- if (hi > 0x7fffffff)
184
- hi ^= 0xffffffff
185
- lo ^= 0xffffffff
186
- 0 - (hi << 32) - lo - 1
187
- else
188
- (hi << 32) + lo
189
- end
190
- end
191
-
192
- def read_double
193
- dat = trans.read_all(8)
194
- val = dat.unpack('G').first
195
- val
196
- end
197
-
198
- def read_string
199
- sz = read_i32
200
- dat = trans.read_all(sz)
201
- dat
202
- end
203
-
204
- end
205
- deprecate_class! :TBinaryProtocol => BinaryProtocol
206
-
207
- class BinaryProtocolFactory < ProtocolFactory
208
- def get_protocol(trans)
209
- return Thrift::BinaryProtocol.new(trans)
210
- end
211
- end
212
- deprecate_class! :TBinaryProtocolFactory => BinaryProtocolFactory
213
- end
@@ -1,19 +0,0 @@
1
- require 'thrift/protocol/binaryprotocol'
2
- require 'thrift_native'
3
-
4
- =begin
5
- The only change required for a transport to support TBinaryProtocolAccelerated is to implement 2 methods:
6
- * borrow(size), which takes an optional argument and returns atleast _size_ bytes from the transport,
7
- or the default buffer size if no argument is given
8
- * consume!(size), which removes size bytes from the front of the buffer
9
-
10
- See TMemoryBuffer and TBufferedTransport for examples.
11
- =end
12
-
13
- module Thrift
14
- class BinaryProtocolAcceleratedFactory < ProtocolFactory
15
- def get_protocol(trans)
16
- BinaryProtocolAccelerated.new(trans)
17
- end
18
- end
19
- end
@@ -1,2 +0,0 @@
1
- require 'thrift/deprecation'
2
- require 'thrift/protocol/binaryprotocol'
@@ -1,2 +0,0 @@
1
- require 'thrift/deprecation'
2
- require 'thrift/protocol'
@@ -1,44 +0,0 @@
1
- require 'thrift/protocol'
2
- require 'thrift/protocol/binaryprotocol'
3
- require 'thrift/transport'
4
-
5
- require 'mongrel'
6
-
7
- ## Sticks a service on a URL, using mongrel to do the HTTP work
8
- module Thrift
9
- class SimpleMongrelHTTPServer
10
- class Handler < Mongrel::HttpHandler
11
- def initialize(processor, protocol_factory)
12
- @processor = processor
13
- @protocol_factory = protocol_factory
14
- end
15
-
16
- def process(request, response)
17
- if request.params["REQUEST_METHOD"] == "POST"
18
- response.start(200) do |head, out|
19
- head["Content-Type"] = "application/x-thrift"
20
- transport = IOStreamTransport.new request.body, out
21
- protocol = @protocol_factory.get_protocol transport
22
- @processor.process protocol, protocol
23
- end
24
- else
25
- response.start(404) { }
26
- end
27
- end
28
- end
29
-
30
- def initialize(processor, opts={})
31
- port = opts[:port] || 80
32
- ip = opts[:ip] || "0.0.0.0"
33
- path = opts[:path] || ""
34
- protocol_factory = opts[:protocol_factory] || BinaryProtocolFactory.new
35
- @server = Mongrel::HttpServer.new ip, port
36
- @server.register "/#{path}", Handler.new(processor, protocol_factory)
37
- end
38
-
39
- def serve
40
- @server.run.join
41
- end
42
- end
43
- deprecate_class! :TSimpleMongrelHTTPServer => SimpleMongrelHTTPServer
44
- end
@@ -1,278 +0,0 @@
1
- require 'thrift/server'
2
- require 'logger'
3
- require 'thread'
4
-
5
- module Thrift
6
- # this class expects to always use a FramedTransport for reading messages
7
- class NonblockingServer < Server
8
- def initialize(processor, serverTransport, transportFactory=nil, protocolFactory=nil, num=20, logger = nil)
9
- super(processor, serverTransport, transportFactory, protocolFactory)
10
- @num_threads = num
11
- if logger.nil?
12
- @logger = Logger.new(STDERR)
13
- @logger.level = Logger::WARN
14
- else
15
- @logger = logger
16
- end
17
- @shutdown_semaphore = Mutex.new
18
- @transport_semaphore = Mutex.new
19
- end
20
-
21
- def serve
22
- @logger.info "Starting #{self}"
23
- @serverTransport.listen
24
- @io_manager = start_io_manager
25
-
26
- begin
27
- loop do
28
- break if @serverTransport.closed?
29
- rd, = select([@serverTransport], nil, nil, 0.1)
30
- next if rd.nil?
31
- socket = @serverTransport.accept
32
- @logger.debug "Accepted socket: #{socket.inspect}"
33
- @io_manager.add_connection socket
34
- end
35
- rescue IOError => e
36
- end
37
- # we must be shutting down
38
- @logger.info "#{self} is shutting down, goodbye"
39
- ensure
40
- @transport_semaphore.synchronize do
41
- @serverTransport.close
42
- end
43
- @io_manager.ensure_closed unless @io_manager.nil?
44
- end
45
-
46
- def shutdown(timeout = 0, block = true)
47
- @shutdown_semaphore.synchronize do
48
- return if @is_shutdown
49
- @is_shutdown = true
50
- end
51
- # nonblocking is intended for calling from within a Handler
52
- # but we can't change the order of operations here, so lets thread
53
- shutdown_proc = lambda do
54
- @io_manager.shutdown(timeout)
55
- @transport_semaphore.synchronize do
56
- @serverTransport.close # this will break the accept loop
57
- end
58
- end
59
- if block
60
- shutdown_proc.call
61
- else
62
- Thread.new &shutdown_proc
63
- end
64
- end
65
-
66
- private
67
-
68
- def start_io_manager
69
- iom = IOManager.new(@processor, @serverTransport, @transportFactory, @protocolFactory, @num_threads, @logger)
70
- iom.spawn
71
- iom
72
- end
73
-
74
- class IOManager # :nodoc:
75
- DEFAULT_BUFFER = 2**20
76
-
77
- def initialize(processor, serverTransport, transportFactory, protocolFactory, num, logger)
78
- @processor = processor
79
- @serverTransport = serverTransport
80
- @transportFactory = transportFactory
81
- @protocolFactory = protocolFactory
82
- @num_threads = num
83
- @logger = logger
84
- @connections = []
85
- @buffers = Hash.new { |h,k| h[k] = '' }
86
- @signal_queue = Queue.new
87
- @signal_pipes = IO.pipe
88
- @signal_pipes[1].sync = true
89
- @worker_queue = Queue.new
90
- @shutdown_queue = Queue.new
91
- end
92
-
93
- def add_connection(socket)
94
- signal [:connection, socket]
95
- end
96
-
97
- def spawn
98
- @iom_thread = Thread.new do
99
- @logger.debug "Starting #{self}"
100
- run
101
- end
102
- end
103
-
104
- def shutdown(timeout = 0)
105
- @logger.debug "#{self} is shutting down workers"
106
- @worker_queue.clear
107
- @num_threads.times { @worker_queue.push [:shutdown] }
108
- signal [:shutdown, timeout]
109
- @shutdown_queue.pop
110
- @signal_pipes[0].close
111
- @signal_pipes[1].close
112
- @logger.debug "#{self} is shutting down, goodbye"
113
- end
114
-
115
- def ensure_closed
116
- kill_worker_threads if @worker_threads
117
- @iom_thread.kill
118
- end
119
-
120
- private
121
-
122
- def run
123
- spin_worker_threads
124
-
125
- loop do
126
- rd, = select([@signal_pipes[0], *@connections])
127
- if rd.delete @signal_pipes[0]
128
- break if read_signals == :shutdown
129
- end
130
- rd.each do |fd|
131
- if fd.handle.eof?
132
- remove_connection fd
133
- else
134
- read_connection fd
135
- end
136
- end
137
- end
138
- join_worker_threads(@shutdown_timeout)
139
- ensure
140
- @shutdown_queue.push :shutdown
141
- end
142
-
143
- def read_connection(fd)
144
- @buffers[fd] << fd.read(DEFAULT_BUFFER)
145
- frame = slice_frame!(@buffers[fd])
146
- if frame
147
- @logger.debug "#{self} is processing a frame"
148
- @worker_queue.push [:frame, fd, frame]
149
- end
150
- end
151
-
152
- def spin_worker_threads
153
- @logger.debug "#{self} is spinning up worker threads"
154
- @worker_threads = []
155
- @num_threads.times do
156
- @worker_threads << spin_thread
157
- end
158
- end
159
-
160
- def spin_thread
161
- Worker.new(@processor, @transportFactory, @protocolFactory, @logger, @worker_queue).spawn
162
- end
163
-
164
- def signal(msg)
165
- @signal_queue << msg
166
- @signal_pipes[1].write " "
167
- end
168
-
169
- def read_signals
170
- # clear the signal pipe
171
- # note that since read_nonblock is broken in jruby,
172
- # we can only read up to a set number of signals at once
173
- sigstr = @signal_pipes[0].readpartial(1024)
174
- # now read the signals
175
- begin
176
- sigstr.length.times do
177
- signal, obj = @signal_queue.pop(true)
178
- case signal
179
- when :connection
180
- @connections << obj
181
- when :shutdown
182
- @shutdown_timeout = obj
183
- return :shutdown
184
- end
185
- end
186
- rescue ThreadError
187
- # out of signals
188
- # note that in a perfect world this would never happen, since we're
189
- # only reading the number of signals pushed on the pipe, but given the lack
190
- # of locks, in theory we could clear the pipe/queue while a new signal is being
191
- # placed on the pipe, at which point our next read_signals would hit this error
192
- end
193
- end
194
-
195
- def remove_connection(fd)
196
- # don't explicitly close it, a thread may still be writing to it
197
- @connections.delete fd
198
- @buffers.delete fd
199
- end
200
-
201
- def join_worker_threads(shutdown_timeout)
202
- start = Time.now
203
- @worker_threads.each do |t|
204
- if shutdown_timeout > 0
205
- timeout = (start + shutdown_timeout) - Time.now
206
- break if timeout <= 0
207
- t.join(timeout)
208
- else
209
- t.join
210
- end
211
- end
212
- kill_worker_threads
213
- end
214
-
215
- def kill_worker_threads
216
- @worker_threads.each do |t|
217
- t.kill if t.status
218
- end
219
- @worker_threads.clear
220
- end
221
-
222
- def slice_frame!(buf)
223
- if buf.length >= 4
224
- size = buf.unpack('N').first
225
- if buf.length >= size + 4
226
- buf.slice!(0, size + 4)
227
- else
228
- nil
229
- end
230
- else
231
- nil
232
- end
233
- end
234
-
235
- class Worker # :nodoc:
236
- def initialize(processor, transportFactory, protocolFactory, logger, queue)
237
- @processor = processor
238
- @transportFactory = transportFactory
239
- @protocolFactory = protocolFactory
240
- @logger = logger
241
- @queue = queue
242
- end
243
-
244
- def spawn
245
- Thread.new do
246
- @logger.debug "#{self} is spawning"
247
- run
248
- end
249
- end
250
-
251
- private
252
-
253
- def run
254
- loop do
255
- cmd, *args = @queue.pop
256
- case cmd
257
- when :shutdown
258
- @logger.debug "#{self} is shutting down, goodbye"
259
- break
260
- when :frame
261
- fd, frame = args
262
- begin
263
- otrans = @transportFactory.get_transport(fd)
264
- oprot = @protocolFactory.get_protocol(otrans)
265
- membuf = MemoryBuffer.new(frame)
266
- itrans = @transportFactory.get_transport(membuf)
267
- iprot = @protocolFactory.get_protocol(itrans)
268
- @processor.process(iprot, oprot)
269
- rescue => e
270
- @logger.error "#{Thread.current.inspect} raised error: #{e.inspect}\n#{e.backtrace.join("\n")}"
271
- end
272
- end
273
- end
274
- end
275
- end
276
- end
277
- end
278
- end