errands 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a781f76605abb3a1044de0fe07eeb8239e747f17
4
+ data.tar.gz: 24ab0e0c763815f8250ba72ebf8a72c98eee9ec0
5
+ SHA512:
6
+ metadata.gz: 0f2c8a6784b251e01f897004db3249c606ae129e421d7137481789732d9690a5a5384df3f559324ef01f7a2acba78a37b4b191eff432c147a7555adc95993c2b
7
+ data.tar.gz: 8faf6c10f519130311a048d71d0b0c80a30d6e8a69bdca20cb8a4429b7cd13d0d5f265bebd5388622b433801841fbc2f2172873bb9f672cd3aa63217b4d6bbf9
@@ -0,0 +1,179 @@
1
+ module Errands
2
+
3
+ module Runner
4
+
5
+ module ThreadAccessors
6
+
7
+ def thread_accessors(*accessors)
8
+ accessors.each do |a|
9
+ define_method a, -> { our[a] }
10
+ end
11
+ end
12
+
13
+ end
14
+
15
+ class ImplementationError < StandardError; end
16
+
17
+ %w|job process|.each do |m|
18
+ define_method m do |*_|
19
+ raise method(__method__).owner::ImplementationError,
20
+ "#{__method__} has to be implemented in client class"
21
+ end
22
+ end
23
+
24
+ def self.included(klass)
25
+ klass.extend ThreadAccessors
26
+ end
27
+
28
+ attr_accessor :running_mode
29
+
30
+ def run(options = startup)
31
+ start options
32
+ our[:events] = []
33
+
34
+ loop do
35
+ errands *our[:events].shift if our[:events].any?
36
+ end
37
+ end
38
+
39
+ def start(options = startup)
40
+ our.merge! options
41
+ starter
42
+ end
43
+
44
+ def my
45
+ Thread.current[:runner] ||= {}
46
+ end
47
+
48
+ def his(t, k, v = nil)
49
+ t[:runner] ||= {}
50
+ v ? t[:runner][k] = v : t[:runner][k]
51
+ end
52
+
53
+ def our
54
+ Thread.main[:runner] ||= {}
55
+ end
56
+
57
+ def starter
58
+ running do
59
+ loop do
60
+ if secure_check :worker, :alive?
61
+ sleep 1
62
+ else
63
+ secure_check :worker, :join
64
+ worker
65
+ end
66
+ end
67
+
68
+ errands :stop, :starter
69
+ end
70
+ end
71
+
72
+ def worker
73
+ our[:work_done] = false
74
+
75
+ running do
76
+ loop do
77
+ begin
78
+ (our[:work_done] = true) && break if work_done?
79
+ process job
80
+ sleep our[:frequency] if our[:frequency]
81
+ rescue => e
82
+ log_error e
83
+ end
84
+ end
85
+
86
+ our[:work_done] && work_done
87
+ errands :stop, :worker
88
+ end
89
+ end
90
+
91
+ def stop(threads = nil)
92
+ our_selection(threads || our[:threads]) do |n, t|
93
+ if Thread.current == t
94
+ errands :stop, n
95
+ else
96
+ t.exit
97
+ t.join
98
+ wait_for n, :status, false
99
+ end
100
+ end
101
+
102
+ our[:stopped] = !status.values.any? { |t| t.alive? }
103
+ end
104
+
105
+ def status
106
+ our_selection our[:threads]
107
+ end
108
+
109
+ def status
110
+ our_selection our[:threads]
111
+ end
112
+
113
+ def wait_for(key, meth = nil, result = true)
114
+ loop do
115
+ break if meth && our[key].respond_to?(meth) ?
116
+ our[key].send(meth) == result :
117
+ !!our[key] == result
118
+ end
119
+ end
120
+
121
+ def work_done?
122
+ false
123
+ end
124
+
125
+ private
126
+
127
+ def our_selection(selection)
128
+ our.dup.select do |k, v|
129
+ Array(selection).include?(k).tap { |bool|
130
+ yield k, our[k] if bool && block_given?
131
+ }
132
+ end
133
+ end
134
+
135
+ def errands(errand, *_)
136
+ name = thread_name(1).to_s << "_#{errand}"
137
+
138
+ running name.to_sym do
139
+ send errand, *_
140
+ our[:threads].delete my[:name]
141
+ end
142
+ end
143
+
144
+ def running(name = nil, &block)
145
+ if @running_mode
146
+ send @running_mode, &block
147
+ else
148
+ register_thread name || thread_name, Thread.new(&block)
149
+ end
150
+ end
151
+
152
+ def thread_name(caller_depth = 2)
153
+ caller_locations(caller_depth, 1).first.base_label.dup.tap { |n|
154
+ n << "_" << Time.now.to_f.to_s.sub('.', '_') if n.end_with? 's'
155
+ }.to_sym
156
+ end
157
+
158
+ def register_thread(name, thread)
159
+ ((our[:threads] ||= []) << name).uniq!
160
+ his our[name] = thread, :name, name
161
+ end
162
+
163
+ def secure_check(name, meth)
164
+ our[name] && our[name].respond_to?(meth) && our[name].send(meth)
165
+ end
166
+
167
+ def log_error(e)
168
+ puts e.message
169
+ end
170
+
171
+ def startup
172
+ {}
173
+ end
174
+
175
+ def work_done; end
176
+
177
+ end
178
+
179
+ end
@@ -0,0 +1,3 @@
1
+ module Errands
2
+ VERSION = "0.0.1"
3
+ end
data/lib/errands.rb ADDED
@@ -0,0 +1,3 @@
1
+ $: << File.dirname(__FILE__)
2
+
3
+ require 'errands/runner'
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: errands
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - lacravate
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-09-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.10.4
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.10.4
41
+ - !ruby/object:Gem::Dependency
42
+ name: simplecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.15'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.15'
55
+ description: A code frame to have an orderly use of thread and separate runtime and
56
+ actual job of a Ruby class
57
+ email:
58
+ - lacravate@lacravate.fr
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - lib/errands.rb
64
+ - lib/errands/runner.rb
65
+ - lib/errands/version.rb
66
+ homepage: https://github.com/lacravate/errands
67
+ licenses: []
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.4.5
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: Turn a model into a threaded service
89
+ test_files: []