cirrocumulus 0.9.7 → 0.9.8

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.
@@ -1,3 +1,4 @@
1
+ require 'log4r'
1
2
  require_relative 'channels/jabber'
2
3
 
3
4
  #
@@ -150,7 +151,7 @@ class ChannelFactory
150
151
  if ontology_instance
151
152
  return ThreadChannel.new(Ontology.query_ontology_instance(agent))
152
153
  else
153
- puts "[WARN] Thread-local ontology not found for identifier=%s" % agent.to_s
154
+ Logger['channels::factory'].warn "Thread-local ontology not found for identifier=%s" % agent.to_s
154
155
  end
155
156
  elsif agent.is_a?(RemoteIdentifier)
156
157
  jabber_client = JabberChannel.query_client(instance.to_s)
@@ -158,11 +159,11 @@ class ChannelFactory
158
159
  if jabber_client
159
160
  return NetworkChannel.new(jabber_client, agent.to_s)
160
161
  else
161
- puts "[WARN] No active Jabber clients."
162
+ Logger['channels::factory'].warn "No active Jabber clients."
162
163
  end
163
164
  end
164
165
 
165
- puts "[WARN] No suitable channel found for #{agent.to_s} (#{agent.class.name})"
166
+ Logger['channels::factory'].warn "No suitable channel found for #{agent.to_s} (#{agent.class.name})"
166
167
  nil
167
168
  end
168
169
  end
@@ -7,7 +7,7 @@ class JabberIdentifier < RemoteIdentifier
7
7
  def initialize(jid)
8
8
  @jid = "#{Cirrocumulus::Environment.current.name}-#{jid}"
9
9
  @channel = JabberChannel.new()
10
- @channel.connect(@jid, 'q1w2e3r4')
10
+ @channel.connect(@jid)
11
11
  @thrd = Thread.new do
12
12
  parser = Sexpistol.new
13
13
  while true do
@@ -66,8 +66,10 @@ class JabberIdentifier < RemoteIdentifier
66
66
  instance.handle_failure(id, action_content[0], action_content[1], options)
67
67
  end
68
68
  rescue Exception => ex
69
- puts ex.message
70
- puts ex.backtrace.to_s
69
+ Log4r::Logger['channels'].warn("Failed to process incoming message")
70
+ Log4r::Logger['channels'].debug("Message body: #{msg.body}")
71
+ Log4r::Logger['channels'].debug("Exception: #{ex.message}")
72
+ Log4r::Logger['channels'].debug("Backtrace: #{ex.backtrace.join("\n")}")
71
73
  end
72
74
  end
73
75
  end
@@ -97,12 +99,12 @@ class JabberChannel
97
99
  @@server = server
98
100
  end
99
101
 
100
- def conference(conf)
101
- @@conference = conf
102
+ def password(pass)
103
+ @@password = pass
102
104
  end
103
105
 
104
- def jid_suffix(suffix)
105
- @@jid_suffix = suffix
106
+ def conference(conf)
107
+ @@conference = conf
106
108
  end
107
109
  end
108
110
 
@@ -123,24 +125,26 @@ class JabberChannel
123
125
  @jabber && @jabber.connected?
124
126
  end
125
127
 
126
- def connect(jid, password)
127
- @full_jid = "%s@%s" % [jid, @@jid_suffix || @server]
128
+ def connect(jid)
129
+ @full_jid = "%s@%s" % [jid, @server]
128
130
  @jid = jid
129
131
 
130
- puts "Using jid #{@jid}"
132
+ Log4r::Logger['channels::jabber'].info "Server: #{@server}"
133
+ Log4r::Logger['channels::jabber'].info "JID: '#{@jid}'"
131
134
 
132
135
  begin
133
- @jabber = Jabber::Simple.new(@full_jid, password)
136
+ @jabber = Jabber::Simple.new(@full_jid, @@password)
134
137
  rescue Jabber::ClientAuthenticationFailure => ex
135
- puts ex.class.name
136
- puts ex.to_s
138
+ Log4r::Logger['channels::jabber'].debug('Received Jabber::ClientAuthenticationFailure, registering new account')
137
139
  client = Jabber::Client.new(@full_jid)
138
140
  client.connect()
139
141
  client.register(password)
140
142
  client.close()
141
- @jabber = Jabber::Simple.new(@full_jid, password)
143
+ @jabber = Jabber::Simple.new(@full_jid, @@password)
142
144
  rescue Exception => ex
143
- puts ex.to_s
145
+ Log4::Logger['channels::jabber'].fatal('Failed to register new account or connect.')
146
+ Log4::Logger['channels::jabber'].fatal("Received exception: #{ex.to_s}")
147
+ return false
144
148
  end
145
149
 
146
150
  join_conference(@conference) if connected?
