ib_ruby_proxy 0.0.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 +7 -0
- data/.circleci/config.yml +77 -0
- data/.gitignore +8 -0
- data/.rspec +1 -0
- data/.rubocop.yml +143 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +74 -0
- data/LICENSE.txt +21 -0
- data/README.md +130 -0
- data/Rakefile +12 -0
- data/bin/console +14 -0
- data/bin/generate_ruby_classes +13 -0
- data/bin/ibproxy +32 -0
- data/bin/setup +8 -0
- data/docs/diagrams.key +0 -0
- data/docs/images/architecture.png +0 -0
- data/examples/common.rb +14 -0
- data/examples/plain_req_historical_ticks.rb +19 -0
- data/examples/req_contract_details.rb +9 -0
- data/examples/req_historical_bars_data.rb +10 -0
- data/examples/req_historical_ticks.rb +10 -0
- data/examples/req_tick_by_tick_data.rb +9 -0
- data/ib_ruby_proxy.gemspec +43 -0
- data/lib/ib_ruby_proxy.rb +35 -0
- data/lib/ib_ruby_proxy/client/callbacks_response_handler.rb +135 -0
- data/lib/ib_ruby_proxy/client/client.rb +69 -0
- data/lib/ib_ruby_proxy/client/ib/bar.rb +36 -0
- data/lib/ib_ruby_proxy/client/ib/combo_leg.rb +36 -0
- data/lib/ib_ruby_proxy/client/ib/contract.rb +56 -0
- data/lib/ib_ruby_proxy/client/ib/contract_details.rb +100 -0
- data/lib/ib_ruby_proxy/client/ib/delta_neutral_contract.rb +26 -0
- data/lib/ib_ruby_proxy/client/ib/historical_tick.rb +26 -0
- data/lib/ib_ruby_proxy/client/ib/historical_tick_bid_ask.rb +32 -0
- data/lib/ib_ruby_proxy/client/ib/historical_tick_last.rb +32 -0
- data/lib/ib_ruby_proxy/client/ib/order.rb +262 -0
- data/lib/ib_ruby_proxy/client/ib/tick_attrib_bid_ask.rb +24 -0
- data/lib/ib_ruby_proxy/client/ib/tick_attrib_last.rb +24 -0
- data/lib/ib_ruby_proxy/client/ib_callbacks_observer.rb +25 -0
- data/lib/ib_ruby_proxy/config.yml +43 -0
- data/lib/ib_ruby_proxy/server/ext/array.rb +22 -0
- data/lib/ib_ruby_proxy/server/ext/enum.rb +20 -0
- data/lib/ib_ruby_proxy/server/ext/idempotent_types.rb +23 -0
- data/lib/ib_ruby_proxy/server/ib/bar.rb +21 -0
- data/lib/ib_ruby_proxy/server/ib/combo_leg.rb +21 -0
- data/lib/ib_ruby_proxy/server/ib/contract.rb +31 -0
- data/lib/ib_ruby_proxy/server/ib/contract_details.rb +53 -0
- data/lib/ib_ruby_proxy/server/ib/delta_neutral_contract.rb +16 -0
- data/lib/ib_ruby_proxy/server/ib/historical_tick.rb +16 -0
- data/lib/ib_ruby_proxy/server/ib/historical_tick_bid_ask.rb +19 -0
- data/lib/ib_ruby_proxy/server/ib/historical_tick_last.rb +19 -0
- data/lib/ib_ruby_proxy/server/ib/order.rb +134 -0
- data/lib/ib_ruby_proxy/server/ib/tick_attrib_bid_ask.rb +15 -0
- data/lib/ib_ruby_proxy/server/ib/tick_attrib_last.rb +15 -0
- data/lib/ib_ruby_proxy/server/ib_client_adapter.rb +51 -0
- data/lib/ib_ruby_proxy/server/ib_proxy_service.rb +85 -0
- data/lib/ib_ruby_proxy/server/ib_ruby_class_files_generator.rb +77 -0
- data/lib/ib_ruby_proxy/server/ib_ruby_class_source_generator.rb +155 -0
- data/lib/ib_ruby_proxy/server/ib_wrapper_adapter.rb +47 -0
- data/lib/ib_ruby_proxy/server/reflection/ib_class.rb +62 -0
- data/lib/ib_ruby_proxy/server/reflection/ib_field.rb +60 -0
- data/lib/ib_ruby_proxy/util/has_logger.rb +10 -0
- data/lib/ib_ruby_proxy/util/string_utils.rb +29 -0
- data/lib/ib_ruby_proxy/version.rb +3 -0
- data/lib/server.rb +4 -0
- data/sandbox/drb_performance/client.rb +46 -0
- data/sandbox/drb_performance/server.rb +26 -0
- data/vendor/TwsApi.jar +0 -0
- metadata +226 -0
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "ib_ruby_proxy"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env jruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift './lib'
|
4
|
+
$LOAD_PATH.unshift File.join(__dir__, '..')
|
5
|
+
$LOAD_PATH.unshift File.join(__dir__, '..', 'lib')
|
6
|
+
|
7
|
+
require 'ib_ruby_proxy'
|
8
|
+
require 'server'
|
9
|
+
|
10
|
+
client_code_dir = File.join(__dir__, '..', 'lib', 'ib_ruby_proxy', 'client', 'ib')
|
11
|
+
server_code_dir = File.join(__dir__, '..', 'lib', 'ib_ruby_proxy', 'server', 'ib')
|
12
|
+
IbRubyProxy::Server::IbRubyClassFilesGenerator.new(client_code_dir: client_code_dir, server_code_dir: server_code_dir).generate_all
|
13
|
+
|
data/bin/ibproxy
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'commander/import'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift './lib'
|
7
|
+
$LOAD_PATH.unshift File.join(__dir__, '..')
|
8
|
+
$LOAD_PATH.unshift File.join(__dir__, '..', 'lib')
|
9
|
+
|
10
|
+
require 'ib_ruby_proxy'
|
11
|
+
require 'server'
|
12
|
+
|
13
|
+
program :name, 'ibproxy'
|
14
|
+
program :version, IbRubyProxy::VERSION
|
15
|
+
program :description, 'Invoke Interactive Brokers API from Ruby'
|
16
|
+
default_command :server
|
17
|
+
|
18
|
+
command :server do |c|
|
19
|
+
c.syntax = 'ibproxy server [options]'
|
20
|
+
c.summary = 'Start ibproxy server'
|
21
|
+
c.option '--ib-port PORT', Integer, "Interactive brokers client port. #{IbRubyProxy::Server::IbProxyService::DEFAULT_IB_GATEWAY_PORT} by default (Gateway). Default for TWS is whatever"
|
22
|
+
c.option '--drb-port PORT', Integer, "Port for the served drb endpoint. #{IbRubyProxy::Server::IbProxyService::DEFAULT_DRB_PORT} by default"
|
23
|
+
c.action do |args, options|
|
24
|
+
options.default ib_port: IbRubyProxy::Server::IbProxyService::DEFAULT_IB_GATEWAY_PORT,
|
25
|
+
drb_port: IbRubyProxy::Server::IbProxyService::DEFAULT_DRB_PORT
|
26
|
+
ib_port = options.ib_port
|
27
|
+
drb_port = options.drb_port
|
28
|
+
puts "Starting with ib port #{ib_port} and drb port #{drb_port}..."
|
29
|
+
IbRubyProxy::Server::IbProxyService.new(ib_port: ib_port, drb_port: drb_port).start
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
data/bin/setup
ADDED
data/docs/diagrams.key
ADDED
Binary file
|
Binary file
|
data/examples/common.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'drb'
|
2
|
+
require 'ib_ruby_proxy'
|
3
|
+
|
4
|
+
class Securities
|
5
|
+
class << self
|
6
|
+
def emini(expiration_month = '201909')
|
7
|
+
IbRubyProxy::Client::Ib::Contract.new symbol: 'ES',
|
8
|
+
sec_type: 'FUT',
|
9
|
+
currency: 'USD',
|
10
|
+
exchange: 'GLOBEX',
|
11
|
+
last_trade_date_or_contract_month: expiration_month
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative './common'
|
2
|
+
|
3
|
+
client = IbRubyProxy::Client::Client.from_drb
|
4
|
+
|
5
|
+
class CallbacksObserver < IbRubyProxy::Client::IbCallbacksObserver
|
6
|
+
def historical_ticks(_request_id, ticks, _done)
|
7
|
+
ap ticks
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
aapl = IbRubyProxy::Client::Ib::Contract.new symbol: 'AAPL',
|
12
|
+
sec_type: 'STK',
|
13
|
+
exchange: 'ISLAND'
|
14
|
+
|
15
|
+
client.add_ib_callbacks_observer CallbacksObserver.new
|
16
|
+
client.req_historical_ticks(18009, aapl, '20190304 12:00:00', nil, 100,
|
17
|
+
'MIDPOINT', 1, false, nil)
|
18
|
+
|
19
|
+
sleep
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require_relative './common'
|
2
|
+
|
3
|
+
client = IbRubyProxy::Client::Client.from_drb
|
4
|
+
|
5
|
+
client.req_historical_ticks(18009, Securities.emini, nil, '20190304 17:00:00', 100,
|
6
|
+
'MIDPOINT', 1, false, nil) do |_callback, _request_id, ticks, _done|
|
7
|
+
ap ticks
|
8
|
+
end
|
9
|
+
|
10
|
+
sleep
|
@@ -0,0 +1,43 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'ib_ruby_proxy/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'ib_ruby_proxy'
|
7
|
+
spec.version = IbRubyProxy::VERSION
|
8
|
+
spec.authors = ['Jorge Manrubia']
|
9
|
+
spec.email = ['jorge.manrubia@gmail.com']
|
10
|
+
|
11
|
+
spec.summary = 'Invoke IB Java API from Ruby'
|
12
|
+
spec.description = 'Invoke IB Java API from Ruby'
|
13
|
+
spec.homepage = 'https://github.com/jorgemanrubia/ib_ruby_proxy'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
20
|
+
spec.metadata['source_code_uri'] = 'https://github.com/jorgemanrubia/ib_ruby_proxy'
|
21
|
+
else
|
22
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
23
|
+
'public gem pushes.'
|
24
|
+
end
|
25
|
+
|
26
|
+
# Specify which files should be added to the gem when it is released.
|
27
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
28
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
29
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
30
|
+
end
|
31
|
+
spec.bindir = 'exe'
|
32
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
33
|
+
spec.require_paths = ['lib']
|
34
|
+
|
35
|
+
spec.add_dependency 'awesome_print'
|
36
|
+
spec.add_dependency 'commander'
|
37
|
+
spec.add_dependency 'concurrent-ruby'
|
38
|
+
spec.add_development_dependency 'bundler', '~> 2.0.1'
|
39
|
+
spec.add_development_dependency 'impersonator'
|
40
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
41
|
+
spec.add_development_dependency 'rspec', '~> 3.8.0'
|
42
|
+
spec.add_development_dependency 'rspec_junit_formatter'
|
43
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'ib_ruby_proxy/version'
|
2
|
+
require 'awesome_print'
|
3
|
+
require 'drb'
|
4
|
+
require 'logger'
|
5
|
+
require 'concurrent-ruby'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
Dir["#{__dir__}/ib_ruby_proxy/util/**/*.rb"].each { |file| require file }
|
9
|
+
Dir["#{__dir__}/ib_ruby_proxy/client/**/*.rb"].each { |file| require file }
|
10
|
+
|
11
|
+
module IbRubyProxy
|
12
|
+
LOGGER_LEVEL = Logger::DEBUG
|
13
|
+
|
14
|
+
# Gem logger
|
15
|
+
#
|
16
|
+
# @return [Logger]
|
17
|
+
def self.logger
|
18
|
+
@logger ||= Logger.new(STDOUT).tap do |logger|
|
19
|
+
logger.level = LOGGER_LEVEL
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Configuration options parsed from +ib_ruby_proxy/config.yml+
|
24
|
+
#
|
25
|
+
# @return [Hash]
|
26
|
+
def self.config
|
27
|
+
@config ||= begin
|
28
|
+
file_path = File.join(__dir__, 'ib_ruby_proxy/config.yml')
|
29
|
+
YAML.load_file(file_path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Error < StandardError
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
module IbRubyProxy
|
2
|
+
module Client
|
3
|
+
# This class maps callbacks with method invocations that originated them so that
|
4
|
+
# a block can be passed to the api method and it will be invoked when a callback is
|
5
|
+
# received
|
6
|
+
class CallbacksResponseHandler
|
7
|
+
IB_CALLBACKS_MAPPING = {
|
8
|
+
req_historical_ticks: { callbacks: %i[historical_ticks historical_ticks_bid_ask
|
9
|
+
historical_ticks_last],
|
10
|
+
discriminate_by_argument_nth: 0 },
|
11
|
+
req_contract_details: { callbacks: %i[contract_details contract_details_end],
|
12
|
+
discriminate_by_argument_nth: 0 },
|
13
|
+
req_tick_by_tick_data: { callbacks: %i[tick_by_tick_bid_ask tick_by_tick_all_last
|
14
|
+
tick_by_tick_mid_point],
|
15
|
+
discriminate_by_argument_nth: 0 },
|
16
|
+
req_historical_data: { callbacks: %i[historical_data historical_data_end
|
17
|
+
historical_data_update],
|
18
|
+
discriminate_by_argument_nth: 0 }
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@method_handlers = {}
|
23
|
+
@callback_handlers = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
# Handle invoked method
|
27
|
+
#
|
28
|
+
# @param [String, Symbol] method_name
|
29
|
+
# @param [Array<Object>] arguments
|
30
|
+
# @param [Proc] block
|
31
|
+
def method_invoked(method_name, *arguments, &block)
|
32
|
+
method_name = method_name.to_sym
|
33
|
+
method_handlers[method_name]&.method_invoked(*arguments, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Handle callback received: it will invoke the block passed in the corresponding
|
37
|
+
# {#method_invoked}, if any.
|
38
|
+
#
|
39
|
+
# @param [Symbol] callback_name
|
40
|
+
# @param [Array<Object>] arguments
|
41
|
+
def callback_received(callback_name, *arguments)
|
42
|
+
callback_name = callback_name.to_sym
|
43
|
+
callback_handlers[callback_name]&.callback_received(callback_name, *arguments)
|
44
|
+
end
|
45
|
+
|
46
|
+
# @private
|
47
|
+
def self.for_ib
|
48
|
+
new.tap do |handler|
|
49
|
+
IbRubyProxy.config['mapped_callbacks'].each do |method, callback_config|
|
50
|
+
nth_argument = callback_config['discriminate_by_argument_nth']
|
51
|
+
handler.configure_block_callback method: method.to_sym,
|
52
|
+
callbacks: callback_config['callbacks'],
|
53
|
+
discriminate_by_argument_nth: nth_argument
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Configures a mapping between a method invocation and a received callback
|
59
|
+
#
|
60
|
+
# @param [String, Symbol] method
|
61
|
+
# @param [String, Symbol] callbacks
|
62
|
+
# @param [Integer, nil] discriminate_by_argument_nth The position of the argument that
|
63
|
+
# will be used to discriminate received callbacks and match them with invocation methods.
|
64
|
+
# +nil+ indicates no argument should be used for discriminating (default)
|
65
|
+
def configure_block_callback(method:, callbacks:, discriminate_by_argument_nth: nil)
|
66
|
+
validate_can_add_callback_on_method!(method)
|
67
|
+
|
68
|
+
handler = BlockCallbackHandler.new(discriminate_by_argument_nth)
|
69
|
+
|
70
|
+
configure_callbacks_handler(callbacks, handler)
|
71
|
+
configure_method_handler(method, handler)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
attr_reader :method_handlers, :callback_handlers
|
77
|
+
|
78
|
+
def configure_method_handler(method, handler)
|
79
|
+
method_handlers[method.to_sym] = handler
|
80
|
+
end
|
81
|
+
|
82
|
+
def configure_callbacks_handler(callbacks, handler)
|
83
|
+
callbacks << :error
|
84
|
+
callbacks.each do |callback_name|
|
85
|
+
callback_handlers[callback_name.to_sym] = handler
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def validate_can_add_callback_on_method!(method)
|
90
|
+
raise "Already configured handler for #{method}" if method_handlers[method]
|
91
|
+
end
|
92
|
+
|
93
|
+
# b_proxy_service.rb:13@private
|
94
|
+
class BlockCallbackHandler
|
95
|
+
include IbRubyProxy::Util::HasLogger
|
96
|
+
|
97
|
+
attr_reader :discriminate_by_argument_nth, :block
|
98
|
+
|
99
|
+
def initialize(discriminate_by_argument_nth)
|
100
|
+
@discriminate_by_argument_nth = discriminate_by_argument_nth
|
101
|
+
@blocks_by_discriminator = {}
|
102
|
+
end
|
103
|
+
|
104
|
+
def method_invoked(*arguments, &block)
|
105
|
+
if @discriminate_by_argument_nth
|
106
|
+
discrminator = arguments[@discriminate_by_argument_nth]
|
107
|
+
unless discrminator
|
108
|
+
raise "No argument #{@discriminate_by_argument_nth} to discriminate with?"\
|
109
|
+
" #{arguments.inspect}"
|
110
|
+
end
|
111
|
+
|
112
|
+
@blocks_by_discriminator[discrminator] = block
|
113
|
+
else
|
114
|
+
@block = block
|
115
|
+
end
|
116
|
+
nil
|
117
|
+
end
|
118
|
+
|
119
|
+
def callback_received(callback_name, *arguments)
|
120
|
+
if callback_name.to_s == 'error'
|
121
|
+
raise StandardError, arguments.join('. ')
|
122
|
+
else
|
123
|
+
block = if @discriminate_by_argument_nth
|
124
|
+
@blocks_by_discriminator[arguments[@discriminate_by_argument_nth]]
|
125
|
+
else
|
126
|
+
@block
|
127
|
+
end
|
128
|
+
|
129
|
+
block&.call(callback_name, *arguments)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'drb/timeridconv'
|
2
|
+
|
3
|
+
module IbRubyProxy
|
4
|
+
module Client
|
5
|
+
# A client for interacting with the DRb service
|
6
|
+
#
|
7
|
+
# If can be instantiated directly from the DRb service with {.create_drb_ib_client}
|
8
|
+
#
|
9
|
+
# It offers the same interface than a {IbRubyProxy::Server::IbClientAdapter} and, also,
|
10
|
+
# configures a {CallbacksResponseHandler} so that you can use Ruby blocks to capture
|
11
|
+
# callbacks invocations based on the semantics of the invoked methods.
|
12
|
+
#
|
13
|
+
# @see CallbacksResponseHandler
|
14
|
+
class Client
|
15
|
+
attr_reader :ib_client
|
16
|
+
|
17
|
+
# @return [Client]
|
18
|
+
# @param [String] host DRb host +localhost+ by default
|
19
|
+
# @param [Object] port DRb port +1992+ by default
|
20
|
+
def self.from_drb(host: 'localhost', port: 1992)
|
21
|
+
new(create_drb_ib_client(host: host, port: port))
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param [IbRubyProxy::Server::IbClientAdapter] ib_client
|
25
|
+
def initialize(ib_client)
|
26
|
+
@ib_client = ib_client
|
27
|
+
@promises_by_request_id = {}
|
28
|
+
@callbacks_response_handler = CallbacksResponseHandler.for_ib
|
29
|
+
@ib_client.add_ib_callbacks_observer ResponseHandleObserver.new(@callbacks_response_handler)
|
30
|
+
end
|
31
|
+
|
32
|
+
# @private
|
33
|
+
def self.create_drb_ib_client(host:, port:)
|
34
|
+
drb_ib_client = DRbObject.new(nil, "druby://#{host}:#{port}")
|
35
|
+
DRb::DRbServer.verbose = true
|
36
|
+
DRb.install_id_conv ::DRb::TimerIdConv.new 60
|
37
|
+
DRb.start_service
|
38
|
+
drb_ib_client
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def respond_to_missing?(name, include_private = false)
|
44
|
+
@ib_client.respond_to?(name, include_private)
|
45
|
+
end
|
46
|
+
|
47
|
+
def method_missing(method, *arguments, &block)
|
48
|
+
@ib_client.public_send(method, *arguments, &block)
|
49
|
+
@callbacks_response_handler.method_invoked method, *arguments, &block
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# An observer that will delegate callbacks to a {CallbacksResponseHandler}
|
54
|
+
#
|
55
|
+
# @private
|
56
|
+
class ResponseHandleObserver
|
57
|
+
include DRb::DRbUndumped
|
58
|
+
|
59
|
+
def initialize(callbacks_response_handler)
|
60
|
+
@callbacks_response_handler = callbacks_response_handler
|
61
|
+
end
|
62
|
+
|
63
|
+
def update(*params)
|
64
|
+
method, *arguments = params
|
65
|
+
@callbacks_response_handler.callback_received(method, *arguments)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|