wires 0.2.9 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2db21e3f9e121e59a5bb749f91bfc99671408c69
4
- data.tar.gz: e05678e737f152a47a9ccd3e7b14214d2ac61f4b
3
+ metadata.gz: fe770b52bcfa8f3d4ebd9cdbc9474495cf518d40
4
+ data.tar.gz: 504f5acec60a51e872a21e01730f0e624e6ce0af
5
5
  SHA512:
6
- metadata.gz: fb026f33a976e5c66d0da73e28bf5ac47deae08b8c1589df176bf70c471c4ea63b8d281777a4416b883258a91e820aeda776db7df0b167441b09b1a5f180c3cf
7
- data.tar.gz: 03fbb2d4b977391eecfc75d4f3dfb259dd57b9345bd6c96e050020af2917dac2ad6ced83c89b6ddbb4b12b06b4e720ad611a9e61865c5f00d3b581e975169ce5
6
+ metadata.gz: 1e2e093f083689a43817e88ca3eec0dd013d513eb072c2f95b4fa98131c23748e61f19830dbe949d8560e91c706a069859f5813d256ed793295bba039bfbb96f
7
+ data.tar.gz: 2bfa6a3d6fe622e208ea61b41ae7dc40ca6ed3bb20dba0c07a4eab0e916301f1a4a13e760eb89857079f57e524c3794d25f5ea07196d047df053522152542f28
@@ -8,4 +8,6 @@ require 'wires/expect_type'
8
8
  require 'wires/event'
9
9
  require 'wires/hub'
10
10
  require 'wires/channel'
11
- require 'wires/time'
11
+ require 'wires/time'
12
+
13
+ include Wires::Convenience # require 'wires/clean' to uninclude Convenience
@@ -1,24 +1,30 @@
1
1
 
2
- def on(events, channels='*', &codeblock)
3
- channels = [channels] unless channels.is_a? Array
4
- for channel in channels
5
- Wires::Channel.new(channel).register(events, codeblock)
2
+ module Wires
3
+ module Convenience
4
+
5
+ def on(events, channels='*', &codeblock)
6
+ channels = [channels] unless channels.is_a? Array
7
+ for channel in channels
8
+ Wires::Channel.new(channel).register(events, codeblock)
9
+ end
10
+ nil end
11
+
12
+ def fire(event, channel='*')
13
+ Wires::Channel.new(channel).fire(event, blocking:false)
14
+ nil end
15
+
16
+ def fire_and_wait(event, channel='*')
17
+ Wires::Channel.new(channel).fire(event, blocking:true)
18
+ nil end
19
+
20
+ def Channel(*args) Wires::Channel.new(*args) end
21
+
6
22
  end
7
- nil end
8
-
9
-
10
- def fire(event, channel='*')
11
- Wires::Channel.new(channel).fire(event, blocking:false)
12
- nil end
23
+ end
13
24
 
14
- def fire_and_wait(event, channel='*')
15
- Wires::Channel.new(channel).fire(event, blocking:true)
16
- nil end
17
-
18
-
19
- def Channel(*args) Wires::Channel.new(*args) end
20
25
 
21
26
  module Wires
27
+
22
28
  class Channel
23
29
 
24
30
  attr_reader :name
@@ -29,7 +35,6 @@ module Wires
29
35
  @target_list = Set.new
30
36
  nil end
31
37
 
32
-
33
38
  # Redefine this class method to use an alternate Hub
34
39
  def self.hub; Hub; end
35
40
  # Don't redefine this instance method!
@@ -74,6 +79,7 @@ module Wires
74
79
 
75
80
  # Fire an event on this channel
76
81
  def fire(event, blocking:false)
82
+ backtrace = caller
77
83
 
78
84
  # Create an instance object from one of several acceptable input forms
79
85
  event = Event.new_from event
@@ -82,7 +88,7 @@ module Wires
82
88
  for chan in relevant_channels()
