asynchronic 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/README.md +0 -70
  4. data/Rakefile +7 -0
  5. data/asynchronic.gemspec +5 -1
  6. data/lib/asynchronic/data_store/in_memory.rb +47 -0
  7. data/lib/asynchronic/data_store/key.rb +15 -0
  8. data/lib/asynchronic/data_store/lookup.rb +27 -0
  9. data/lib/asynchronic/data_store/redis.rb +52 -0
  10. data/lib/asynchronic/environment.rb +57 -0
  11. data/lib/asynchronic/error.rb +13 -0
  12. data/lib/asynchronic/hash.rb +31 -0
  13. data/lib/asynchronic/job.rb +46 -0
  14. data/lib/asynchronic/process.rb +117 -48
  15. data/lib/asynchronic/queue_engine/in_memory.rb +72 -0
  16. data/lib/asynchronic/queue_engine/ost.rb +73 -0
  17. data/lib/asynchronic/runtime.rb +40 -0
  18. data/lib/asynchronic/version.rb +1 -1
  19. data/lib/asynchronic/worker.rb +27 -18
  20. data/lib/asynchronic.rb +17 -32
  21. data/spec/coverage_helper.rb +0 -6
  22. data/spec/data_store/data_store_examples.rb +62 -0
  23. data/spec/data_store/in_memory_spec.rb +10 -0
  24. data/spec/data_store/key_spec.rb +36 -0
  25. data/spec/data_store/lookup_spec.rb +92 -0
  26. data/spec/data_store/redis_spec.rb +14 -0
  27. data/spec/expectations.rb +89 -0
  28. data/spec/facade_spec.rb +61 -0
  29. data/spec/jobs.rb +123 -33
  30. data/spec/minitest_helper.rb +12 -14
  31. data/spec/process/life_cycle_examples.rb +329 -0
  32. data/spec/process/life_cycle_in_memory_spec.rb +11 -0
  33. data/spec/process/life_cycle_redis_spec.rb +15 -0
  34. data/spec/queue_engine/in_memory_spec.rb +11 -0
  35. data/spec/queue_engine/ost_spec.rb +15 -0
  36. data/spec/queue_engine/queue_engine_examples.rb +47 -0
  37. data/spec/worker/in_memory_spec.rb +11 -0
  38. data/spec/worker/redis_spec.rb +16 -0
  39. data/spec/worker/worker_examples.rb +49 -0
  40. metadata +111 -18
  41. data/lib/asynchronic/persistent.rb +0 -61
  42. data/lib/asynchronic/pipeline.rb +0 -23
  43. data/spec/integration_spec.rb +0 -122
  44. data/spec/persistent_spec.rb +0 -88
@@ -0,0 +1,49 @@
1
+ module WorkerExamples
2
+
3
+ let(:env) { Asynchronic::Environment.new queue_engine, data_store }
4
+ let(:queue_name) { :test_worker }
5
+ let(:queue) { env.queue queue_name }
6
+
7
+ def enqueue_processes
8
+ processes = 5.times.map do
9
+ env.build_process(WorkerJob, queue: :test_worker).tap(&:enqueue)
10
+ end
11
+
12
+ queue.must_enqueued processes
13
+ processes.each { |p| p.must_be :queued? }
14
+
15
+ processes
16
+ end
17
+
18
+ it 'Instance usage' do
19
+ worker = Asynchronic::Worker.new :test_worker, env
20
+
21
+ processes = enqueue_processes
22
+
23
+ Thread.new do
24
+ loop { break if queue.empty? }
25
+ worker.stop
26
+ end
27
+
28
+ worker.start
29
+
30
+ processes.each { |p| p.must_be :completed? }
31
+ end
32
+
33
+ it 'Class usage' do
34
+ Asynchronic.configure do |config|
35
+ config.queue_engine = queue_engine
36
+ config.data_store = data_store
37
+ end
38
+
39
+ processes = enqueue_processes
40
+
41
+ Asynchronic::Worker.start :test_worker do |worker|
42
+ loop { break if worker.queue.empty? }
43
+ worker.stop
44
+ end
45
+
46
+ processes.each { |p| p.must_be :completed? }
47
+ end
48
+
49
+ end
metadata CHANGED
@@ -1,99 +1,155 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asynchronic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriel Naiman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-29 00:00:00.000000000 Z
11
+ date: 2014-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: ost
14
+ name: redis
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
15
21
  prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ost
