openwferu 0.9.10.653 → 0.9.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/README.txt +65 -33
  2. data/examples/README.txt +4 -0
  3. data/examples/flowtracing.rb +2 -0
  4. data/examples/homeworkreview.rb +2 -0
  5. data/examples/mano_tracker.rb +2 -0
  6. data/examples/openwferu.rb +3 -1
  7. data/examples/quotereporter.rb +2 -0
  8. data/examples/scheduler_cron_usage.rb +3 -1
  9. data/examples/scheduler_usage.rb +3 -1
  10. data/lib/openwfe/engine/engine.rb +15 -5
  11. data/lib/openwfe/expool/expressionpool.rb +30 -4
  12. data/lib/openwfe/expool/journal.rb +16 -18
  13. data/lib/openwfe/expool/journal_replay.rb +56 -8
  14. data/lib/openwfe/expool/wfidgen.rb +17 -8
  15. data/lib/openwfe/expressions/condition.rb +41 -26
  16. data/lib/openwfe/expressions/expressionmap.rb +7 -0
  17. data/lib/openwfe/expressions/fe_cancel.rb +1 -1
  18. data/lib/openwfe/expressions/fe_concurrence.rb +14 -5
  19. data/lib/openwfe/expressions/fe_cron.rb +3 -1
  20. data/lib/openwfe/expressions/fe_cursor.rb +1 -1
  21. data/lib/openwfe/expressions/fe_fqv.rb +58 -0
  22. data/lib/openwfe/expressions/fe_if.rb +1 -1
  23. data/lib/openwfe/expressions/fe_iterator.rb +5 -0
  24. data/lib/openwfe/expressions/fe_listen.rb +224 -0
  25. data/lib/openwfe/expressions/fe_misc.rb +32 -9
  26. data/lib/openwfe/expressions/fe_participant.rb +26 -6
  27. data/lib/openwfe/expressions/fe_sleep.rb +5 -7
  28. data/lib/openwfe/expressions/fe_timeout.rb +127 -0
  29. data/lib/openwfe/expressions/fe_when.rb +13 -1
  30. data/lib/openwfe/expressions/flowexpression.rb +4 -1
  31. data/lib/openwfe/expressions/time.rb +10 -27
  32. data/lib/openwfe/expressions/timeout.rb +23 -6
  33. data/lib/openwfe/flowexpressionid.rb +7 -6
  34. data/lib/openwfe/listeners/socketlisteners.rb +1 -1
  35. data/lib/openwfe/participants/enoparticipants.rb +103 -47
  36. data/lib/openwfe/participants/participant.rb +29 -3
  37. data/lib/openwfe/participants/participantmap.rb +10 -2
  38. data/lib/openwfe/participants/participants.rb +31 -19
  39. data/lib/openwfe/participants/socketparticipants.rb +3 -1
  40. data/lib/openwfe/rest/controlclient.rb +5 -18
  41. data/lib/openwfe/rest/oldrestservlet.rb +279 -0
  42. data/lib/openwfe/rest/restclient.rb +55 -25
  43. data/lib/openwfe/rest/worklistclient.rb +35 -44
  44. data/lib/openwfe/rest/xmlcodec.rb +79 -69
  45. data/lib/openwfe/rudefinitions.rb +15 -7
  46. data/lib/openwfe/storage/yamlextras.rb +3 -3
  47. data/lib/openwfe/util/observable.rb +64 -7
  48. data/lib/openwfe/util/scheduler.rb +107 -77
  49. data/lib/openwfe/util/workqueue.rb +5 -11
  50. data/lib/openwfe/utils.rb +3 -3
  51. data/lib/openwfe/version.rb +1 -2
  52. data/lib/openwfe/workitem.rb +3 -4
  53. data/lib/openwfe/worklist/oldrest.rb +244 -0
  54. data/lib/openwfe/worklist/storelocks.rb +288 -0
  55. data/lib/openwfe/worklist/storeparticipant.rb +4 -2
  56. data/lib/openwfe/worklist/worklist.rb +297 -0
  57. data/test/cron_test.rb +8 -9
  58. data/test/eno_test.rb +10 -13
  59. data/test/flowtestbase.rb +26 -17
  60. data/test/ft_15_iterator.rb +19 -0
  61. data/test/ft_23c_wait.rb +2 -2
  62. data/test/ft_2b_concurrence.rb +2 -2
  63. data/test/ft_30_socketlistener.rb +5 -1
  64. data/test/ft_32_journal.rb +1 -1
  65. data/test/ft_32c_journal.rb +102 -0
  66. data/test/ft_32d_journal.rb +85 -0
  67. data/test/ft_45_citerator.rb +25 -0
  68. data/test/ft_49_condition.rb +60 -2
  69. data/test/ft_4_misc.rb +15 -0
  70. data/test/ft_50_xml_attribute.rb +4 -4
  71. data/test/ft_53_null_noop_participant.rb +66 -0
  72. data/test/ft_54_listen.rb +223 -0
  73. data/test/ft_55_ptimeout.rb +64 -0
  74. data/test/ft_56_timeout.rb +55 -0
  75. data/test/ft_57_a.rb +109 -0
  76. data/test/ft_tests.rb +7 -0
  77. data/test/hparticipant_test.rb +3 -3
  78. data/test/obs_test.rb +115 -0
  79. data/test/orest_test.rb +224 -0
  80. data/test/pending.rb +24 -0
  81. data/test/rake_qtest.rb +5 -1
  82. data/test/rake_test.rb +4 -0
  83. data/test/scheduler_test.rb +31 -2
  84. data/test/sec_test.rb +7 -3
  85. data/test/slock_test.rb +82 -0
  86. metadata +19 -3
  87. data/test/ft_32b_journal.rb +0 -76
