langrove 0.0.4.5 → 0.0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. data/.rvmrc +29 -38
  2. data/Gemfile +13 -7
  3. data/Gemfile.lock +35 -32
  4. data/Guardfile +11 -0
  5. data/README.md +34 -0
  6. data/Rakefile +8 -6
  7. data/bin/README.md +3 -0
  8. data/bin/langrove +1 -2
  9. data/langrove.gemspec +35 -0
  10. data/lib/langrove/README.md +82 -0
  11. data/lib/langrove/adaptor/README.md +92 -0
  12. data/lib/langrove/adaptor/adaptor_base.rb +123 -0
  13. data/lib/langrove/adaptor/base.rb +12 -2
  14. data/lib/langrove/adaptor/default.rb +8 -0
  15. data/lib/langrove/adaptor/event_machine_adaptor.rb +152 -0
  16. data/lib/langrove/adaptor/query_adaptor.rb +271 -0
  17. data/lib/langrove/behaviour/README.md +170 -0
  18. data/lib/langrove/behaviour/assessable.rb +63 -0
  19. data/lib/langrove/behaviour/base.rb +16 -0
  20. data/lib/langrove/behaviour/behaviour_base.rb +341 -0
  21. data/lib/langrove/behaviour/enqueueable.rb +104 -0
  22. data/lib/langrove/behaviour/notifiable.rb +48 -0
  23. data/lib/langrove/behaviour/persistable.rb +89 -0
  24. data/lib/langrove/behaviour/preloadable.rb +63 -0
  25. data/lib/langrove/daemon/README.md +7 -0
  26. data/lib/langrove/daemon/base.rb +9 -2
  27. data/lib/langrove/daemon/daemon_base.rb +330 -0
  28. data/lib/langrove/daemon/default.rb +3 -0
  29. data/lib/langrove/ext/README.md +48 -0
  30. data/lib/langrove/ext/class_loader.rb +9 -66
  31. data/lib/langrove/ext/config_item.rb +31 -23
  32. data/lib/langrove/ext/config_loader.rb +42 -8
  33. data/lib/langrove/ext/fake_config.rb +121 -0
  34. data/lib/langrove/ext/fake_logger.rb +50 -7
  35. data/lib/langrove/ext/fake_root.rb +38 -0
  36. data/lib/langrove/ext/hash.rb +56 -0
  37. data/lib/langrove/ext/i.rb +43 -0
  38. data/lib/langrove/ext/log_monitor.rb +272 -0
  39. data/lib/langrove/ext/module_loader.rb +52 -0
  40. data/lib/langrove/ext/recursive_string.rb +94 -0
  41. data/lib/langrove/ext/spec_helper.rb +84 -0
  42. data/lib/langrove/ext.rb +8 -2
  43. data/lib/langrove/handler/README.md +161 -0
  44. data/lib/langrove/handler/base.rb +29 -2
  45. data/lib/langrove/handler/default.rb +4 -0
  46. data/lib/langrove/handler/deferred.rb +105 -0
  47. data/lib/langrove/handler/handler_base.rb +242 -0
  48. data/lib/langrove/handler/http_servlet.rb +58 -0
  49. data/lib/langrove/handler/socket.rb +21 -0
  50. data/lib/langrove/handler/socket_base.rb +127 -0
  51. data/lib/langrove/handler/socket_multiplexer.rb +438 -0
  52. data/lib/langrove/handler/web_socket.rb +41 -0
  53. data/lib/langrove/plugin/README.md +76 -0
  54. data/lib/langrove/plugin/assessor.rb +363 -0
  55. data/lib/langrove/plugin/base.rb +18 -0
  56. data/lib/langrove/plugin/buffered_persistor.rb +97 -0
  57. data/lib/langrove/plugin/enqueuer.rb +186 -0
  58. data/lib/langrove/plugin/notifier.rb +144 -0
  59. data/lib/langrove/plugin/persistor.rb +360 -0
  60. data/lib/langrove/plugin/plugin_base.rb +79 -0
  61. data/lib/langrove/plugin/yaml_file.md +5 -0
  62. data/lib/langrove/plugin/yaml_file.rb +261 -0
  63. data/lib/langrove/protocol/README.md +102 -0
  64. data/lib/langrove/protocol/base.rb +10 -2
  65. data/lib/langrove/protocol/default.rb +3 -0
  66. data/lib/langrove/protocol/protocol_base.rb +60 -0
  67. data/lib/langrove/protocol/syslog.rb +34 -27
  68. data/lib/langrove/root/README.md +17 -0
  69. data/lib/langrove/root/base.rb +11 -0
  70. data/lib/langrove/root/config.rb +163 -0
  71. data/lib/langrove/root/root_base.rb +259 -0
  72. data/lib/langrove/server/README.md +7 -0
  73. data/lib/langrove/server/base.rb +9 -0
  74. data/lib/langrove/server/default.rb +3 -0
  75. data/lib/langrove/server/server_base.rb +301 -0
  76. data/lib/langrove/version.rb +3 -1
  77. data/lib/langrove.rb +44 -1
  78. data/spec/langrove/adaptor/adaptor_base_spec.rb +33 -0
  79. data/spec/langrove/adaptor/event_machine_adaptor_spec.rb +62 -0
  80. data/spec/langrove/adaptor/query_adaptor_spec.rb +94 -0
  81. data/spec/langrove/behaviour/assessable_spec.rb +42 -0
  82. data/spec/langrove/behaviour/behaviour_base_spec.rb +396 -0
  83. data/spec/langrove/behaviour/enqueueable_spec.rb +19 -0
  84. data/spec/langrove/behaviour/notifiable_spec.rb +6 -0
  85. data/spec/langrove/behaviour/persistable_spec.rb +19 -0
  86. data/spec/langrove/behaviour/preloadable_spec.rb +19 -0
  87. data/spec/langrove/daemon/base_spec.rb +6 -0
  88. data/spec/langrove/daemon/daemon_base_spec.rb +253 -0
  89. data/spec/langrove/ext/class_loader_spec.rb +9 -12
  90. data/spec/langrove/ext/fake_config_spec.rb +50 -0
  91. data/spec/langrove/ext/fake_logger_spec.rb +12 -0
  92. data/spec/langrove/ext/fake_root_spec.rb +19 -0
  93. data/spec/langrove/ext/hash_spec.rb +54 -0
  94. data/spec/langrove/ext/i_spec.rb +11 -0
  95. data/spec/langrove/ext/log_monitor_spec.rb +254 -0
  96. data/spec/langrove/ext/module_loader_spec.rb +70 -0
  97. data/spec/langrove/ext/recursive_string_spec.rb +132 -0
  98. data/{functional/config/environments/development.rb → spec/langrove/ext/spec_helper_spec.rb} +0 -0
  99. data/spec/langrove/handler/deferred_spec.rb +9 -0
  100. data/spec/langrove/handler/handler_base_spec.rb +134 -0
  101. data/spec/langrove/handler/socket_base_spec.rb +76 -0
  102. data/spec/langrove/handler/socket_multiplexer_spec.rb +480 -0
  103. data/spec/langrove/handler/socket_spec.rb +6 -0
  104. data/spec/langrove/handler/web_socket_spec.rb +19 -0
  105. data/spec/langrove/plugin/assessor_spec.rb +278 -0
  106. data/spec/langrove/plugin/buffered_persistor_spec.rb +94 -0
  107. data/spec/langrove/plugin/enqueuer_spec.rb +136 -0
  108. data/spec/langrove/plugin/notifier_spec.rb +107 -0
  109. data/spec/langrove/plugin/persistor_spec.rb +300 -0
  110. data/spec/langrove/plugin/plugin_base_spec.rb +86 -0
  111. data/spec/langrove/plugin/yaml_file_spec.rb +348 -0
  112. data/spec/langrove/protocol/protocol_base_spec.rb +19 -0
  113. data/spec/langrove/protocol/syslog_spec.rb +5 -2
  114. data/spec/langrove/root/config_spec.rb +103 -0
  115. data/spec/langrove/root/root_base_spec.rb +93 -0
  116. data/spec/langrove/server/server_base_spec.rb +414 -0
  117. data/spec/spec_helper.rb +38 -0
  118. metadata +157 -92
  119. data/.watchr +0 -27
  120. data/functional/config/boot.rb +0 -64
  121. data/functional/config/daemons.yml +0 -13
  122. data/functional/config/environment.rb +0 -28
  123. data/functional/config/environments/production.rb +0 -0
  124. data/functional/config/environments/test.rb +0 -0
  125. data/functional/lib/client/socket_to_file.rb +0 -47
  126. data/functional/lib/daemon/datagram.rb +0 -21
  127. data/functional/lib/protocol/socket_to_file.rb +0 -55
  128. data/functional/libexec/daemon.rb +0 -68
  129. data/functional/tmp/README +0 -1
  130. data/lib/langrove/_base.rb +0 -28
  131. data/lib/langrove/adaptor_base.rb +0 -116
  132. data/lib/langrove/client/base.rb +0 -2
  133. data/lib/langrove/client/datagram.rb +0 -25
  134. data/lib/langrove/client_base.rb +0 -92
  135. data/lib/langrove/daemon_base.rb +0 -281
  136. data/lib/langrove/ext/find.rb +0 -90
  137. data/lib/langrove/ext/persistable.rb +0 -103
  138. data/lib/langrove/handler_base.rb +0 -148
  139. data/lib/langrove/job/base.rb +0 -1
  140. data/lib/langrove/job_base.rb +0 -24
  141. data/lib/langrove/protocol_base.rb +0 -32
  142. data/spec/functional/daemon/datagram_spec.rb +0 -121
  143. data/spec/langrove/adaptor_base_spec.rb +0 -63
  144. data/spec/langrove/client/datagram_spec.rb +0 -1
  145. data/spec/langrove/client_base_spec.rb +0 -5
  146. data/spec/langrove/daemon_base_spec.rb +0 -154
  147. data/spec/langrove/ext/find_spec.rb +0 -53
  148. data/spec/langrove/ext/persistable_spec.rb +0 -117
  149. data/spec/langrove/handler_base_spec.rb +0 -103
  150. data/spec/langrove/job_base_spec.rb +0 -28
  151. data/spec/langrove/protocol_base_spec.rb +0 -6
  152. data/spec/todo_spec.rb +0 -12
  153. data/tmp/README +0 -2