16
29
  requirement: !ruby/object:Gem::Requirement
17
30
  requirements:
18
31
  - - "~>"
19
32
  - !ruby/object:Gem::Version
20
33
  version: '0.1'
34
+ type: :runtime
35
+ prerelease: false
21
36
  version_requirements: !ruby/object:Gem::Requirement
22
37
  requirements:
23
38
  - - "~>"
24
39
  - !ruby/object:Gem::Version
25
40
  version: '0.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: class_config
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.0'
26
48
  type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: bundler
29
- prerelease: false
30
57
  requirement: !ruby/object:Gem::Requirement
31
58
  requirements:
32
59
  - - "~>"
33
60
  - !ruby/object:Gem::Version
34
61
  version: '1.3'
62
+ type: :development
63
+ prerelease: false
35
64
  version_requirements: !ruby/object:Gem::Requirement
36
65
  requirements:
37
66
  - - "~>"
38
67
  - !ruby/object:Gem::Version
39
68
  version: '1.3'
40
- type: :development
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rake
43
- prerelease: false
44
71
  requirement: !ruby/object:Gem::Requirement
45
72
  requirements:
46
73
  - - ">="
47
74
  - !ruby/object:Gem::Version
48
75
  version: '0'
76
+ type: :development
77
+ prerelease: false
49
78
  version_requirements: !ruby/object:Gem::Requirement
50
79
  requirements:
51
80
  - - ">="
52
81
  - !ruby/object:Gem::Version
53
82
  version: '0'
54
- type: :development
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: minitest
57
- prerelease: false
58
85
  requirement: !ruby/object:Gem::Requirement
59
86
  requirements:
60
87
  - - "~>"
61
88
  - !ruby/object:Gem::Version
62
89
  version: '4.7'
90
+ type: :development
91
+ prerelease: false
63
92
  version_requirements: !ruby/object:Gem::Requirement
64
93
  requirements:
65
94
  - - "~>"
66
95
  - !ruby/object:Gem::Version
67
96
  version: '4.7'
97
+ - !ruby/object:Gem::Dependency
98
+ name: minitest-great_expectations
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.0'
68
104
  type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.0'
69
111
  - !ruby/object:Gem::Dependency
70
112
  name: turn
71
- prerelease: false
72
113
  requirement: !ruby/object:Gem::Requirement
73
114
  requirements:
74
115
  - - "~>"
75
116
  - !ruby/object:Gem::Version
76
117
  version: '0.9'
118
+ type: :development
119
+ prerelease: false
77
120
  version_requirements: !ruby/object:Gem::Requirement
78
121
  requirements:
79
122
  - - "~>"
80
123
  - !ruby/object:Gem::Version
81
124
  version: '0.9'
82
- type: :development
83
125
  - !ruby/object:Gem::Dependency
84
126
  name: simplecov
85
- prerelease: false
86
127
  requirement: !ruby/object:Gem::Requirement
87
128
  requirements:
88
129
  - - ">="
89
130
  - !ruby/object:Gem::Version
90
131
  version: '0'
132
+ type: :development
133
+ prerelease: false
91
134
  version_requirements: !ruby/object:Gem::Requirement
92
135
  requirements:
93
136
  - - ">="
94
137
  - !ruby/object:Gem::Version
95
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: pry
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
96
146
  type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
97
153
  description: DSL for asynchronic pipeline
98
154
  email:
99
155
  - gabynaiman@gmail.com
@@ -110,16 +166,39 @@ files:
110
166
  - Rakefile
111
167
  - asynchronic.gemspec
112
168
  - lib/asynchronic.rb