@@ -1,6 +1,6 @@
1
1
  #
2
2
  #--
3
- # Copyright (c) 2005-2007, John Mettraux, org
3
+ # Copyright (c) 2005-2007, John Mettraux, OpenWFE.org
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -51,13 +51,13 @@ module OpenWFE
51
51
  #
52
52
  # Ugly XML codec for OpenWFE workitems
53
53
  #
54
- class XmlCodec
54
+ module XmlCodec
55
55
 
56
56
  #
57
57
  # Takes as input some XML element and returns is decoded
58
58
  # (as an instance)
59
59
  #
60
- def decode (xmlElt)
60
+ def XmlCodec.decode (xmlElt)
61
61
 
62
62
  return nil unless xmlElt
63
63
 
@@ -73,6 +73,7 @@ module OpenWFE
73
73
 
74
74
  #puts "decode() xmlElt.name is >#{xmlElt.name}<"
75
75
 
76
+ return decode_session_id(xmlElt) if xmlElt.name == 'session'
76
77
  return decode_list(xmlElt) if xmlElt.name == STORES
77
78
  return decode_store(xmlElt) if xmlElt.name == STORE
78
79
  return decode_list(xmlElt) if xmlElt.name == HEADERS
@@ -83,10 +84,8 @@ module OpenWFE
83
84
  return decode_list(xmlElt) if xmlElt.name == HISTORY
84
85
  return decode_historyitem(xmlElt) if xmlElt.name == HISTORY_ITEM
85
86
 
86
- return decode_list(xmlElt) \
87
- if xmlElt.name == FLOW_EXPRESSION_IDS
88
- return decode_fei(xmlElt) \
89
- if xmlElt.name == FLOW_EXPRESSION_ID
87
+ return decode_list(xmlElt) if xmlElt.name == FLOW_EXPRESSION_IDS
88
+ return decode_fei(xmlElt) if xmlElt.name == FLOW_EXPRESSION_ID
90
89
 
91
90
  return decode_inflowworkitem(xmlElt) \
92
91
  if xmlElt.name == IN_FLOW_WORKITEM
@@ -114,7 +113,7 @@ module OpenWFE
114
113
  #
115
114
  # Takes some OpenWFE Ruby instance and returns it as XML
116
115
  #
117
- def encode (owfeData)
116
+ def XmlCodec.encode (owfeData)
118
117
 
119
118
  #puts "encode() #{owfeData.inspect}"
120
119
 
@@ -132,18 +131,35 @@ module OpenWFE
132
131
  "Cannot encode : "+owfeData.inspect()
133
132
  end
134
133
 
134
+ def XmlCodec.encode_workitem_as_header (in_flow_workitem, locked)
135
+
136
+ e = REXML::Element.new HEADER
137
+
138
+ e.add_attribute A_LAST_MODIFIED, "#{in_flow_workitem.last_modified}"
139
+ e.add_attribute A_LOCKED, locked
140
+
141
+ e << XmlCodec::encode_fei(in_flow_workitem.fei)
142
+ e << XmlCodec::encode_attributes(in_flow_workitem)
143
+
144
+ e
145
+ end
146
+
135
147
  private
