Revision fd4ccbdd
Added by Marc Dequènes over 13 years ago
- ID fd4ccbddaa0989a06add8eac41dba03823d784b2
lib/cyborghood/cyborg/botnet_dsl.rb | ||
---|---|---|
@success_cb = nil
|
||
@calls = {}
|
||
@calls_reply = {}
|
||
@notifications = {}
|
||
@notifications_awaiting = 0
|
||
@notifications_received = 0
|
||
|
||
@final_reply = {
|
||
:results => {},
|
||
:errors => {}
|
||
:errors => {},
|
||
:notifications => {}
|
||
}
|
||
|
||
@notification_name = "task/#{@name}"
|
||
end
|
||
|
||
def on_error(&callback)
|
||
... | ... | |
}
|
||
end
|
||
|
||
def send_notification(name, data)
|
||
name = @notification_name if name == :thread
|
||
Logger.instance.debug "Sending notification to '#{name}'"
|
||
@conversation.bot.get_channel(name) << data
|
||
end
|
||
|
||
# TODO: implement settable timeout
|
||
def wait_notification(name, criterias = {})
|
||
name = @notification_name if name == :thread
|
||
@notifications[name] ||= []
|
||
@notifications[name] << criterias
|
||
@notifications_awaiting += 1
|
||
end
|
||
|
||
protected
|
||
|
||
def _start_dsl
|
||
return if @calls.empty? and @notifications.empty?
|
||
|
||
@conversation.thread(@name) do |conv_thread|
|
||
conv_thread.lock(@name)
|
||
|
||
@calls.each_pair do |key, data|
|
||
conv_thread.call(data[:cmd], *data[:args]) do |reply|
|
||
@calls_reply[key] = reply[:status]
|
||
... | ... | |
@final_reply[:errors][key] = reply[:exception]
|
||
end
|
||
|
||
check_finished
|
||
_check_finished(conv_thread)
|
||
end
|
||
end
|
||
|
||
@notifications.each_pair do |name, list|
|
||
subcription_id = @conversation.bot.get_channel(name).subscribe do |msg|
|
||
old_notifications_received = @notifications_received
|
||
list.each do |criterias|
|
||
if _notification_criterias_match(msg, criterias)
|
||
@final_reply[:notifications][name] ||= []
|
||
@final_reply[:notifications][name] << msg
|
||
@notifications_received += 1
|
||
# do not break, the same message may satisfy multiple criterias
|
||
end
|
||
end
|
||
if @final_reply[:notifications][name].size == @notifications[name].size
|
||
@conversation.bot.get_channel(name).unsubscribe(subcription_id)
|
||
end
|
||
_check_finished(conv_thread) if @notifications_received > old_notifications_received
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
def check_finished
|
||
return unless @calls.size == @calls_reply.size
|
||
def _notification_criterias_match(msg, criterias)
|
||
criterias.each_pair do |key, expected_val|
|
||
val = msg[key]
|
||
if expected_val.is_a? Regexp
|
||
return false if val !~ expected_val
|
||
else
|
||
return false if val != expected_val
|
||
end
|
||
end
|
||
true
|
||
end
|
||
|
||
def _check_finished(conv_thread)
|
||
return unless @calls.size == @calls_reply.size and
|
||
@notifications_received == @notifications_awaiting
|
||
|
||
conv_thread.unlock(@name)
|
||
|
||
# process reply in the same thread, but with a new DSL Thread context
|
||
cb = @calls_reply.values.index(:error) ? @error_cb : @success_cb
|
Also available in: Unified diff
[evol] preliminary work for Conversation synchronization in DSL (action callbacks had to be moved from Protocol to ConversationThread to be able to check idle with the new locks, needed to process notifications without falling idle)