113
- - lib/asynchronic/persistent.rb
114
- - lib/asynchronic/pipeline.rb
169
+ - lib/asynchronic/data_store/in_memory.rb
170
+ - lib/asynchronic/data_store/key.rb
171
+ - lib/asynchronic/data_store/lookup.rb
172
+ - lib/asynchronic/data_store/redis.rb
173
+ - lib/asynchronic/environment.rb
174
+ - lib/asynchronic/error.rb
175
+ - lib/asynchronic/hash.rb
176
+ - lib/asynchronic/job.rb
115
177
  - lib/asynchronic/process.rb
178
+ - lib/asynchronic/queue_engine/in_memory.rb
179
+ - lib/asynchronic/queue_engine/ost.rb
180
+ - lib/asynchronic/runtime.rb
116
181
  - lib/asynchronic/version.rb
117
182
  - lib/asynchronic/worker.rb
118
183
  - spec/coverage_helper.rb
119
- - spec/integration_spec.rb
184
+ - spec/data_store/data_store_examples.rb
185
+ - spec/data_store/in_memory_spec.rb
186
+ - spec/data_store/key_spec.rb
187
+ - spec/data_store/lookup_spec.rb
188
+ - spec/data_store/redis_spec.rb
189
+ - spec/expectations.rb
190
+ - spec/facade_spec.rb
120
191
  - spec/jobs.rb
121
192
  - spec/minitest_helper.rb
122
- - spec/persistent_spec.rb
193
+ - spec/process/life_cycle_examples.rb
194
+ - spec/process/life_cycle_in_memory_spec.rb
195
+ - spec/process/life_cycle_redis_spec.rb
196
+ - spec/queue_engine/in_memory_spec.rb
197
+ - spec/queue_engine/ost_spec.rb
198
+ - spec/queue_engine/queue_engine_examples.rb
199
+ - spec/worker/in_memory_spec.rb
200
+ - spec/worker/redis_spec.rb
201
+ - spec/worker/worker_examples.rb
123
202
  homepage: https://github.com/gabynaiman/asynchronic
124
203
  licenses:
125
204
  - MIT
@@ -140,13 +219,27 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
219
  version: '0'
141
220
  requirements: []
142
221
  rubyforge_project:
143
- rubygems_version: 2.1.5
222
+ rubygems_version: 2.2.2
144
223
  signing_key:
145
224
  specification_version: 4
146
225
  summary: DSL for asynchronic pipeline using queues over Redis
147
226
  test_files:
148
227
  - spec/coverage_helper.rb
149
- - spec/integration_spec.rb
228
+ - spec/data_store/data_store_examples.rb
229
+ - spec/data_store/in_memory_spec.rb
230
+ - spec/data_store/key_spec.rb
231
+ - spec/data_store/lookup_spec.rb
232
+ - spec/data_store/redis_spec.rb
233
+ - spec/expectations.rb
234
+ - spec/facade_spec.rb
150
235
  - spec/jobs.rb
151
236
  - spec/minitest_helper.rb