136
148
 
137
149
  #
138
150
  # DECODE
139
151
  #
140
152
 
141
- def decode_list (xmlElt)
153
+ def XmlCodec.decode_session_id (xmlElt)
154
+ Integer(xmlElt.attributes['id'])
155
+ end
156
+
157
+ def XmlCodec.decode_list (xmlElt)
142
158
  xmlElt.elements.collect { |elt| decode(elt) }
143
159
  end
144
160
 
145
161
 
146
- def decode_launchable (xmlElt)
162
+ def XmlCodec.decode_launchable (xmlElt)
147
163
 
148
164
  launchable = Launchable.new()
149
165
 
@@ -154,7 +170,7 @@ module OpenWFE
154
170
  end
155
171
 
156
172
 
157
- def decode_expression (xmlElt)
173
+ def XmlCodec.decode_expression (xmlElt)
158
174
 
159
175
  exp = Expression.new()
160
176
 
@@ -165,11 +181,11 @@ module OpenWFE
165
181
  exp.state = xmlElt.attributes[STATE]
166
182
  exp.state_since = xmlElt.attributes[STATE_SINCE]
167
183
 
168
- return exp
184
+ exp
169
185
  end
170
186
 
171
187
 
172
- def decode_store (xmlElt)
188
+ def XmlCodec.decode_store (xmlElt)
173
189
 
174
190
  store = Store.new()
175
191
 
@@ -178,11 +194,11 @@ module OpenWFE
178
194
  store.workitem_count = Integer(store.workitem_count)
179
195
  store.permissions = xmlElt.attributes[PERMISSIONS]
180
196
 
181
- return store
197
+ store
182
198
  end
183
199
 
184
200
 
185
- def decode_header (xmlElt)
201
+ def XmlCodec.decode_header (xmlElt)
186
202
 
187
203
  header = Header.new()
188
204
 
@@ -191,11 +207,11 @@ module OpenWFE
191
207
  header.flow_expression_id = decode(OpenWFE.first_element(xmlElt, FLOW_EXPRESSION_ID))
192
208
  header.attributes = decode(OpenWFE.first_element(xmlElt, ATTRIBUTES))
193
209
 
194
- return header
210
+ header
195
211
  end
196
212
 
197
213
 
198
- def decode_fei (xmlElt)
214
+ def XmlCodec.decode_fei (xmlElt)
199
215
 
200
216
  fei = FlowExpressionId.new
201
217
 
@@ -219,7 +235,7 @@ module OpenWFE
219
235
  end
220
236
 
221
237
 
222
- def decode_attribute (xmlElt)
238
+ def XmlCodec.decode_attribute (xmlElt)
223
239
 
224
240
  #puts "decodeAttribute() '#{xmlElt.name}' --> '#{xmlElt.text}'"
225
241
 
@@ -273,13 +289,13 @@ module OpenWFE
273
289
  OpenWFE.xmldoc_to_string(xmlElt.document())
274
290
  end
275
291
 
276
- def decode_xmldocument (xmlElt)
292
+ def XmlCodec.decode_xmldocument (xmlElt)
277
293
 
278
294
  s = Base64::decode64 xmlElt.text.strip
279
295
  REXML::Document.new s
280
296
  end
281
297
 
282
- def decode_entry (xmlElt, map)
298
+ def XmlCodec.decode_entry (xmlElt, map)
283
299
 
284
300
  key = xmlElt.elements[1]
285
301
  val = xmlElt.elements[2]
@@ -301,12 +317,12 @@ module OpenWFE
301
317
  map[key] = val
302
318
  end
303
319
 
304
- def parse_boolean (string)
320
+ def XmlCodec.parse_boolean (string)
305
321
 
306
- return string.strip.downcase == 'true'
322
+ string.strip.downcase == 'true'
307
323
  end
308
324
 
309
- def decode_historyitem (xmlElt)
325
+ def XmlCodec.decode_historyitem (xmlElt)
310
326
 
311
327
  hi = HistoryItem.new
312
328
 
@@ -320,21 +336,21 @@ module OpenWFE
320
336
  hi.wf_instance_id = xmlElt.attributes[WORKFLOW_INSTANCE_ID]