83
89
  for target in chan.target_list
84
90
  for string in target[0] & event.class.codestrings
85
- self.class.hub.spawn(event, string, *target[1], blocking)
91
+ self.class.hub.spawn(event, string, *target[1], blocking, backtrace)
86
92
  end end end
87
93
 
88
94
  nil end
@@ -108,5 +114,7 @@ module Wires
108
114
  end
109
115
  return relevant.uniq
110
116
  end
117
+
111
118
  end
119
+
112
120
  end
@@ -0,0 +1,9 @@
1
+ require 'wires'
2
+
3
+ class << self
4
+ target_owner = Wires::Convenience
5
+ target_owner.instance_methods(false)
6
+ .select { |sym| respond_to?(sym) }
7
+ .select { |sym| method(sym).owner==target_owner }
8
+ .each { |sym| undef_method sym }
9
+ end
@@ -97,6 +97,7 @@ module Wires
97
97
  obj = super
98
98
 
99
99
  kwargs = args[-1].is_a?(Hash) ? args.pop : Hash.new
100
+ kwargs[:kwargs] = kwargs.clone.freeze
100
101
  kwargs[:args] = args
101
102
  kwargs[:codeblock] = block if block
102
103
  for key in kwargs.keys
@@ -1,5 +1,4 @@
1
1
 
2
- #TODO: Allow custom grain times
3
2
  module Wires
4
3
  # An Event Hub. Event/proc associations come in, and the procs
5
4
  # get called in new threads in the order received
@@ -33,12 +32,8 @@ module Wires
33
32
 
34
33
  @please_finish_all = false
35
34
 
36
- @on_neglect = Proc.new do |args|
37
- $stderr.puts "#{self} neglected to spawn task: #{args.inspect}"
38
- end
39
- @on_neglect_done = Proc.new do |args|
40
- $stderr.puts "#{self} finally spawned neglected task: #{args.inspect}"
41
- end
35
+ reset_neglect_procs
36
+ reset_handler_exception_proc
42
37
 
43
38
  at_exit { (sleep 0.05 until dead?) unless $! }
44
39
 
@@ -101,22 +96,45 @@ module Wires
101
96
 
102
97
  def on_neglect(&block)
103
98
  @on_neglect=block
104
- end
99
+ nil end
105
100
  def on_neglect_done(&block)
106
101
  @on_neglect_done=block
102
+ nil end
103
+ def on_handler_exception(&block)
104
+ @on_handler_exception=block
105
+ end
106
+
107
+ def reset_neglect_procs
108
+ @on_neglect = Proc.new do |args|
109
+ $stderr.puts "#{self} neglected to spawn task: #{args.inspect}"
110
+ end
111
+ @on_neglect_done = Proc.new do |args|
112
+ $stderr.puts "#{self} finally spawned neglected task: #{args.inspect}"
113
+ end
114
+ nil end
115
+
116
+ def reset_handler_exception_proc
117
+ @on_handler_exception = Proc.new { raise }
107
118
  end
108
119
 
109
120
  # Spawn a task
110
- def spawn(*args) # :args: event, ch_string, proc, blocking
121
+ def spawn(*args) # :args: event, ch_string, proc, blocking, fire_bt
122
+
111
123
  @spawning_count_lock.synchronize { @spawning_count += 1 }
112
124
 
113
125
  return neglect(*args) if dead?
114
126
 
115
- event, ch_string, proc, blocking = *args
127
+ event, ch_string, proc, blocking, fire_bt = *args
128
+ *exc_args = event, ch_string, fire_bt
116
129
 
117
130
  # If blocking, run the proc in this thread
118
131
  if blocking
119
- proc.call(event, ch_string)
132
+ begin
133
+ proc.call(event, ch_string)
134
+ rescue Exception => exc
135
+ unhandled_exception(exc, *exc_args)
136
+ end
137
+
120
138
  return :done
121
139
  end
122
140
 