@@ -182,6 +186,7 @@ class JabberChannel
182
186
  protected
183
187
 
184
188
  def join_conference(conference)
185
- @jabber.send!("<presence to='#{conference}@conference.#{@@jid_suffix || @server}/#{@jid}' />")
189
+ Log4r::Logger['channels::jabber'].info "Joining conference '#{conference}'"
190
+ @jabber.send!("<presence to='#{conference}@conference.#{@server}/#{@jid}' />")
186
191
  end
187
192
  end
@@ -1,3 +1,5 @@
1
+ require 'log4r'
2
+
1
3
  module Cirrocumulus
2
4
  #
3
5
  # Cirrocumulus environment. It is a container where all ontologies will be loaded.
@@ -11,7 +13,7 @@ module Cirrocumulus
11
13
  attr_reader :name
12
14
 
13
15
  def initialize(name)
14
- puts "Loading #{name} Cirrocumulus environment."
16
+ Log4r::Logger['agent'].info "Loading #{name} Cirrocumulus environment"
15
17
 
16
18
  @name = name
17
19
  @ontologies = []
@@ -22,7 +24,7 @@ module Cirrocumulus
22
24
  # Loads ontology instance into environment.
23
25
  #
24
26
  def load_ontology(ontology_instance)
25
- puts "Adding #{ontology_instance.name} ontology."
27
+ Log4r::Logger['agent'].info "Adding #{ontology_instance.name} ontology"
26
28
  @ontologies << ontology_instance
27
29
  end
28
30
 
@@ -74,9 +74,9 @@ class KnowledgeClass
74
74
  def to_template
75
75
  description = @@classes[self.name]
76
76
  fact = [description.name.to_sym]
77
- fact << description.primary_key.upcase.to_sym
77
+ fact << description.primary_key.upcase.to_sym if description.primary_key
78
78
  description.properties.each do |k|
79
- next if k == description.primary_key
79
+ next if k == description.primary_key && description.primary_key
80
80
 
81
81
  fact << k.to_sym
82
82
  fact << k.upcase.to_sym
@@ -106,7 +106,7 @@ class KnowledgeClass
106
106
  @values = {}
107
107
 
108
108
  description = @@classes[self.class.name]
109
- if options.has_key?(description.primary_key.to_sym)
109
+ if description.primary_key && options.has_key?(description.primary_key.to_sym)
110
110
  @values[description.primary_key] = options[description.primary_key.to_sym]
111
111
  end
112
112
 
@@ -120,7 +120,7 @@ class KnowledgeClass
120
120
  def to_template
121
121
  description = @@classes[self.class.name]
122
122
  fact = [description.name.to_sym]
123
- fact << values[description.primary_key]
123
+ fact << values[description.primary_key] if description.primary_key
124
124
  description.properties.each do |k|
125
125
  next if k == description.primary_key
126
126
 
@@ -134,9 +134,9 @@ class KnowledgeClass
134
134
  def to_params
135
135
  description = @@classes[self.class.name]
136
136
  fact = [description.name.to_sym]
137
- fact << (values.has_key?(description.primary_key) ? values[description.primary_key] : description.primary_key.upcase.to_sym)
137
+ fact << (values.has_key?(description.primary_key) ? values[description.primary_key] : description.primary_key.upcase.to_sym) if description.primary_key
138
138
  description.properties.each do |k|
139
- next if k == description.primary_key
139
+ next if k == description.primary_key && description.primary_key
140
140
 
141
141
  fact << k.to_sym
142
142
  fact << (values.has_key?(k) ? values[k] : k.upcase.to_sym)
@@ -95,6 +95,7 @@ class Ontology
95
95
  @classes = []
96
96
  @last_saga_id = 0
97
97
  @sagas = []
98
+ @last_tick_time = Time.now
98
99
 
99
100
  self.class.register_ontology_instance(self)
100
101
  @mutex = Mutex.new
@@ -112,6 +113,12 @@ class Ontology
112
113
  while self.running do
113
114
  ontology.timeout_facts
114
115
  @rule_queue.run_queued_rules
116
+
117
+ if Time.now - @last_tick_time > 1
118
+ ontology.tick
119
+ @last_tick_time = Time.now
120
+ end
121
+
115
122
  sleep 0.1
116
123
  end
117
124
  end
@@ -219,7 +226,7 @@ class Ontology
219
226
  # Inform another agent about a fact. Normally, it will be added to it's KB.
220
227
  #
221
228
  def inform(agent, fact, options = {})
222
- puts "%25s | inform %s about %s %s" % [identifier, agent, Sexpistol.new.to_sexp(fact), print_message_options(options)]
229
+ info "%25s | inform %s about %s %s" % [identifier, agent, Sexpistol.new.to_sexp(fact), print_message_options(options)]
223
230
 