321
337
  hi.expression_id = xmlElt.attributes[EXPRESSION_ID]
322
338
 
323
- return hi
339
+ hi
324
340
  end
325
341
 
326
342
 
327
- def decode_launch_ok (xmlElt)
343
+ def XmlCodec.decode_launch_ok (xmlElt)
328
344
 
329
345
  sFei = xmlElt.attributes[A_FLOW_ID]
330
346
 
331
- return true if not sFei
347
+ return true unless sFei
332
348
 
333
349
  FlowExpressionId.to_fei(sFei)
334
350
  end
335
351
 
336
352
 
337
- def decode_inflowworkitem (xmlElt)
353
+ def XmlCodec.decode_inflowworkitem (xmlElt)
338
354
 
339
355
  wi = InFlowWorkItem.new()
340
356
 
@@ -350,13 +366,12 @@ module OpenWFE
350
366
 
351
367
  wi.history = decode(OpenWFE.first_element(xmlElt, HISTORY))
352
368
 
353
- return wi
369
+ wi
354
370
  end
355
371
 
372
+ def XmlCodec.decode_launchitem (xmlElt)
356
373
 
357
- def decode_launchitem (xmlElt)
358
-
359
- li = LaunchItem.new()
374
+ li = LaunchItem.new
360
375
 
361
376
  li.workflow_definition_url =
362
377
  xmlElt.attributes[WORKFLOW_DEFINITION_URL]
@@ -373,19 +388,24 @@ module OpenWFE
373
388
  #
374
389
 
375
390
 
376
- def encode_item (item, elt)
391
+ def XmlCodec.encode_item (item, elt)
377
392
 
378
393
  elt.attributes[A_LAST_MODIFIED] = item.last_modified
379
394
 
395
+ elt << encode_attributes(item)
396
+ end
397
+
398
+ def XmlCodec.encode_attributes (item)
399
+
380
400
  eAttributes = REXML::Element.new(ATTRIBUTES)
381
401
 
382
402
  eAttributes << encode_attribute(item.attributes)
383
403
 
384
- elt << eAttributes
404
+ eAttributes
385
405
  end
386
406
 
387
407
 
388
- def encode_launchitem (launchitem)
408
+ def XmlCodec.encode_launchitem (launchitem)
389
409
 
390
410
  doc = REXML::Document.new()
391
411
 
@@ -408,7 +428,7 @@ module OpenWFE
408
428
  end
409
429
 
410
430
 
411
- def encode_inflowitem (item, elt)
431
+ def XmlCodec.encode_inflowitem (item, elt)
412
432
 
413
433
  encode_item(item, elt)
414
434
 
@@ -422,7 +442,7 @@ module OpenWFE
422
442
  end
423
443
 
424
444
 
425
- def encode_inflowworkitem (item)
445
+ def XmlCodec.encode_inflowworkitem (item)
426
446
 
427
447
  doc = REXML::Document.new()
428
448
 
@@ -440,11 +460,11 @@ module OpenWFE
440
460
 
441
461
  s = OpenWFE.xmldoc_to_string(doc)
442
462
  #puts "encoded :\n#{s}"
443
- return s
463
+ s
444
464
  end
445
465
 
446
466
 
447
- def encode_history (item, elt)
467
+ def XmlCodec.encode_history (item, elt)
448
468
 
449
469
  eHistory = REXML::Element.new(HISTORY)
450
470
 
@@ -468,7 +488,7 @@ module OpenWFE
468
488
  end
469
489
 
470
490
 
471
- def encode_attribute (att)
491
+ def XmlCodec.encode_attribute (att)
472
492
 
473
493
  #puts "encodeAttribute() att.class is #{att.class}"
474
494
 
@@ -505,14 +525,14 @@ module OpenWFE
505
525
  # "Cannot encode attribute of class '#{att.class}'"
506
526
  end
507
527
 
508
- def encode_xmldocument (elt)
528
+ def XmlCodec.encode_xmldocument (elt)
509
529
 
510
530
  e = REXML::Element.new(E_XML_DOCUMENT)
511
531
  e.text = Base64::encode64(elt.to_s)
512
532
  e
513
533
  end
514
534
 
515
- def encode_xmlattribute (elt)
535
+ def XmlCodec.encode_xmlattribute (elt)
516
536
 
