orchestrated 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -1,11 +1,11 @@
1
1
  Orchestrated
2
2
  ============
3
3
 
4
- The [delayed_job](https://github.com/collectiveidea/delayed_job) Ruby Gem provides a job queuing system for Ruby. It implements an elegant API for delaying execution of any object method. Not only is the execution of the method (message delivery) delayed in time, it is potentially shifted in space. By shifting in space, i.e. running in a separate virtual machine, possibly on a separate computer, multiple CPUs can be brought to bear on a computing problem.
4
+ The [delayed_job](https://github.com/collectiveidea/delayed_job) Ruby Gem provides a job queuing system for Ruby. It implements an elegant API for delaying execution of any object method. Not only is the execution of the method (message delivery) delayed in time, it is potentially shifted in space too. By shifting in space, i.e. running in a separate virtual machine, possibly on a separate computer, multiple CPUs can be brought to bear on a computing problem.
5
5
 
6
- By breaking up otherwise serial execution into multiple queued jobs, a program can be made more scalable. Processing of (distributed) queues has a long and successful history in data processing for this reason.
6
+ By breaking up otherwise serial execution into multiple queued jobs, a program can be made more scalable. This sort of distributed queue-processing architecture has a long and successful history in data processing.
7
7
 
8
- Queuing works well for simple tasks. By simple I mean, the task can be done all at once, in one piece. It has no dependencies on other tasks. This works well for performing a file upload task in the background (to avoid tying up a Ruby virtual machine process/thread). More complex (compound) multi-part tasks, however, do not fit this model. Examples of complex (compound) tasks include:
8
+ Queuing works well for simple tasks. By simple we mean, the task can be done all at once, in one piece. It has no dependencies on other tasks. This works well for performing a file upload task in the background (to avoid tying up a Ruby virtual machine process/thread). More complex (compound) multi-part tasks, however, do not fit this model. Examples of complex (compound) tasks include:
9
9
 
10
10
  1. pipelined (multi-step) generation of complex PDF documents
11
11
  2. extract/transfer/load (ETL) jobs that may load thousands of database records
@@ -27,6 +27,13 @@ Or install it yourself as:
27
27
 
28
28
  $ gem install orchestrated
29
29
 
30
+ Now generate the database migration:
31
+
32
+ $ rails g orchestrated:active_record
33
+ $ rake db:migrate
34
+
35
+ If you do not already have [delayed_job](https://github.com/collectiveidea/delayed_job) set up, you'll need to do that as well.
36
+
30
37
  The API
31
38
  -------
32
39
 
@@ -53,14 +60,20 @@ Declaring ```acts_as_orchestrated``` on your class gives it two methods:
53
60
  * ```orchestrated```—call this to specify your workflow prerequisite, and designate a workflow step
54
61
  * ```orchestration```—call this in the context of a workflow step (execution) to access orchestration (and prerequisite) context
55
62
 
56
- After that you can orchestrate any method on such a class e.g.
63
+ After that you can orchestrate any method on such a class. Let's say you needed to download files from a remote system (a slow process), transform each one, and then load it into your system. Imagine you had had a Downloader class that knew how to download and an Xform class that knew how to transform the downloaded file and load it into your system. You might write an orchestration like this:
57
64
 
58
65
  ```ruby
59
- gen = StatementGenerator.new
60
- gen.orchestrated( orchestrated.generate(stmt_id) ).render(stmt_id)
66
+ xform = Xform.new
67
+ xform.orchestrated(
68
+ xform.orchestrated(
69
+ Downloader.new.orchestrated.download(
70
+ :from=>'http://foo.bar.com/customer_fred', :to=>'fred_file'
71
+ )
72
+ ).transform('fred_file', 'fred_file_processed')
73
+ ).load('fred_file_processed')
61
74
  ```
62
75
 
63
- The next time you process a delayed job, the :generate message will be delivered. The time after that, the :render message will be delivered.
76
+ The next time you process a delayed job, the :download message will be delivered to a Downloader. After the download is complete, the next time a delayed job is processed, the :transform message will be delivered to an Xform object.
64
77
 
65
78
  What happened there? The pattern is:
66
79
 
@@ -68,7 +81,7 @@ What happened there? The pattern is:
68
81
  2. call orchestrated on it: this returns an "orchestration"
69
82
  3. send a message to the orchestration (returned in the second step)
70
83
 
71
- Now the messages you can send in (3) are limited to the messages that your object can respond to. The message will be "remembered" by the framework and "replayed" (on a new instance of your object) somewhere on the network (later).
84
+ Now the messages you can send in (3) are limited to the messages that your object can respond to. The message will be remembered by the framework and "replayed" (on a new instance of your object) somewhere on the network (later).
72
85
 
73
86
  Not accidentally, this is similar to the way [delayed_job](https://github.com/collectiveidea/delayed_job)'s delay method works. Under the covers, orchestrated is conspiring with [delayed_job](https://github.com/collectiveidea/delayed_job) when it comes time to actually execute a workflow step. Before that time though, orchestrated keeps track of everything.
74
87
 
data/Rakefile CHANGED
@@ -1 +1,4 @@
1
1
  require "bundler/gem_tasks"
2
+ # state_machine gem's Rake tasks aren't set up properly for use outside
3
+ # of Rails projects, hence the .. below
4
+ require 'state_machine/../tasks/state_machine'
@@ -0,0 +1,17 @@
1
+ # borrowed from delayed_job_active_record, and modified…
2
+ require 'rails/generators/migration'
3
+ require 'rails/generators/active_record/migration'
4
+
5
+ # Extend the DelayedJobGenerator so that it creates an AR migration
6
+ module Orchestrated
7
+ class ActiveRecordGenerator < Rails::Generators::Base
8
+ include Rails::Generators::Migration
9
+ extend ActiveRecord::Generators::Migration
10
+
11
+ self.source_paths << File.join(File.dirname(__FILE__), 'templates')
12
+
13
+ def create_migration_file
14
+ migration_template 'migration.rb', 'db/migrate/create_orchestrated.rb'
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ class CreateOrchestrated < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :orchestrations do |table|
4
+ table.string :state
5
+ table.text :handler
6
+ table.references :prerequisite
7
+ table.references :delayed_job, :polymorphic => true
8
+ table.timestamps
9
+ end
10
+ create_table :completion_expressions do |table|
11
+ table.string :type
12
+ # only one kind of completion expression needs this
13
+ # (OrchestrationCompletion) but I didn't want to put
14
+ # it in a separate table because it would really contort
15
+ # the Rails model
16
+ table.references :orchestration
17
+ end
18
+ create_table :composited_completions do |table|
19
+ table.references :composite_completion
20
+ table.references :completion_expression
21
+ end
22
+ end
23
+
24
+ def self.down
25
+ drop_table :composited_completions
26
+ drop_table :completion_expressions
27
+ drop_table :orchestrations
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module Orchestrated
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/orchestrated.gemspec CHANGED
@@ -18,16 +18,19 @@ Gem::Specification.new do |gem|
18
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
19
  gem.require_paths = ["lib"]
20
20
 
21
- gem.add_runtime_dependency 'delayed_job_active_record', '~> 0.3'
22
- gem.add_runtime_dependency 'activerecord', ['>= 3']
21
+ gem.add_runtime_dependency 'delayed_job_active_record', '>= 0.3'
22
+ gem.add_runtime_dependency 'activerecord', ['~> 3']
23
23
  gem.add_runtime_dependency 'state_machine', ['>= 1']
24
24
 
25
- gem.add_development_dependency 'rake'
26
- gem.add_development_dependency 'rails', ['>= 3'] # for rspec-rails
27
- gem.add_development_dependency 'rspec-rails'
25
+ gem.add_development_dependency 'rake', ['>= 10']
26
+ gem.add_development_dependency 'rails', ['~> 3'] # for rspec-rails
27
+ gem.add_development_dependency 'rspec-rails', ['>= 2.12']
28
28
  # I couldn't get rspecs transactional fixtures setting to do savepoints
29
29
  # in this project (which is not _really_ a Rails app). database_cleaner
30
30
  # claims it'll help us clean up the database so let's try it!
31
- gem.add_development_dependency 'database_cleaner'
32
- gem.add_development_dependency 'sqlite3'
31
+ gem.add_development_dependency 'database_cleaner', ['>= 0.9']
32
+ gem.add_development_dependency 'sqlite3', ['>= 1.3.6']
33
+ gem.add_development_dependency 'debugger'
34
+ # The state_machine:draw rake task needs this
35
+ gem.add_development_dependency 'ruby-graphviz', ['>= 0.9.0']
33
36
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orchestrated
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ~>
19
+ - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
21
  version: '0.3'
22
22
  type: :runtime
@@ -24,7 +24,7 @@ dependencies:
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ~>
27
+ - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0.3'
30
30
  - !ruby/object:Gem::Dependency
@@ -32,7 +32,7 @@ dependencies:
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
35
- - - ! '>='
35
+ - - ~>
36
36
  - !ruby/object:Gem::Version
37
37
  version: '3'
38
38
  type: :runtime
@@ -40,7 +40,7 @@ dependencies:
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
- - - ! '>='
43
+ - - ~>
44
44
  - !ruby/object:Gem::Version
45
45
  version: '3'
46
46
  - !ruby/object:Gem::Dependency
@@ -66,7 +66,7 @@ dependencies:
66
66
  requirements:
67
67
  - - ! '>='
68
68
  - !ruby/object:Gem::Version
69
- version: '0'
69
+ version: '10'
70
70
  type: :development
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -74,13 +74,13 @@ dependencies:
74
74
  requirements:
75
75
  - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
- version: '0'
77
+ version: '10'
78
78
  - !ruby/object:Gem::Dependency
79
79
  name: rails
80
80
  requirement: !ruby/object:Gem::Requirement
81
81
  none: false
82
82
  requirements:
83
- - - ! '>='
83
+ - - ~>
84
84
  - !ruby/object:Gem::Version
85
85
  version: '3'
86
86
  type: :development
@@ -88,7 +88,7 @@ dependencies:
88
88
  version_requirements: !ruby/object:Gem::Requirement
89
89
  none: false
90
90
  requirements:
91
- - - ! '>='
91
+ - - ~>
92
92
  - !ruby/object:Gem::Version
93
93
  version: '3'
94
94
  - !ruby/object:Gem::Dependency
@@ -98,7 +98,7 @@ dependencies:
98
98
  requirements:
99
99
  - - ! '>='
100
100
  - !ruby/object:Gem::Version
101
- version: '0'
101
+ version: '2.12'
102
102
  type: :development
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
@@ -106,7 +106,7 @@ dependencies:
106
106
  requirements:
107
107
  - - ! '>='
108
108
  - !ruby/object:Gem::Version
109
- version: '0'
109
+ version: '2.12'
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: database_cleaner
112
112
  requirement: !ruby/object:Gem::Requirement
@@ -114,7 +114,7 @@ dependencies:
114
114
  requirements:
115
115
  - - ! '>='
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: '0.9'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
@@ -122,9 +122,25 @@ dependencies:
122
122
  requirements:
123
123
  - - ! '>='
124
124
  - !ruby/object:Gem::Version
125
- version: '0'
125
+ version: '0.9'
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: sqlite3
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: 1.3.6
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: 1.3.6
142
+ - !ruby/object:Gem::Dependency
143
+ name: debugger
128
144
  requirement: !ruby/object:Gem::Requirement
129
145
  none: false
130
146
  requirements:
@@ -139,6 +155,22 @@ dependencies:
139
155
  - - ! '>='
140
156
  - !ruby/object:Gem::Version
141
157
  version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: ruby-graphviz
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: 0.9.0
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: 0.9.0
142
174
  description: a workflow orchestration framework running on delayed_job and active_record
143
175
  email:
144
176
  - bill@paydici.com
@@ -152,6 +184,8 @@ files:
152
184
  - Orchestrated::Orchestration_state.png
153
185
  - README.markdown
154
186
  - Rakefile
187
+ - lib/generators/orchestrated/active_record_generator.rb
188
+ - lib/generators/orchestrated/templates/migration.rb
155
189
  - lib/orchestrated.rb
156
190
  - lib/orchestrated/base.rb
157
191
  - lib/orchestrated/completion.rb