class Roby::Interface::Async::Log
Asynchronous access to the log stream
Roby
logs are purely incremental information, which means that on connection one must process the whole existing log before being able to provide the current state. From a user perspective, this init phase is really overhead, so it's better to avoid updating the UI while the data is being processed. For this reason, the class provides {#on_init_progress} and {#on_init_done} to provide progress information to the user, and start normal processing when init is finished.
It must be integrated into your application's event loop by calling {#poll}.
Constants
- DEFAULT_HOST
- DEFAULT_PORT
- STATE_CONNECTED
- STATE_DISCONNECTED
- STATE_PENDING_DATA
Attributes
@return [Roby::DRoby::Logfile::Client,nil] the object used to communicate
to the server, or nil if we have not managed to connect yet
The future used to connect to the remote process without blocking the main event loop
@!endgroup
The plan rebuilder object, which processes the log stream to rebuild {#plan}
@return [Roby::DRoby::PlanRebuilder]
Public Class Methods
# File lib/roby/interface/async/log.rb, line 88 def initialize(host = DEFAULT_REMOTE_NAME, port: DEFAULT_PORT, connect: true, plan_rebuilder: default_plan_rebuilder) @host = host @port = port @plan_rebuilder = plan_rebuilder @first_connection_attempt = true @closed = false if connect attempt_connection end end
Public Instance Methods
Start a connection attempt
# File lib/roby/interface/async/log.rb, line 105 def attempt_connection @connection_future = Concurrent::Future.new do Roby::DRoby::Logfile::Client.new(host, port) end connection_future.execute end
# File lib/roby/interface/async/log.rb, line 231 def clear_integrated plan_rebuilder.clear_integrated end
# File lib/roby/interface/async/log.rb, line 164 def close @closed = true unreachable! plan_rebuilder.clear end
# File lib/roby/interface/async/log.rb, line 160 def closed? !!@closed end
# File lib/roby/interface/async/log.rb, line 100 def connected? !!client end
# File lib/roby/interface/async/log.rb, line 175 def cycle_index plan_rebuilder && plan_rebuilder.cycle_index end
# File lib/roby/interface/async/log.rb, line 179 def cycle_start_time plan_rebuilder && plan_rebuilder.cycle_start_time end
@api private
Create a plan rebuilder for use in the async object
# File lib/roby/interface/async/log.rb, line 84 def default_plan_rebuilder DRoby::PlanRebuilder.new end
# File lib/roby/interface/async/log.rb, line 183 def init_done? client && client.init_done? end
The plan self is working on
@return [Roby::Plan]
# File lib/roby/interface/async/log.rb, line 33 def plan; plan_rebuilder.plan end
Active part of the async. This has to be called regularly within the system's main event loop (e.g. Roby's, Vizkit's or Qt's)
@return [(Boolean,Boolean)] true if we are connected to the remote server
and false otherwise
# File lib/roby/interface/async/log.rb, line 121 def poll(max: 0.1) if connected? if client.read_and_process_pending(max: max) return STATE_PENDING_DATA else return STATE_CONNECTED end elsif !closed? poll_connection_attempt return STATE_DISCONNECTED end rescue Interrupt close raise rescue ComError Log.info "link closed, trying to reconnect" unreachable! if !closed? attempt_connection end false rescue Exception => e Log.warn "error while polling connection, trying to reconnect" Roby.log_exception_with_backtrace(e, Log, :warn) unreachable! if !closed? attempt_connection end false end
Verify the state of the last connection attempt
It checks on the last connection attempt, and sets {#client} if it was successful, as well as call the callbacks registered with {#on_reachable}
# File lib/roby/interface/async/log.rb, line 192 def poll_connection_attempt return if client return if closed? if connection_future.complete? case e = connection_future.reason when ConnectionError, ComError Interface.info "Async::Log failed connection attempt: #{e}" attempt_connection if @first_connection_attempt @first_connection_attempt = false run_hook :on_unreachable end nil when NilClass Interface.info "successfully connected" @client = connection_future.value plan_rebuilder.clear run_hook :on_reachable client.on_init_progress do |received, expected| run_hook :on_init_progress, received, expected end client.on_init_done do run_hook :on_init_done end client.on_data do |data| plan_rebuilder.process_one_cycle(data) cycle = plan_rebuilder.cycle_index time = plan_rebuilder.cycle_start_time Interface.debug "Async update(#{cycle}, #{time})" run_hook :on_update, cycle, time end else raise connection_future.reason end end end
True if we are connected to a client
# File lib/roby/interface/async/log.rb, line 171 def reachable? !!client end
Information about the scheduler state
@return [Schedulers::State]
# File lib/roby/interface/async/log.rb, line 38 def scheduler_state; plan.consolidated_scheduler_state end
# File lib/roby/interface/async/log.rb, line 152 def unreachable! if client client.close if !client.closed? @client = nil run_hook :on_unreachable end end