@@ -0,0 +1,363 @@
1
+ ASSESSOR_VERSION = 0
2
+
3
+ module LanGrove
4
+
5
+ module Plugin
6
+
7
+ #
8
+ # This need a better home.
9
+ #
10
+ class Handler
11
+
12
+ attr_accessor :capsule
13
+ attr_accessor :key
14
+ attr_accessor :type
15
+
16
+ def initialize( key, capsule = {} )
17
+ @type = :handler
18
+ @key = key
19
+ @capsule = capsule
20
+ end
21
+
22
+ end
23
+
24
+ class Assessor < Base
25
+
26
+ def self.type
27
+
28
+ :assessor
29
+
30
+ end
31
+
32
+
33
+ #
34
+ # Assessor has an internal Persistor used to store|fetch
35
+ # the previous 'capsule' contents.
36
+ #
37
+ attr_reader :persistor
38
+
39
+
40
+ #
41
+ # assess_present tests for presense of a key(s)
42
+ # between two hashes.
43
+ #
44
+ # - If on the first(old) but not the second(new)
45
+ #
46
+ # an :off notification is generated
47
+ #
48
+ # - If on both,
49
+ #
50
+ # a :repeat: notification is generated
51
+ #
52
+ # - If not on the first(old) but is on the second
53
+ #
54
+ # an :on notification is generated
55
+ #
56
+ def assess_present( old_val, new_val, key, &block )
57
+
58
+ return if @reported.has_key?( key )
59
+
60
+ delta = nil
61
+
62
+ begin
63
+
64
+ delta = new_val - old_val
65
+
66
+ rescue; end
67
+
68
+ if old_val.nil?
69
+
70
+ yield key, :on, new_val, delta unless new_val.nil?
71
+
72
+ else
73
+
74
+ yield key, :repeat, new_val, delta unless new_val.nil?
75
+ yield key, :off, new_val, delta if new_val.nil?
76
+
77
+ end
78
+
79
+ @reported[key] = 1
80
+
81
+ end
82
+
83
+
84
+
85
+ def assess( handler )
86
+
87
+ #
88
+ # The passed in handler will have the key attribute set.
89
+ #
90
+ # Use the id from that key with the local persistors
91
+ # configured table to collect the 'previous' contents
92
+ # of the handlers capsule (as was passed through this
93
+ # collator last time the capsule changed).
94
+ #
95
+ #
96
+ begin
97
+
98
+ @logger.error(
99
+
100
+ "ERROR: Assessor encountered undefined #{handler.class}.key"
101
+
102
+ )
103
+
104
+ return
105
+
106
+ end if handler.key.nil?
107
+
108
+ key = handler.key
109
+ key['table'] = @persistor.instance_variable_get(:@table)
110
+
111
+ previous = Handler.new( key )
112
+
113
+ #
114
+ # Fetch previous 'capsule'
115
+ #
116
+
117
+ unless persistor.fetch( previous )
118
+
119
+ @logger.info "Persistor did/could not fetch previous, make this fail the job..."
120
+
121
+ return
122
+
123
+ end
124
+
125
+ each_change( previous.capsule, handler.capsule ) do |key, state, value, delta|
126
+
127
+ #
128
+ # Assemble the notification
129
+ #
130
+ notifiation = {
131
+
132
+ :source => handler.unique,
133
+ :system => @root.config.system,
134
+ :application => @root.config.application,
135
+ :key => key,
136
+ :state => state,
137
+ :value => value,
138
+ :delta => delta,
139
+
140
+ }
141
+
142
+ notifiation[:ref] = @refference unless @refference.nil?
143
+
144
+ #
145
+ # Pass to the Handler for possible
146
+ # filtration.
147
+ #
148
+ handler.event_filter( :notification, notifiation ) do |notify|
149
+
150
+ I.show notify
151
+
152
+ #
153
+ # Filtered.
154
+ #
155
+ # Pass to trigger.
156
+ #
157
+ # Note: It is passed in the capsule of a
158
+ # mini Handler, to stick to pattern.
159
+ #
160
+ @root.trigger(
161
+
162
+ Handler.new( nil, notifiation ), :handler, :notify
163
+
164
+ )
165
+
166
+ end
167
+
168
+ end
169
+
170
+ #
171
+ # Save the current to previous
172
+ #
173
+ previous.capsule = handler.capsule
174
+ persistor.store( previous )
175
+
176
+ end
177
+
178
+
179
+ def initialize( root, config, name = nil )
180
+
181
+ super( root, config, name )
182
+
183
+ @refference = @config[:ref]
184
+
185
+ validate_config
186
+
187
+ @provides = {
188
+
189
+ :assessor => {
190
+
191
+ :version => ASSESSOR_VERSION
192
+
193
+ }
194
+
195
+ }
196
+
197
+ end
198
+
199
+ def assess_handler( handler )
200
+
201
+ #
202
+ # Option to trigger :handler_assess:
203
+ #
204
+
205
+ assess( handler )
206
+
207
+ #
208
+ # Option to trigger :handler_after_assess:
209
+ #
210
+
211
+ end
212
+
213
+
214
+ def validate_config
215
+
216
+ config_exception(
217
+
218
+ "#{self.class} requires a nested Persistor :plugin:"
219
+
220
+ ) if (
221
+ @config[:plugin].nil? or
222
+ @persistor = @root.config.get_plugin( @config[:plugin] ) and
223
+ @persistor.nil?
224
+
225
+ )
226
+
227
+ config_exception(
228
+
229
+ "#{self.class} requires :assess: subconfig"
230
+
231
+ ) unless (
232
+
233
+ @config.has_key?( :assess ) and
234
+ @assess = @config[:assess]
235
+
236
+ )
237
+
238
+ @assess ||= {}
239
+
240
+ config_exception(
241
+
242
+ "#{self.class} requires :assess: to contain a subconfig of dataitems to collate"
243
+
244
+ ) unless (
245
+
246
+ @assess.is_a?( Hash )
247
+
248
+ )
249
+
250
+ end
251
+
252
+ def each_change( old_hash, new_hash, &block )
253
+
254
+ @reported = {}
255
+
256
+ @assess.each do |key_match, assess_type|
257
+
258
+ #
259
+ # Search both hashes in tandem and yield the
260
+ # values found at the match key,
261
+ #
262
+ # If the value at the matching key is a new
263
+ # hash, yield all subkeys from each in
264
+ # tandem
265
+ #
266
+ tandem_recurse( old_hash, new_hash, key_match ) do |o, n, key|
267
+
268
+ self.send(
269
+
270
+ "assess_#{assess_type}".to_sym,
271
+ o, n, key, &block
272
+
273
+ )
274
+
275
+ end
276
+
277
+ end
278
+
279
+ end
280
+
281
+ def tandem_recurse( oldh, newh, match, &block )
282
+
283
+ if ( oldh.is_a?( Hash ) and oldh.has_key?( match ) ) or
284
+ ( newh.is_a?( Hash ) and newh.has_key?( match ) )
285
+
286
+ o = oldh[match] unless oldh.nil?
287
+ n = newh[match] unless newh.nil?
288
+
289
+ unless o.is_a?( Hash ) or n.is_a?( Hash )
290
+
291
+ yield o, n, match if block
292
+
293
+ return
294
+
295
+ end
296
+
297
+ if n.is_a?( Hash )
298
+
299
+ n.each do |key, value|
300
+
301
+ oo = o[key] unless o.nil?
302
+
303
+ yield oo, value, key if block
304
+
305
+ end
306
+
307
+ end
308
+
309
+ if o.is_a?( Hash )
310
+
311
+ o.each do |key, value|
312
+
313
+ nn = n[key] unless n.nil?
314
+
315
+ yield value, nn, key if block
316
+
317
+ end
318
+
319
+ end
320
+
321
+ end
322
+
323
+ unless newh.nil? or newh.size == 0
324
+
325
+ newh.each do |key, value|
326
+
327
+ if value.is_a?( Hash )
328
+
329
+ o = nil
330
+ o ||= oldh[key]
331
+
332
+ tandem_recurse( o, value, match, &block )
333
+
334
+ end
335
+
336
+ end
337
+
338
+ end
339
+
340
+ unless oldh.nil? or oldh.size == 0
341
+
342
+ oldh.each do |key, value|
343
+
344
+ if value.is_a?( Hash )
345
+
346
+ n = nil
347
+ n ||= newh[key]
348
+
349
+ tandem_recurse( value, n, match, &block )
350
+
351
+ end
352
+
353
+ end
354
+
355
+ end
356
+
357
+ end
358
+
359
+ end
360
+
361
+ end
362
+
363
+ end
@@ -0,0 +1,18 @@
1
+ module LanGrove
2
+
3
+ module Plugin
4
+
5
+ end
6
+
7
+ end
8
+
9
+ require 'langrove/plugin/plugin_base'
10
+
11
+ require 'langrove/plugin/persistor'
12
+ require 'langrove/plugin/buffered_persistor'
13
+ require 'langrove/plugin/yaml_file'
14
+
15
+ require 'langrove/plugin/enqueuer'
16
+ require 'langrove/plugin/assessor'
17
+ require 'langrove/plugin/notifier'
18
+ #require 'langrove/plugin/terminator'
@@ -0,0 +1,97 @@
1
+ module LanGrove
2
+
3
+ module Plugin
4
+
5
+ class BufferedPersistor < Persistor
6
+
7
+ def store_all
8
+
9
+ #
10
+ # OVERRIDE
11
+ #
12
+ # To store all capsules accumulated in
13
+ # @capsules
14
+ #
15
+
16
+ @capsules.is_a? Hash
17
+
18
+ end
19
+
20
+ def validate_config
21
+
22
+ unless defined?( EM ) and EM.reactor_running?
23
+
24
+ raise LanGrove::PluginException.new(
25
+
26
+ "#{self.class} only runs inside EventMachine enabled daemons"
27
+
28
+ )
29
+
30
+ end
31
+
32
+ super
33
+
34
+ @capsules = {}
35
+ @stored = {}
36
+
37
+ @interval = @config[:interval]
38
+
39
+ if @interval.nil?
40
+
41
+ #
42
+ # default to call store every 10 minutes
43
+ #
44
+
45
+ @logger.info "#{self.class} defaulting :interval: to 10 minutes"
46
+
47
+ @interfal = 600
48
+
49
+ end
50
+
51
+ EM.add_periodic_timer( @interval ) do
52
+
53
+ if @running
54
+
55
+ @logger.warn "#{self.class} already running store_all"
56
+
57
+ break
58
+
59
+ end
60
+
61
+ @running = true
62
+
63
+ store_all
64
+
65
+ @running = false
66
+
67
+ end
68
+
69
+ end
70
+
71
+ def store( handler )
72
+
73
+ gen_key( handler ) if handler.key.nil?
74
+
75
+ @key_column = handler.key['key'].first[0]
76
+
77
+ key = handler.key['key'].first[1]
78
+
79
+ @stored[key] = false
80
+
81
+ @capsules[key] = YAML.load(
82
+
83
+ #
84
+ # LAZY... deep copy through YAML serialize
85
+ #
86
+
87
+ YAML.dump( handler.capsule )
88
+
89
+ )
90
+
91
+ end
92
+
93
+ end
94
+
95
+ end
96
+
97
+ end
@@ -0,0 +1,186 @@
1
+ ENQUEUER_VERSION = 0
2
+
3
+ module LanGrove
4
+
5
+ module Plugin
6
+
7
+ class Enqueuer < Base
8
+
9
+ def self.type
10
+
11
+ :enqueuer
12
+
13
+ end
14
+
15
+ def initialize( root, config, name = nil )
16
+
17
+ super( root, config, name )
18
+
19
+ validate_config
20
+
21
+ @provides = {
22
+
23
+ :enqueuer => {
24
+
25
+ :version => ENQUEUER_VERSION
26
+
27
+ }
28
+
29
+ }
30
+
31
+ end
32
+
33
+ def enqueue_key( handler )
34
+
35
+ #
36
+ # Enqueue a job into a work queue
37
+ # Insert the capsule.key as payload
38
+ #
39
+
40
+ header = queue_header( :get_capsule, handler )
41
+ data = handler.key
42
+
43
+ # enqueue( header, data )
44
+
45
+ raise LanGrove::PluginException.new(
46
+
47
+ "#{self.class}.enqueue_key() not implemented."
48
+
49
+ )
50
+
51
+ end
52
+
53
+ def enqueue_capsule( handler )
54
+
55
+ #
56
+ # Enqueue a job into a work queue
57
+ # Insert the capsule.capsule as payload
58
+ #
59
+
60
+ header = queue_header( :load_capsule, handler )
61
+ data = handler.capsule
62
+
63
+ # enqueue( header, data )
64
+
65
+ raise LanGrove::PluginException.new(
66
+
67
+ "#{self.class}.enqueue_casule() not implemented."
68
+
69
+ )
70
+
71
+ end
72
+
73
+ def enqueue_key_handler( handler )
74
+
75
+ @root.trigger( handler, :handler, :enqueue )
76
+
77
+ enqueue_key( handler )
78
+
79
+ @root.trigger( handler, :handler, :after_enqueue )
80
+
81
+ end
82
+
83
+ def enqueue_capsule_handler( handler )
84
+
85
+ @root.trigger( handler, :handler, :enqueue )
86
+
87
+ enqueue_capsule( handler )
88
+
89
+ @root.trigger( handler, :handler, :after_enqueue )
90
+
91
+ end
92
+
93
+ def queue_header( action, handler, routing_flags = 'none' )
94
+
95
+ #
96
+ # Jobs inserted into a work queue should contain
97
+ # as first paremeter the following header:
98
+ #
99
+ #
100
+
101
+ context = "#{@root.config.system}:#{@root.config.application}:#{routing_flags}"
102
+
103
+ return {
104
+
105
+ 'context' => context,
106
+
107
+ #
108
+ # Required - A timestamp,
109
+ #
110
+ # - Allows for monitoring of queue lag.
111
+ #
112
+ # - Allows for a future QueueMarshal which
113
+ # can redirect by age into a :do_immediately
114
+ # and a :do_later_because_old_data_isnot_urgent
115
+ #
116
+ #
117
+ 'created_at' => Time.now,
118
+
119
+ #
120
+ # Optional - A dequeue action,
121
+ #
122
+ # The worker dequeueing the Job will make a call
123
+ # to whatever function is specified ahead of
124
+ # yielding the Job to be processed
125
+ #
126
+ #
127
+ 'action' => action,
128
+
129
+ #
130
+ # Optional - A sequence number,
131
+ #
132
+ # - Allows for the ability to 'expire' jobs.
133
+ #
134
+ # eg. A sequence on the persisted capsule differing
135
+ # from the sequence in the key on the associated
136
+ # Job as queued would mean a subsequent update to
137
+ # the persisted capsule has ocurred,
138
+ #
139
+ # And an additional Job has been queued to process
140
+ # it, so the first job can therefore be skipped in
141
+ # the cases where:
142
+ #
143
+ # A. Only the most recent state is relevant
144
+ # for processing.
145
+ #
146
+ # B. The capsule is persisted from a single
147
+ # source, all other processes access it
148
+ # from a read only capacity.
149
+ #
150
+ # Z. The Job is quick, or sufficiently not slow,
151
+ # or being queued by something possibly faster,
152
+ # but also queueing jobs against enough separate
153
+ # persistables in a manner that will ensure that
154
+ # the possibility of the queue worker never ever
155
+ # catching up to a 'latest' capsule, and therefore
156
+ # permanently collecting and skipping jobs, is
157
+ # sufficiently unlikely.
158
+ #
159
+ #
160
+ 'sequence' => handler.capsule['persisted_seq']
161
+
162
+ }
163
+
164
+ end
165
+
166
+ def validate_config
167
+
168
+ #
169
+ # Deferrer requires :worker specified
170
+ # as the WorkerClass that will consume
171
+ # jobs from the queue
172
+ #
173
+
174
+ config_exception(
175
+
176
+ "#{self.class} requires :job:"
177
+
178
+ ) unless @job = @config[ :job ]
179
+
180
+ end
181
+
182
+ end
183
+
184
+ end
185
+
186
+ end