517
537
  return elt if elt.name == E_RAW_XML
518
538
 
@@ -526,7 +546,7 @@ module OpenWFE
526
546
  end
527
547
 
528
548
 
529
- def encode_base64attribute (att)
549
+ def XmlCodec.encode_base64attribute (att)
530
550
 
531
551
  e = REXML::Element.new(E_BASE64)
532
552
  e.text = att.content
@@ -535,7 +555,7 @@ module OpenWFE
535
555
  end
536
556
 
537
557
 
538
- def encode_atomicattribute (name, value)
558
+ def XmlCodec.encode_atomicattribute (name, value)
539
559
 
540
560
  elt = REXML::Element.new(name)
541
561
  #elt << REXML::Text.new(value.to_s())
@@ -545,7 +565,7 @@ module OpenWFE
545
565
  end
546
566
 
547
567
 
548
- def encode_listattribute (list)
568
+ def XmlCodec.encode_listattribute (list)
549
569
 
550
570
  elt = REXML::Element.new(E_LIST)
551
571
 
@@ -553,11 +573,11 @@ module OpenWFE
553
573
  elt << encode_attribute(e)
554
574
  end
555
575
 
556
- return elt
576
+ elt
557
577
  end
558
578
 
559
579
 
560
- def encode_mapattribute (hash)
580
+ def XmlCodec.encode_mapattribute (hash)
561
581
 
562
582
  name = hash[MAP_TYPE]
563
583
  name = 'map' if name == nil
@@ -578,11 +598,11 @@ module OpenWFE
578
598
  elt << eEntry
579
599
  end
580
600
 
581
- return elt
601
+ elt
582
602
  end
583
603
 
584
604
 
585
- def encode_fei (fei)
605
+ def XmlCodec.encode_fei (fei)
586
606
 
587
607
  elt = REXML::Element.new(FLOW_EXPRESSION_ID)
588
608
 
@@ -598,43 +618,33 @@ module OpenWFE
598
618
  elt.attributes[EXPRESSION_NAME] = fei.expression_name
599
619
  elt.attributes[EXPRESSION_ID] = fei.expression_id
600
620
 
601
- return elt
621
+ elt
602
622
  end
603
623
  end
604
624
 
605
- XMLCODEC = XmlCodec.new
606
- #
607
- # some kind of a singleton, rather a lonelyton
608
-
609
- #
610
- # Decodes any XML blurb produced by OpenWFE[ja] into a Ruby instance.
611
- #
612
- def OpenWFE.xml_decode (xmlelt)
613
- XMLCODEC.decode(xmlelt)
614
- end
615
-
616
- #
617
- # Encodes to XML (OpenWFE dialect ;) ) workitems and launch items.
618
- #
619
- def OpenWFE.xml_encode (owfedata)
620
- XMLCODEC.encode(owfedata)
621
- end
622
-
623
625
  #
624
626
  # Just turns some XML to a String (if decl is set to false, no
625
627
  # XML declaration will be printed).
626
628
  #
627
629
  def OpenWFE.xmldoc_to_string (xml, decl=true)
628
630
 
629
- s = ""
631
+ #return xml if xml.is_a?(String)
630
632
 
631
- if decl and xml[0].kind_of? REXML::XMLDecl
633
+ if decl and (not xml[0].is_a?(REXML::XMLDecl))
632
634
  xml << REXML::XMLDecl.new()
633
635
  end
634
636
 
637
+ s = ""
635
638
  xml.write(s, 0)
636
639
  return s
637
640
  end
638
641
 
642
+ #
643
+ # An alias for OpenWFE::xmldoc_to_string()
644
+ #
645
+ def OpenWFE.xml_to_s (xml, decl=true)
646
+ OpenWFE::xmldoc_to_string(xml, decl)
647
+ end
648
+
639
649
  end
640
650
 
@@ -90,25 +90,33 @@ module OpenWFE
90
90
  module OwfeServiceLocator
91
91
 
92
92
  def get_engine
93
- return @application_context[S_ENGINE]
93
+ @application_context[S_ENGINE]
94
94
  end
95
95
  def get_scheduler
96
- return @application_context[S_SCHEDULER]
96
+ @application_context[S_SCHEDULER]
97
97
  end
98
98
  def get_expression_map
