Class: Roby::Interface::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/roby/interface/server.rb

Overview

The server-side object allowing to access an interface (e.g. a Roby app) through any communication channel

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io, interface, main_thread: Thread.current) ⇒ Server



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/roby/interface/server.rb', line 19

def initialize(io, interface, main_thread: Thread.current)
    @notifications_enabled = true
    @io = io
    @interface = interface
    @main_thread = main_thread
    @pending_notifications = Queue.new

    interface.on_cycle_end do
        write_packet(
            [
                :cycle_end,
                interface.execution_engine.cycle_index,
                interface.execution_engine.cycle_start
            ], defer_exceptions: true)
    end
    interface.on_notification do |*args|
        if notifications_enabled?
            @pending_notifications << args
        end
        if Thread.current == @main_thread
            flush_pending_notifications
        end
    end
    interface.on_ui_event do |*args|
        write_packet([:ui_event, *args], defer_exceptions: true)
    end
    interface.on_job_notification do |*args|
        write_packet([:job_progress, *args], defer_exceptions: true)
    end
    interface.on_exception do |*args|
        write_packet([:exception, *args], defer_exceptions: true)
    end
end

Instance Attribute Details

#client_idString (readonly)



11
12
13
# File 'lib/roby/interface/server.rb', line 11

def client_id
  @client_id
end

#interfaceInterface (readonly)



9
10
11
# File 'lib/roby/interface/server.rb', line 9

def interface
  @interface
end

#ioDRobyChannel (readonly)



7
8
9
# File 'lib/roby/interface/server.rb', line 7

def io
  @io
end

Instance Method Details

#closeObject



85
86
87
# File 'lib/roby/interface/server.rb', line 85

def close
    io.close
end

#closed?Boolean



81
82
83
# File 'lib/roby/interface/server.rb', line 81

def closed?
    io.closed?
end

#disable_notificationsObject



77
78
79
# File 'lib/roby/interface/server.rb', line 77

def disable_notifications
    self.notifications_enabled = false
end

#enable_notificationsObject



73
74
75
# File 'lib/roby/interface/server.rb', line 73

def enable_notifications
    self.notifications_enabled = true
end

#flush_pending_notificationsObject



53
54
55
56
57
58
59
60
61
# File 'lib/roby/interface/server.rb', line 53

def flush_pending_notifications
    notifications = []
    until @pending_notifications.empty?
        notifications << @pending_notifications.pop
    end
    notifications.each do |args|
        write_packet([:notification, *args], defer_exceptions: true)
    end
end

#handshake(id) ⇒ Object



67
68
69
70
71
# File 'lib/roby/interface/server.rb', line 67

def handshake(id)
    @client_id = id
    Roby::Interface.info "new interface client: #{id}"
    [interface.actions, interface.commands]
end

#has_deferred_exception?Boolean



106
107
108
# File 'lib/roby/interface/server.rb', line 106

def has_deferred_exception?
    @deferred_exception
end

#notifications_enabled?Boolean



14
# File 'lib/roby/interface/server.rb', line 14

attr_predicate :notifications_enabled?, true

#pollObject

Process one command from the client, and send the reply

Raises:

  • (@deferred_exception)


123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/roby/interface/server.rb', line 123

def poll
    raise @deferred_exception if has_deferred_exception?

    path, m, *args = io.read_packet
    return unless m

    begin
        reply =
            if m == :process_batch
                process_batch(path, args.first)
            else
                process_call(path, m, *args)
            end

        true
    rescue Exception => e
        write_packet([:bad_call, e])
        return
    end

    begin
        write_packet([:reply, reply])
    rescue ComError
        raise
    rescue Exception => e
        write_packet([:protocol_error, e])
        raise
    end
end

#process_batch(path, calls) ⇒ Object



89
90
91
92
93
# File 'lib/roby/interface/server.rb', line 89

def process_batch(path, calls)
    calls.map do |p, m, *a|
        process_call(path + p, m, *a)
    end
end

#process_call(path, name, *args) ⇒ Object



95
96
97
98
99
100
101
102
103
104
# File 'lib/roby/interface/server.rb', line 95

def process_call(path, name, *args)
    if path.empty? && respond_to?(name)
        send(name, *args)
    else
        receiver = path.inject(interface) do |obj, subcommand|
            obj.send(subcommand)
        end
        receiver.send(name, *args)
    end
end

#to_ioObject



63
64
65
# File 'lib/roby/interface/server.rb', line 63

def to_io
    io.to_io
end

#write_packet(call, defer_exceptions: false) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/roby/interface/server.rb', line 110

def write_packet(call, defer_exceptions: false)
    return if has_deferred_exception?

    flush_pending_notifications
    io.write_packet(call)
rescue Exception => e
    if defer_exceptions
        @deferred_exception = e
    else raise
    end
end