224
231
  channel = ChannelFactory.retrieve(identifier, agent)
225
232
  channel.inform(identifier, fact, options) if channel
@@ -233,7 +240,7 @@ class Ontology
233
240
  # The action of agreeing to perform some action, possibly in the future.
234
241
  #
235
242
  def agree(agent, action, options = {})
236
- puts "%25s | agree with %s to perform %s %s" % [identifier, agent, Sexpistol.new.to_sexp(action), print_message_options(options)]
243
+ info "%25s | agree with %s to perform %s %s" % [identifier, agent, Sexpistol.new.to_sexp(action), print_message_options(options)]
237
244
 
238
245
  channel = ChannelFactory.retrieve(identifier, agent)
239
246
  channel.agree(identifier, action, options) if channel
@@ -243,7 +250,7 @@ class Ontology
243
250
  # The action of refusing to perform a given action, and explaining the reason for the refusal.
244
251
  #
245
252
  def refuse(agent, action, reason, options = {})
246
- puts "%25s | refuse %s to perform %s because %s %s" % [identifier, agent, Sexpistol.new.to_sexp(action), Sexpistol.new.to_sexp(reason), print_message_options(options)]
253
+ info "%25s | refuse %s to perform %s because %s %s" % [identifier, agent, Sexpistol.new.to_sexp(action), Sexpistol.new.to_sexp(reason), print_message_options(options)]
247
254
 
248
255
  channel = ChannelFactory.retrieve(identifier, agent)
249
256
  channel.refuse(identifier, action, reason, options) if channel
@@ -253,7 +260,7 @@ class Ontology
253
260
  # The action of telling another agent that an action was attempted but the attempt failed.
254
261
  #
255
262
  def failure(agent, action, reason = true , options = {})
256
- puts "%25s | inform %s that action %s failed with reason %s %s" % [identifier, agent, Sexpistol.new.to_sexp(action), Sexpistol.new.to_sexp(reason), print_message_options(options)]
263
+ info "%25s | inform %s that action %s failed with reason %s %s" % [identifier, agent, Sexpistol.new.to_sexp(action), Sexpistol.new.to_sexp(reason), print_message_options(options)]
257
264
 
258
265
  channel = ChannelFactory.retrieve(identifier, agent)
259
266
  channel.failure(identifier, action, reason, options) if channel
@@ -263,7 +270,7 @@ class Ontology
263
270
  # Send request to another agent.
264
271
  #
265
272
  def request(agent, contents, options = {})
266
- puts "%25s | %s -> %s" % [identifier.to_s, Sexpistol.new.to_sexp(contents), agent.to_s]
273
+ info "%25s | %s -> %s" % [identifier.to_s, Sexpistol.new.to_sexp(contents), agent.to_s]
267
274
 
268
275
  channel = ChannelFactory.retrieve(identifier, agent)
269
276
  channel.request(identifier, contents) if channel
@@ -274,7 +281,7 @@ class Ontology
274
281
  end
275
282
 
276
283
  def query(agent, expression, options = {})
277
- puts "%25s | query %s about %s %s" % [identifier, agent, Sexpistol.new.to_sexp(expression), print_message_options(options)]
284
+ info "%25s | query %s about %s %s" % [identifier, agent, Sexpistol.new.to_sexp(expression), print_message_options(options)]
278
285
 
279
286
  channel = ChannelFactory.retrieve(identifier, agent)
280
287
  channel.query(identifier, expression, options) if channel
@@ -297,6 +304,11 @@ class Ontology
297
304
  #
298
305
  def restore_state; end
299
306
 
307
+ #
308
+ # Tick. Every second.
309
+ #
310
+ def tick; end
311
+
300
312
  #
301
313
  # Handles incoming fact. By default, just adds this fact to KB or redirects its processing to corresponding saga
302
314
  #
@@ -325,19 +337,19 @@ class Ontology
325
337
 
326
338
  def handle_agree(sender, action, options = {})
327
339
  if !handle_saga_reply(sender, :agree, action, options)
328
- puts "%25s | %s agreed to perform %s %s" % [identifier, sender, Sexpistol.new.to_sexp(action), print_message_options(options)]
340
+ info "%25s | %s agreed to perform %s %s" % [identifier, sender, Sexpistol.new.to_sexp(action), print_message_options(options)]
329
341
  end
330
342
  end
331
343
 
332
344
  def handle_refuse(sender, action, reason, options = {})
333
345
  if !handle_saga_reply(sender, :refuse, [action, reason], options)
334
- puts "%25s | %s refused to perform %s because %s %s" % [identifier, sender, Sexpistol.new.to_sexp(action), Sexpistol.new.to_sexp(reason), print_message_options(options)]
346
+ info "%25s | %s refused to perform %s because %s %s" % [identifier, sender, Sexpistol.new.to_sexp(action), Sexpistol.new.to_sexp(reason), print_message_options(options)]
335
347
  end