152
- - spec/persistent_spec.rb
237
+ - spec/process/life_cycle_examples.rb
238
+ - spec/process/life_cycle_in_memory_spec.rb
239
+ - spec/process/life_cycle_redis_spec.rb
240
+ - spec/queue_engine/in_memory_spec.rb
241
+ - spec/queue_engine/ost_spec.rb
242
+ - spec/queue_engine/queue_engine_examples.rb
243
+ - spec/worker/in_memory_spec.rb
244
+ - spec/worker/redis_spec.rb
245
+ - spec/worker/worker_examples.rb
@@ -1,61 +0,0 @@
1
- module Asynchronic
2
- module Persistent
3
-
4
- def self.included(base)
5
- base.send :include, InstanceMethods
6
- base.extend ClassMethods
7
- end
8
-
9
- module InstanceMethods
10
-
11
- def id
12
- @id
13
- end
14
-
15
- def save
16
- @id ||= SecureRandom.uuid
17
- nest.set Marshal.dump(self)
18
- end
19
-
20
- def delete
21
- return unless id
22
- nest.del
23
- end
24
-
25
- def archive
26
- return unless id
27
- FileUtils.mkpath(Asynchronic.archiving_path) unless Dir.exists?(Asynchronic.archiving_path)
28
- File.write Asynchronic.archiving_file(id), Base64.encode64(Marshal.dump(self))
29
- delete
30
- end
31
-
32
- def nest
33
- self.class.nest[id]
34
- end
35
-
36
- end
37
-
38
- module ClassMethods
39
-
40
- def create(*args, &block)
41
- new(*args, &block).tap(&:save)
42
- end
43
-
44
- def find(id)
45
- if nest[id].get
46
- Marshal.load nest[id].get
47
- elsif File.exists?(Asynchronic.archiving_file(id))
48
- Marshal.load(Base64.decode64(File.read(Asynchronic.archiving_file(id))))
49
- else
50
- nil
51
- end
52
- end
53
-
54
- def nest
55
- @nest ||= Nest.new self.name, Asynchronic.redis
56
- end
57
-
58
- end
59
-
60
- end
61
- end
@@ -1,23 +0,0 @@
1
- module Asynchronic
2
- module Pipeline
3
-
4
- Step = Struct.new :name, :options, :block
5
-
6
- def queue(name=nil)
7
- name ? @queue = name : @queue
8
- end
9
-
10
- def step(name, options={}, &block)
11
- steps << Step.new(name, options, block)
12
- end
13
-
14
- def steps
15
- @steps ||= []
16
- end
17
-
18
- def run(context={})
19
- Process.enqueue self, context
20
- end
21
-
22
- end
23
- end
@@ -1,122 +0,0 @@
1
- require 'minitest_helper'
2
- require 'jobs'
3
-
4
- describe 'Integration' do
5
-
6
- before do
7
- Registry.clear
8
- end
9
-
10
- def start_and_stop_worker(queue=nil)
11
- worker = Asynchronic::Worker.new queue
12
- Thread.new do
13
- sleep 0.1
14
- while Nest.new('ost')[worker.queue].exists; end
15
- worker.stop
16
- end
17
- worker.start
18
- end
19
-
20
- def exist_queue?(queue)
21
- Nest.new('ost')[queue].exists
22
- end
23
-
24
- it 'Job defaults' do
25
- SingleStepJob.queue.must_be_nil
26
- SingleStepJob.steps.count.must_equal 1
27
- SingleStepJob.steps[0].name.must_equal :step_name
28
- SingleStepJob.steps[0].options.must_equal Hash.new
29
- SingleStepJob.steps[0].block.class.must_equal Proc
30
- SingleStepJob.must_respond_to :run
31
- end
32
-
33
- it 'Process defaults' do
34
- pid = SingleStepJob.run
35
-
36
- pid.wont_be_nil
37
-
38
- process = Asynchronic::Process.find pid
39
-
40
- process.pipeline.must_equal SingleStepJob
41
- process.context.must_equal Hash.new
42
- process.children.count.must_equal 1
43
- process.children[0].status.must_equal :pending
44
- process.children[0].output.must_be_nil
45
- end
46
-
47
- describe 'Execution' do
48
-
49
- it 'One step job' do
50
- SingleStepJob.queue.must_be_nil
51
- refute exist_queue? Asynchronic.default_queue
52
-
53
- pid = SingleStepJob.run
54
-
55
- assert exist_queue? Asynchronic.default_queue
56
- Registry.must_be_empty
57
-
58
- start_and_stop_worker
59
-
60
- process = Asynchronic::Process.find pid
61
- process.children[0].status.must_equal :finalized
62
- process.children[0].output.must_equal :single_step_job
63
-
64
- Registry.to_a.must_equal [:single_step_job]
65
- end
66
-
67
- it 'Two steps with specific queue and context arguments' do
68
- TwoStepsWithSpecificQueueJob.queue.wont_be_nil
69
- refute exist_queue? TwoStepsWithSpecificQueueJob.queue
70
-
71
- pid = TwoStepsWithSpecificQueueJob.run value1: 10
72
-
73
- assert exist_queue? TwoStepsWithSpecificQueueJob.queue
74
- Registry.must_be_empty
75
-
76
- start_and_stop_worker TwoStepsWithSpecificQueueJob.queue
77
-
78
- process = Asynchronic::Process.find pid
79
- process.context.must_equal value1: 10, value2: 5
80
- process.children[0].status.must_equal :finalized
81
- process.children[0].output.must_equal 11
82
- process.children[1].status.must_equal :finalized
83
- process.children[1].output.must_equal 55
84
-
85
- Registry.to_a.must_equal [11, 55]
86
- end
87
-
88
- it 'Steps with different queues (fixed and contextual)' do
89
- MultipleQueuesJob.queue.must_be_nil
90
- refute exist_queue? :queue1
91
- refute exist_queue? :queue2
92
-
93
- pid = MultipleQueuesJob.run dynamic_queue: :queue2
94
-
95
- assert exist_queue? :queue1
96
- refute exist_queue? :queue2
97
- Registry.must_be_empty
98
-
99
- start_and_stop_worker :queue1
100
-
101
- process = Asynchronic::Process.find pid
102
- process.children[0].status.must_equal :finalized
103
- process.children[1].status.must_equal :pending
104
-
105
- refute exist_queue? :queue1
106
- assert exist_queue? :queue2
107
- Registry.to_a.must_equal [:first_queue]
108
-
109
- start_and_stop_worker :queue2
110
-
111
- process = Asynchronic::Process.find pid
112
- process.children[0].status.must_equal :finalized
113
- process.children[1].status.must_equal :finalized
114
-
115
- refute exist_queue? :queue1
116
- refute exist_queue? :queue2
117
- Registry.to_a.must_equal [:first_queue, :second_queue]
118
- end
119
-
120
- end
121
-
122
- end
@@ -1,88 +0,0 @@
1
- require 'minitest_helper'
2
-
3
- describe Asynchronic::Persistent do
4
-
5
- Dummy = Struct.new :string, :hash, :array do
6
- include Asynchronic::Persistent
7
- end
8
-
9
- def dummy_attributes
10
- ['text', {key1: 'value1', key2: 'value2'}, [1,2,3]]
11
- end
12
-
13
- def assert_dummy(obj)
14
- obj.string.must_equal 'text'
15
- obj.hash.must_equal key1: 'value1', key2: 'value2'
16
- obj.array.must_equal [1,2,3]
17
- end
18
-
19
- describe 'Instance methods' do
20
-
21
- let(:dummy) { Dummy.new *dummy_attributes }
22
-
23
- it 'Nest instance identifier' do
24
- dummy.define_singleton_method(:id) { '123456' }
25
- dummy.nest.must_equal 'Dummy:123456'
26
- end
27
-
28
- it 'Save' do
29
- dummy.id.must_equal nil
30
- dummy.save
31
- dummy.id.wont_equal nil
32
-
33
- redis.keys.must_include dummy.nest
34
-
35
- assert_dummy Marshal.load(redis.get(dummy.nest))
36
- end
37
-
38
- it 'Delete' do
39
- dummy.save
40
- redis.keys.must_include dummy.nest
41
-
42
- dummy.delete
43
- redis.keys.wont_include dummy.nest
44
- end
45
-
46
- it 'Archive' do
47
- dummy.save
48
- redis.keys.must_include dummy.nest
49
- refute File.exists?(Asynchronic.archiving_file(dummy.id))
50
-
51
- dummy.archive
52
- redis.keys.wont_include dummy.nest
53
- assert File.exists?(Asynchronic.archiving_file(dummy.id))
54
-
55
- assert_dummy Marshal.load(Base64.decode64(File.read(Asynchronic.archiving_file(dummy.id))))
56
- end
57
-
58
- end
59
-
60
- describe 'Class methods' do
61
-
62
- it 'Nest class identifier' do
63
- Dummy.nest.must_equal 'Dummy'
64
- end
65
-
66
- it 'Create' do
67
- dummy = Dummy.create *dummy_attributes
68
-
69
- redis.keys.must_include dummy.nest
70
- assert_dummy Marshal.load(redis.get(dummy.nest))
71
- end
72
-
73
- it 'Find' do
74
- dummy = Dummy.create *dummy_attributes
75
-
76
- assert_dummy Dummy.find(dummy.id)
77
- end
78
-
79
- it 'Find archived' do
80
- dummy = Dummy.create *dummy_attributes
81
- dummy.archive
82
-
83
- assert_dummy Dummy.find(dummy.id)
84
- end
85
-
86
- end
87
-
88
- end