@@ -133,10 +151,17 @@ module Wires
133
151
  raise ThreadError if (@max_child_threads) and \
134
152
  (@max_child_threads <= @child_threads.size)
135
153
  # Start the new child thread; follow with chain of neglected tasks
136
- new_thread = Thread.new { proc.call(event, ch_string); \
137
- spawn_neglected_task_chain }
154
+ new_thread = Thread.new do
155
+ begin
156
+ proc.call(event, ch_string)
157
+ spawn_neglected_task_chain
158
+ rescue Exception => exc
159
+ unhandled_exception(exc, *exc_args)
160
+ end
161
+ end
162
+
138
163
  # Capture ThreadError from either OS or user-set limitation
139
- rescue ThreadError; return neglect(*args); end
164
+ rescue ThreadError; return neglect(*args) end
140
165
 
141
166
  @child_threads << new_thread
142
167
  return new_thread
@@ -171,11 +196,21 @@ module Wires
171
196
  nil end
172
197
 
173
198
  private
199
+
200
+ # Send relevant data to a custom exception handler
201
+ def unhandled_exception(exception, event, ch_string, fire_bt)
202
+
203
+ class << exception; attr_reader :fire_backtrace; end
204
+ exception.instance_variable_set(:@fire_backtrace, fire_bt.dup)
205
+
206
+ @on_handler_exception.call(exception, event, ch_string)
207
+
208
+ end
174
209
 
175
210
  # Temporarily neglect a task until resources are available to run it
176
211
  def neglect(*args)
177
212
  @neglected_lock.synchronize do
178
- @on_neglect.call(args)
213
+ @on_neglect.call(*args)
179
214
  @neglected << args
180
215
  end
181
216
  false end
@@ -187,7 +222,7 @@ module Wires
187
222
  ((@neglected.shift)[0...-1]<<true) # Call with blocking
188
223
  end
189
224
  spawn(*args)
190
- @on_neglect_done.call(args)
225
+ @on_neglect_done.call(*args)
191
226
  spawn_neglected_task_chain
192
227
  nil end
193
228
 
@@ -200,7 +235,7 @@ module Wires
200
235
  end
201
236
  break if cease
202
237
  spawn(*args)
203
- @on_neglect_done.call(args)
238
+ @on_neglect_done.call(*args)
204
239
  end
205
240
  nil end
206
241
 
@@ -1,5 +1,4 @@
1
1
 
2
-
3
2
  module Wires
4
3
 
5
4
  class TimeSchedulerAnonEvent < Event; end
@@ -240,9 +239,15 @@ class ActiveSupport::Duration
240
239
 
241
240
  end
242
241
 
243
- def fire_every(interval, event, channel='*', **kwargs)
244
- Wires::TimeScheduler << \
245
- Wires::TimeSchedulerItem.new(self, event, channel, **kwargs)
242
+ module Wires
243
+ module Convenience
244
+
245
+ def fire_every(interval, event, channel='*', **kwargs)
246
+ Wires::TimeScheduler << \
247
+ Wires::TimeSchedulerItem.new(self, event, channel, **kwargs)
248
+ end
249
+
250
+ end
246
251
  end
247
252
 
248
253
  # TODO: Repeatable event sugar?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wires
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.9
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe McIlvain
@@ -66,6 +66,34 @@ dependencies:
66
66
  - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: turn
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: starkfish
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
69
97
  description: An asynchronous (threaded) event routing framework in Ruby. Patch your
70
98
  objects together with wires. Inspired by the python 'circuits' framework.
71
99
  email: joe.eli.mac@gmail.com
@@ -77,6 +105,7 @@ files:
77
105
  - lib/wires/time.rb
78
106
  - lib/wires/hub.rb
79
107
  - lib/wires/expect_type.rb
108
+ - lib/wires/clean.rb
80
109
  - lib/wires/channel.rb
81
110
  - lib/wires/event.rb
82
111
  - LICENSE