99
- return @application_context[S_EXPRESSION_MAP]
99
+ @application_context[S_EXPRESSION_MAP]
100
100
  end
101
101
  def get_wfid_generator
102
- return @application_context[S_WFID_GENERATOR]
102
+ @application_context[S_WFID_GENERATOR]
103
103
  end
104
104
  def get_expression_pool
105
- return @application_context[S_EXPRESSION_POOL]
105
+ @application_context[S_EXPRESSION_POOL]
106
106
  end
107
107
  def get_expression_storage
108
- return @application_context[S_EXPRESSION_STORAGE]
108
+ @application_context[S_EXPRESSION_STORAGE]
109
109
  end
110
110
  def get_participant_map
111
- return @application_context[S_PARTICIPANT_MAP]
111
+ @application_context[S_PARTICIPANT_MAP]
112
+ end
113
+
114
+ #
115
+ # Returns the 'journal' service (or nil if there is no
116
+ # journal service available).
117
+ #
118
+ def get_journal
119
+ @application_context['journal']
112
120
  end
113
121
 
114
122
  #
@@ -60,11 +60,11 @@ module OpenWFE
60
60
 
61
61
  l.delete("@application_context")
62
62
 
63
- l.delete("@timeout_job_id")
63
+ #l.delete("@timeout_job_id")
64
64
  #l.delete("@scheduler_job_id")
65
65
  # scheduler ids should not get persisted
66
66
 
67
- return l
67
+ l
68
68
  end
69
69
  end
70
70
 
@@ -108,7 +108,7 @@ module OpenWFE
108
108
  def to_yaml_properties
109
109
  l = super()
110
110
  l.delete("@raw_representation")
111
- return l
111
+ l
112
112
  end
113
113
  end
114
114
  end
@@ -53,29 +53,86 @@ module OpenWFE
53
53
  # Observers will register themselves to the Observable via
54
54
  # this method.
55
55
  #
56
- def add_observer (channel, &callback)
57
- (@observers[channel] ||= []) << callback
56
+ # An observer is an instance which responds to call(channel, *args)
57
+ #
58
+ def add_observer (channel, observer=nil, &callback)
59
+ observer = callback unless observer
60
+ (@observers[channel] ||= []) << observer
61
+ end
62
+
63
+ #
64
+ # Removes an observer (this obviously doesn't work well when
65
+ # the actual observer is a block).
66
+ # If a channel is given, the observer will only get removed when
67
+ # registered for that channel.
68
+ #
69
+ def remove_observer (observer, channel=nil)
70
+
71
+ channels = if channel
72
+ [ channel ]
73
+ else
74
+ @observers.keys
75
+ end
76
+
77
+ channels.each do |c|
78
+ do_remove_observer observer, c
79
+ end
58
80
  end
59
81
 
60
82
  protected
61
83
 
62
84
  #
63
85
  # Observable classes do call this method to notify their
64
- # observers
86
+ # observers.
87
+ #
88
+ # Returns true if there was an observer registered.
65
89
  #
66
90
  def onotify (channel, *args)
67
- do_notify(channel, channel, *args)
91
+
68
92
  do_notify(:all, channel, *args)
93
+ do_notify(channel, channel, *args)
69
94
  end
70
95
 
71
96
  private
72
97
 
98
+ def do_remove_observer (observer, channel)
99
+
100
+ observers = @observers[channel]
101
+ observers.delete(observer) if observers
102
+ end
103
+
73
104
  def do_notify (target_channel, channel, *args)
74
- if @observers[target_channel]
75
- @observers[target_channel].each do |obs|
76
- obs.call channel, *args
105
+
106
+ if target_channel.is_a?(String)
107
+
108
+ observers = []
109
+
110
+ @observers.each do |c, o|
111
+
112
+ if c.is_a?(String)
113
+ next unless target_channel.match(c)
114
+ elsif c.is_a?(Regexp)
115
+ next unless c.match(target_channel)
116
+ else
117
+ next
118
+ end
119
+
120
+ observers = observers + o
77
121
  end
122
+ else
123
+
124
+ observers = @observers[target_channel]
125
+ end
126
+
127
+ return false unless observers
128
+
129
+ observers.each do |obs|
130
+ obs.call channel, *args
78
131
  end
132
+
133
+ observers.size > 0
134
+ #
135
+ # returns true if at least one observer was called
79
136
  end
80
137
  end
81
138
  end