336
348
  end
337
349
 
338
350
  def handle_failure(sender, action, reason, options = {})
339
351
  if !handle_saga_reply(sender, :failure, [action, reason], options)
340
- puts "%25s | %s failed to perform %s because %s %s" % [identifier, sender, Sexpistol.new.to_sexp(action), Sexpistol.new.to_sexp(reason), print_message_options(options)]
352
+ info "%25s | %s failed to perform %s because %s %s" % [identifier, sender, Sexpistol.new.to_sexp(action), Sexpistol.new.to_sexp(reason), print_message_options(options)]
341
353
  end
342
354
  end
343
355
 
@@ -346,12 +358,12 @@ class Ontology
346
358
  #
347
359
  def handle_request(sender, contents, options = {})
348
360
  if !handle_saga_reply(sender, :request, contents, options)
349
- puts "%25s | %s requests to perform %s %s" % [identifier, sender, Sexpistol.new.to_sexp(contents), print_message_options(options)]
361
+ info "%25s | %s requests to perform %s %s" % [identifier, sender, Sexpistol.new.to_sexp(contents), print_message_options(options)]
350
362
  end
351
363
  end
352
364
 
353
365
  def handle_query(sender, expression, options = {})
354
- puts "%25s | %s queries %s %s" % [identifier, sender, Sexpistol.new.to_sexp(expression), print_message_options(options)] unless handle_saga_reply(sender, :query, expression, options)
366
+ info "%25s | %s queries %s %s" % [identifier, sender, Sexpistol.new.to_sexp(expression), print_message_options(options)] unless handle_saga_reply(sender, :query, expression, options)
355
367
  end
356
368
 
357
369
  #
@@ -425,8 +437,12 @@ class Ontology
425
437
  "[%s]" % options.map {|k,v| "%s=%s" % [k, v]}.join(',')
426
438
  end
427
439
 
440
+ def info(msg)
441
+ Log4r::Logger['ontology'].info(msg)
442
+ end
443
+
428
444
  def debug(msg)
429
- puts "[DBG] %s" % msg
445
+ Log4r::Logger['ontology'].debug(msg)
430
446
  end
431
447
 
432
448
  end
@@ -25,7 +25,17 @@ class RuleQueue
25
25
 
26
26
  def push(entry)
27
27
  @mutex.synchronize do
28
- @queue.push(QueueEntry.new(entry)) unless @queue.find {|e| e.state != :finished && e.run_data == entry}
28
+ return if @queue.find {|e| e != :marker && e.state != :finished && e.run_data == entry}
29
+
30
+ if entry.rule.options.has_key?(:for)
31
+ delay = entry.rule.options[:for]
32
+ run_at = Time.now + delay
33
+ debug("Enqueued rule #{entry.rule.name}#{entry.parameters.inspect}")
34
+ debug("And will execute this rule after #{delay} sec (at #{run_at.strftime("%H:%M:%S %d.%m.%Y")})")
35
+ @queue.push(QueueEntry.new(entry, run_at))
36
+ else
37
+ @queue.push(QueueEntry.new(entry))
38
+ end
29
39
  end
30
40
  end
31
41
 
@@ -42,10 +52,13 @@ class RuleQueue
42
52
  end
43
53
 
44
54
  def run_queued_rules
45
- while (entry = pop) != nil do
55
+ @queue.push :marker
56
+
57
+ while (entry = pop) != :marker do
46
58
  next if entry.state == :finished
47
- if entry.run_at && (entry.run_at < Time.now)
48
- push(entry)
59
+
60
+ if !entry.run_at.nil? && (entry.run_at > Time.now)
61
+ @queue.push(entry)
49
62
  next
50
63
  end
51
64
 
@@ -55,7 +68,7 @@ class RuleQueue
55
68
  entry.rule.code.call(@ontology_instance, entry.params)
56
69
  entry.state
57
70
  rescue Exception => e
58
- puts "[WARN] Exception while executing rule: %s\n%s" % [e.to_s, e.backtrace.to_s]
71
+ warn "Exception while executing rule: %s\n%s" % [e.to_s, e.backtrace.to_s]
59
72
  end
60
73
  end
61
74
  end
@@ -64,6 +77,11 @@ class RuleQueue
64
77
  private
65
78
 
66
79
  def debug(msg)
67
- puts msg
80
+ Log4r::Logger['ontology::run_queue'].debug(msg)
68
81
  end
82
+
83
+ def warn(msg)
84
+ Log4r::Logger['ontology::run_queue'].warn(msg)
85
+ end
86
+
69
87
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cirrocumulus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 0.9.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: