org-converge 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fd70719da7320b3897953946f0a2963b7357af63
4
+ data.tar.gz: 7132c1734caa2456114f35c029dad12615188073
5
+ SHA512:
6
+ metadata.gz: a11513f0b8d6395a12cf9372d8ebc5fcbf7afeb45ff2dffae3bb6230b3137c4c163b3eea5282ff895793d4d00854345a2d7352d28d3a7ab5ba5987ca2ac7f329
7
+ data.tar.gz: 50ef8e63011189ffd2f02dacbb4f32357b2b4d8c2ad410611a2b79eb4873ed282a95877e1f5a6b5e748bf6d538a99d7f95b9998ce9d7e9ef4b819056983b6045
data/Gemfile CHANGED
@@ -3,6 +3,7 @@ source 'https://rubygems.org'
3
3
  group :development, :test do
4
4
  gem 'rake'
5
5
  gem 'rspec'
6
+ gem 'nats', '0.5.0.beta.12'
6
7
  end
7
8
 
8
9
  gemspec
data/README.org CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  ** Description
9
9
 
10
- This attempts to be an experiment of using Org mode syntax to
10
+ This is an experiment of using Org mode to
11
11
  create documentable reproducible runs, borrowing some ideas
12
12
  of what is possible to do with tools like =chef-solo=,
13
13
  =rake=, =foreman=, etc...
@@ -18,15 +18,16 @@ of what is possible to do with tools like =chef-solo=,
18
18
 
19
19
  ** Motivation
20
20
 
21
- The Org babel syntax has proven to be flexible enough to writing
22
- /reproducible research/ papers. Then, I believe that configuring and setting up
23
- a server for example is something that could be also be done using
24
- the same syntax, given that /converging/ the configuration is something
25
- that one ought to be able to reproduce.
21
+ [[http://orgmode.org/worg/org-contrib/babel/Org Babel][Org Mode]] has proven to be flexible enough to write
22
+ [[http://www.jstatsoft.org/v46/i03][reproducible research papers]].
23
+ Then, I believe that configuring and setting up
24
+ a server for example, is something that could also be done using
25
+ the same approach, given that /converging/ the configuration
26
+ is a kind of run that one ought to be able to reproduce.
26
27
 
27
28
  ** Usage
28
29
 
29
- To run the blocks in parallel...
30
+ To run the blocks in parallel:
30
31
 
31
32
  #+begin_src sh
32
33
  org-converge path/to/setup-file.org --runmode=parallel
@@ -45,12 +46,121 @@ it is possible to make the blocks depend on one another.
45
46
  org-converge path/to/setup-file.org --runmode=chained
46
47
  #+end_src
47
48
 
49
+ In case the blocks have results blocks, it is possible to run
50
+ the blocks and matched against the results with the ~org-spec~ helper command:
51
+
52
+ #+begin_src sh
53
+ org-spec path/to/file-spec.org
54
+ #+end_src
55
+
48
56
  *** Other commands available
49
57
 
50
58
  : org-run # alias for org-converge
51
59
  : org-tangle # just tangles the contents without running the blocks
52
60
 
53
- ** Quick example
61
+ ** How it works
62
+
63
+ Org Converge uses a liberally extended version of Org Babel
64
+ features in order to give support for converging the configuration
65
+ of a server, and the [[https://github.com/wallyqs/org-ruby][Ruby implementation of the Org mode parser]]
66
+ which makes integrating with useful Ruby tools like foreman, rake, rspec and ohai more straightforward.
67
+
68
+ For example, using Org Babel we can easily spread config
69
+ files on a server by writing the following on a ~server.org~ file.
70
+
71
+ #+begin_src sh
72
+ ,#+begin_src yaml :tangle /etc/component.yml
73
+ multitenant: false
74
+ status_port: 10004
75
+ ,#+end_src
76
+ #+end_src
77
+
78
+ And then configure it by running it as follows, (considering we have
79
+ the correct permissions for tangling at =/etc/component.yml=):
80
+
81
+ #+begin_src sh
82
+ sudo org-converge server.org
83
+ #+end_src
84
+
85
+ Next, let's say that we no only one want to set the configured templates,
86
+ but that we also want to install some packages. In that case, we
87
+ should be able to do the following:
88
+ (Note: Currently, only named blocks would be run)
89
+
90
+ #+begin_src sh
91
+ ,** Configuring the component
92
+  
93
+ ,#+begin_src yaml :tangle /etc/component.yml
94
+ multitenant: false
95
+ status_port: 10004
96
+ ,#+end_src
97
+
98
+ ,** Installing the dependencies
99
+
100
+ Need the following so that ~bundle install~ can compile
101
+ the native extensions correctly.
102
+
103
+ # Giving the block a name would make it run
104
+  
105
+ ,#+name: build_essentials
106
+ ,#+begin_src sh
107
+ apt-get install build-essentials -y
108
+ ,#+end_src
109
+  
110
+ Then the following should work:
111
+  
112
+ ,#+name: bundle_install 
113
+ ,#+begin_src sh
114
+ cd project_path
115
+ bundle install
116
+ ,#+end_src
117
+ #+end_src
118
+
119
+ Since we are using Org mode syntax, it is possible to reuse this setup file by including it.
120
+
121
+ #+begin_src sh
122
+ ,#+TITLE: Another setup
123
+
124
+ Include the code blocks from the server into this:
125
+ ,#+include: "server.org"
126
+
127
+ ,#+name: install_org_mode
128
+ ,#+begin_src sh
129
+ apt-get install org-mode -y
130
+ ,#+end_src
131
+ #+end_src
132
+
133
+ #+end_src
134
+
135
+ ** Examples
136
+
137
+ Currently there is support for the following kind of runs:
138
+
139
+ - runs where the blocks need to run sequentially (~--runmode=sequential~) ::
140
+
141
+ Each code block is part of a step to be ran
142
+
143
+ - runs where the blocks need to be run in parallel (~--runmode=parallel~) ::
144
+
145
+ One example of this is having what is supposed to be a distributed system running locally for development (where ~foreman~ would be used).
146
+
147
+ - runs where the blocks need to be run in sequence according to defined dependencies (~--runmode=chained~) ::
148
+
149
+ Set of runs that are usually covered by using something like rake, make, etc...
150
+
151
+ - runs where the blocks are run and matched against the expected results for testing (~--runmode=spec~) ::
152
+
153
+ Each block is run and there is an assertion to check whether the contents in ~#+RESULTS~ block match
154
+
155
+ Besides being able to specify which kind of run to use through an option, it is also possible
156
+ to define this within the Org mode file itself as an in buffer setting:
157
+
158
+ #+begin_src org
159
+ ,#+TITLE: Defining the runmode as an in buffer setting
160
+ ,#+runmode: sequential
161
+ #+end_src
162
+
163
+ *** Parallel runs
54
164
 
55
165
  The following is an example of running 3 processes
56
166
  in parallel by defining them as code blocks from
@@ -58,20 +168,20 @@ an Org mode file:
58
168
 
59
169
  #+begin_src sh
60
170
  ,#+TITLE: Running Org babel processes in parallel
61
-
171
+  
62
172
  ,* Print with different languages
63
-  
173
+   
64
174
  ,#+name: hello_from_bash
65
175
  ,#+begin_src sh :shebang #!/bin/bash
66
176
  while true; do echo "hello world from bash"; sleep 1; done
67
177
  ,#+end_src
68
-  
178
+    
69
179
  ,#+name: hello_from_ruby
70
180
  ,#+begin_src ruby :shebang #!/usr/local/bin/ruby
71
181
  $stdout.sync = true
72
182
  loop { puts "hello world from ruby" ; sleep 1 }
73
183
  ,#+end_src
74
-  
184
+    
75
185
  ,#+name: hello_from_python
76
186
  ,#+begin_src python :shebang #!/usr/bin/python
77
187
  import time
@@ -86,7 +196,7 @@ an Org mode file:
86
196
  We store this in a file named =hello.org= and then run it as follows:
87
197
 
88
198
  #+begin_src sh
89
- org-converge hello.org
199
+ org-run hello.org
90
200
  #+end_src
91
201
 
92
202
  This would produce an output similar to the following:
@@ -94,7 +204,7 @@ This would produce an output similar to the following:
94
204
  #+begin_src sh
95
205
  [2014-05-04T19:23:40 +0900] Tangling 0 files...
96
206
  [2014-05-04T19:23:40 +0900] Tangling succeeded!
97
- [2014-05-04T19:23:40 +0900] Tangling 3 scripts within directory: /Users/mariko/repos/org-converge/run...
207
+ [2014-05-04T19:23:40 +0900] Tangling 3 scripts within directory: /Users/wallyqs/repos/org-converge/run...
98
208
  [2014-05-04T19:23:40 +0900] Running code blocks now! (3 runnable blocks found in total)
99
209
  [2014-05-04T19:23:40 +0900] hello_from_bash (4664) -- started with pid 4664
100
210
  [2014-05-04T19:23:40 +0900] hello_from_ruby (4665) -- started with pid 4665
@@ -105,56 +215,70 @@ This would produce an output similar to the following:
105
215
  [2014-05-04T19:23:42 +0900] hello_from_ruby (4665) -- hello world from ruby
106
216
  #+end_src
107
217
 
108
- ** How it works
109
-
110
- Org Converge uses an liberally extended version of Org Babel
111
- features in order to give support for converging the configuration
112
- of a server.
113
-
114
- For example, using Org Babel and macros we can easily spread config
115
- files on a server by writing the following on a ~server.org~ file.
218
+ Also possible to specify the name of the block to be ran:
116
219
 
117
220
  #+begin_src sh
118
- ,#+begin_src yaml :tangle /etc/component.yml
119
- multitenant: false
120
- status_port: 10004
121
- ,#+end_src
221
+ org-run hello.org --name from_ruby
122
222
  #+end_src
123
223
 
124
- And then configure it by running it as follows, (considering we have
125
- the correct permissions for tangling at =/etc/component.yml=):
224
+ *** Spec mode
225
+
226
+ In case the Org mode file has a results block which represents the expected result,
227
+ there is an ~org-spec~ command which can be useful to check whether there is change.
228
+ For example, given the following file stored in ~test.org~:
126
229
 
127
230
  #+begin_src sh
128
- sudo org-converge server.org
231
+ ,#+TITLE: Expected results example
232
+  
233
+ ,#+name: hello
234
+ ,#+begin_src ruby :results output
235
+ 10.times do
236
+ puts "hola"
237
+ end
238
+ ,#+end_src
239
+  
240
+ ,#+RESULTS: hello
241
+ ,#+begin_example
242
+ hola
243
+ hola
244
+ hola
245
+ hola
246
+ hola
247
+ hola
248
+ hola
249
+ hola
250
+ hola
251
+ hola
252
+ ,#+end_example
129
253
  #+end_src
130
254
 
131
- Next, let's say that we no only one want to set the configured templates,
132
- but that we also want to install some packages. In that case, we
133
- should be able to do the following:
255
+ We can be able to verify whether this is still correct by running ~org-spec test.org~
134
256
 
135
257
  #+begin_src sh
136
- ,* Configuring the component
137
-
138
- ,#+begin_src yaml :tangle /etc/component.yml
139
- multitenant: false
140
- status_port: 10004
141
- ,#+end_src
142
-
143
- ,* Installing the dependencies
144
-
145
- Need the following so that ~bundle install~ can compile
146
- the native extensions correctly.
258
+ Checking results from 'hello' code block: OK
259
+ #+end_src
147
260
 
148
- ,#+begin_src sh
149
- apt-get install build-essentials -y
150
- ,#+end_src
151
-  
152
- Then the following should work:
153
-  
154
- ,#+begin_src sh
155
- cd project_path
156
- bundle install
157
- ,#+end_src
261
+ As an example, let's say that the behavior of the original code block changed, and now says hello 5 times instead.
262
+ In that case the output would be as follows:
263
+
264
+ #+begin_src diff
265
+ Checking results from 'hello' code block: DIFF
266
+ @@ -1,11 +1,6 @@
267
+ -hola
268
+ -hola
269
+ -hola
270
+ -hola
271
+ -hola
272
+ -hola
273
+ -hola
274
+ -hola
275
+ -hola
276
+ -hola
277
+ +hello
278
+ +hello
279
+ +hello
280
+ +hello
281
+ +hello
158
282
  #+end_src
159
283
 
160
284
  ** Contributing
data/TODO CHANGED
@@ -2,7 +2,7 @@
2
2
  #+TODO: TODO | DONE CANCELED
3
3
  #+startup: showeverything
4
4
 
5
- * [0/7] > 0.0.9 version
5
+ * [0/9] 0.1.0 version
6
6
 
7
7
  - [ ] Macros can be loaded and applied to the configuration
8
8
  - [ ] Actually support converging and idempotency (~--runmode=idempotent~)
@@ -14,9 +14,15 @@
14
14
  - [ ] Display how the run would look like without making changes
15
15
  : org-converge setupfile.org --dry-run
16
16
  - [ ] Use :eval for evaling blocks (off by default)
17
- - [ ] Can use :dir for running a process relative to that directory
17
+ - [ ] Can use ~:dir~ for running a process relative to that directory
18
+ - [ ] Bugfix for when results blocks have only inline examples or images
19
+ - [ ] Bugfix for when the result from a ~org-spec~ run has non-zero exit status
18
20
 
19
- * [1/1] 0.0.8 version
21
+ * [1/1] 0.0.10
22
+
23
+ - [X] Add ~:procs~ to code blocks to identify how many times it should run
24
+
25
+ * [1/1] 0.0.8, 0.0.9 version
20
26
 
21
27
  - [X] ~org-spec~ exploration!
22
28
 
@@ -64,7 +64,8 @@ module Orgmode
64
64
  :mkdirp => line.block_header_arguments[':mkdirp'],
65
65
  :name => line.properties['block_name'],
66
66
  :before => line.block_header_arguments[':before'],
67
- :after => line.block_header_arguments[':after']
67
+ :after => line.block_header_arguments[':after'],
68
+ :procs => line.block_header_arguments[':procs'],
68
69
  }
69
70
  @scripts[@scripts_counter][:lang] = line.block_lang
70
71
  # TODO: have a way to specify which are the default binaries to be used per language
@@ -163,8 +163,7 @@ module OrgConverge
163
163
  # Decision: Only run blocks which have a name
164
164
  next unless script[:header][:name]
165
165
 
166
- display_name = script[:header][:name]
167
- @engine.register display_name, cmd, { :cwd => @root_dir, :logger => logger }
166
+ run_procs(script, cmd)
168
167
  end
169
168
  logger.info "Running code blocks now! (#{babel.ob.scripts.count} runnable blocks found in total)"
170
169
  @engine.start
@@ -178,8 +177,7 @@ module OrgConverge
178
177
  scripts.each do |key, script|
179
178
  file = File.expand_path("#{@run_dir}/#{key}")
180
179
  cmd = "#{script[:lang]} #{file}"
181
- display_name = script[:header][:name]
182
- @engine.register display_name, cmd, { :cwd => @root_dir, :logger => logger }
180
+ run_procs(script, cmd)
183
181
  end
184
182
 
185
183
  logger.info "Running code blocks now! (#{scripts.count} runnable blocks found in total)"
@@ -281,6 +279,7 @@ module OrgConverge
281
279
  exit 1 if failed.count > 0
282
280
  end
283
281
 
282
+ private
284
283
  def diff(expected_lines, actual_lines)
285
284
  output = ""
286
285
  file_length_difference = 0
@@ -335,5 +334,18 @@ module OrgConverge
335
334
  puts block[:lines]
336
335
  end
337
336
  end
337
+
338
+ def run_procs(script, cmd)
339
+ display_name = script[:header][:name]
340
+ if script[:header][:procs]
341
+ procs = script[:header][:procs].to_i
342
+ procs.times do |i|
343
+ proc_name = "#{display_name}-#{i}"
344
+ @engine.register proc_name, cmd, { :cwd => @root_dir, :logger => logger }
345
+ end
346
+ else
347
+ @engine.register display_name, cmd, { :cwd => @root_dir, :logger => logger }
348
+ end
349
+ end
338
350
  end
339
351
  end
@@ -1,3 +1,3 @@
1
1
  module OrgConverge
2
- VERSION = "0.0.9"
2
+ VERSION = "0.0.10"
3
3
  end
data/org-converge.gemspec CHANGED
@@ -14,9 +14,10 @@ Gem::Specification.new do |gem|
14
14
  gem.name = "org-converge"
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = OrgConverge::VERSION
17
- gem.add_runtime_dependency('docopt', '~> 0.5.0')
18
- gem.add_runtime_dependency('org-ruby', '~> 0.9.6')
19
- gem.add_runtime_dependency('foreman', '~> 0.63.0')
20
- gem.add_runtime_dependency('tco', '~> 0.1.0')
17
+ gem.add_runtime_dependency('docopt', '~> 0.5')
18
+ gem.add_runtime_dependency('org-ruby', '~> 0.9')
19
+ gem.add_runtime_dependency('foreman', '~> 0.63')
20
+ gem.add_runtime_dependency('tco', '~> 0.1')
21
21
  gem.add_runtime_dependency('rake', '~> 10.3')
22
+ gem.add_runtime_dependency('diff-lcs', '~> 1.2')
22
23
  end
@@ -6,7 +6,7 @@ with all output being flushed to the screen.
6
6
  - Count some numbers with bash
7
7
 
8
8
  #+name: bash_counter
9
- #+begin_src sh :shebang #!/bin/bash
9
+ #+begin_src bash :shebang #!/bin/bash
10
10
  echo '' > out.log
11
11
  for i in `seq 1 5`; do
12
12
  echo "Writing! $i"
@@ -8,27 +8,27 @@
8
8
  ** Runnable blocks
9
9
 
10
10
  #+name: runnable_block_1
11
- #+begin_src sh :results output
11
+ #+begin_src bash :results output
12
12
  echo "first" > output.log
13
13
  #+end_src
14
14
 
15
15
  ** COMMENT Non runnable blocks
16
16
 
17
17
  #+name: not_runnable_block_2
18
- #+begin_src sh :results output
18
+ #+begin_src bash :results output
19
19
  echo "should not run" >> output.log
20
20
  #+end_src
21
21
 
22
22
  ** More runnable blocks
23
23
 
24
24
  #+name: runnable_block_3
25
- #+begin_src sh :results output
25
+ #+begin_src bash :results output
26
26
  echo "third" >> output.log
27
27
  #+end_src
28
28
 
29
29
  *** COMMENT Not runnable block
30
30
 
31
31
  #+name: not_runnable_block_4
32
- #+begin_src sh :results output
32
+ #+begin_src bash :results output
33
33
  echo "fourth" >> output.log
34
34
  #+end_src
@@ -7,7 +7,7 @@ results, we can try checking whether the contents from the code block
7
7
  are evaling into what is being documented in the results block.
8
8
 
9
9
  #+name: hello
10
- #+begin_src sh :results output code :exports both
10
+ #+begin_src bash :results output code :exports both
11
11
  for i in `seq 20`; do
12
12
  echo "hello"
13
13
  done
@@ -26,7 +26,7 @@ This one would fail near christmas, outside of Japan,
26
26
  when the site is down, or there is a change in the rss.xml being provided.
27
27
 
28
28
  #+name: christmas_check
29
- #+begin_src sh :results output
29
+ #+begin_src bash :results output
30
30
  curl https://isitchristmas.com/rss.xml 2> /dev/null | grep title
31
31
  # curl isitchristmastyet.com 2> /dev/null
32
32
  #+end_src
@@ -34,29 +34,14 @@ curl https://isitchristmas.com/rss.xml 2> /dev/null | grep title
34
34
  #+RESULTS: christmas_check
35
35
  #+begin_example
36
36
  <title>Is It Christmas?</title>
37
- <title>いいえ</title>
38
- <title>いいえ</title>
39
- <title>いいえ</title>
40
- <title>いいえ</title>
41
- <title>いいえ</title>
42
- <title>いいえ</title>
43
- <title>いいえ</title>
44
- <title>いいえ</title>
45
- <title>いいえ</title>
46
- <title>いいえ</title>
47
- #+end_example
48
-
49
- #+RESULTS: fetch_google
50
- #+begin_example
51
- <title>Is It Christmas?</title>
52
- <title>いいえ</title>
53
- <title>いいえ</title>
54
- <title>いいえ</title>
55
- <title>いいえ</title>
56
- <title>いいえ</title>
57
- <title>いいえ</title>
58
- <title>いいえ</title>
59
- <title>いいえ</title>
60
- <title>いいえ</title>
61
- <title>いいえ</title>
37
+ <title>NO</title>
38
+ <title>NO</title>
39
+ <title>NO</title>
40
+ <title>NO</title>
41
+ <title>NO</title>
42
+ <title>NO</title>
43
+ <title>NO</title>
44
+ <title>NO</title>
45
+ <title>NO</title>
46
+ <title>NO</title>
62
47
  #+end_example
@@ -9,7 +9,7 @@ With ~:after first~, the ~second~ block becomes
9
9
  a prerequisite of the ~first~ block.
10
10
 
11
11
  #+name: second
12
- #+begin_src sh :after first
12
+ #+begin_src bash :after first
13
13
  for i in `seq 5 10`; do
14
14
  echo $i >> out.log
15
15
  done
@@ -35,7 +35,7 @@ The same with ~:before all~, this would be executed
35
35
  at the beginning.
36
36
 
37
37
  #+name: prologue
38
- #+begin_src sh :before first :results output
38
+ #+begin_src bash :before first :results output
39
39
  echo "init" > out.log
40
40
  #+end_src
41
41
 
@@ -0,0 +1,347 @@
1
+ #+TITLE: Sequential and Distributed runs to solve Problem #4 from Project Euler, written in Org mode Babel mode
2
+ #+startup: showeverything
3
+
4
+ [[https://projecteuler.net/problem=4][Problem #4]] from Project Euler reads as follows:
5
+
6
+ #+begin_quote
7
+ A palindromic number reads the same both ways.
8
+ The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
9
+ Find the largest palindrome made from the product of two 3-digit numbers.
10
+ #+end_quote
11
+
12
+ We can notice the following from the problem:
13
+
14
+ - The definition of a palindrome ::
15
+ Can be implemented considering that the reverse list of chars should be identical to the original list.
16
+
17
+ - There is exponential growth ::
18
+ We look for the largest palindrome in the range of 3 digit numbers (100 - 999).
19
+ For this, we iterate 2 times on the range, multiply the entries and make the palindrome check.
20
+
21
+ *** First implementation: Sequential run to find the largest palindrome
22
+
23
+ A straightforward implementation of the problem is by iterating twice
24
+ over the same range and grabbing the highest largest number:
25
+
26
+ #+name: sequential_palindrome_check
27
+ #+begin_src ruby :results output
28
+ require 'benchmark'
29
+
30
+ def palindrome_check(number)
31
+ digits = number.to_s.split('').map(&:to_i)
32
+ reverse_is_equal = digits == digits.reverse ? true : false
33
+
34
+ reverse_is_equal
35
+ end
36
+
37
+ SMALLEST_NUMBER = 100
38
+ LARGEST_NUMBER = 999
39
+
40
+ last_palindrome = 0
41
+ last_x = 0
42
+ last_y = 0
43
+ bm = Benchmark.measure do
44
+ SMALLEST_NUMBER.upto(LARGEST_NUMBER).each do |i|
45
+ SMALLEST_NUMBER.upto(LARGEST_NUMBER).each do |j|
46
+
47
+ product = i * j
48
+ is_palindrome = palindrome_check(product)
49
+ if is_palindrome and product > last_palindrome
50
+ last_palindrome = product
51
+ last_x = i
52
+ last_y = j
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ puts "The largest palindrome within this range is: #{last_palindrome} (x: #{last_x}, y: #{last_y}) and it took #{bm}"
59
+ #+end_src
60
+
61
+ #+RESULTS:
62
+ : The largest palindrome within this range is: 906609 (x: 913, y: 993) and it took 16.36000
63
+
64
+ For 3 digits, this approach seems like good enough. But what if we
65
+ want to find out the largest palindrome number with 4 digits? Since
66
+ growth is exponential, running this in a single process will take a
67
+ while to finish.
68
+
69
+ *** Second implementation: Distributed parallel run to find the largest palindrome
70
+
71
+ One way to improve things is to parallelize the computation and
72
+ coordinating the aggregation of the results by using a message
73
+ bus. Borrowing [[http://blog.gopheracademy.com/plumbing-and-semantics][an idea]] in this case we use [[http://blog.gopheracademy.com/plumbing-and-semantics][NATS]].
74
+
75
+ The approach to take here will be:
76
+
77
+ - Split the ranges in subranges according to the number of subscribers
78
+ - Make each one of the subscribers do the computation for us and emit
79
+ the response with the results
80
+ - Collect the responses and identify the smallest, largest palindrome
81
+ within the range
82
+
83
+ For this run, we will have 10 checkers doing the calculation in
84
+ parallel, and one process collecting the replies.
85
+
86
+ #+name: dist_palindrome_checks_aggregator
87
+ #+begin_src ruby
88
+ # palindrome_checks_aggregator.rb
89
+ require 'nats/client'
90
+ require 'json'
91
+
92
+ sleep 6 # Wait for the checkers to be ready before sending compute requests
93
+ $stdout.sync = true
94
+ ["TERM", "INT"].each { |sig| trap(sig) { NATS.stop } }
95
+
96
+ MIN_RANGE = 100
97
+ MAX_RANGE = 999
98
+ CHECKERS = 10
99
+
100
+ @checkers_responses = 0
101
+ @palindromes = []
102
+
103
+ NATS.start {
104
+ # Stop running at the same time as the nats-server
105
+ EM.add_timer(40) { NATS.stop; exit 0 }
106
+ NATS.subscribe('palindromes-check.responses') do |msg, reply, sub|
107
+ palindromes_computation = JSON.parse(msg)
108
+ puts "Thanks, got: #{palindromes_computation['palindromes_found'].count} palindromes."
109
+ @palindromes << palindromes_computation['palindromes_found'].flatten
110
+ @checkers_responses += 1
111
+
112
+ total = @palindromes.flatten.count
113
+ smallest = @palindromes.flatten.min
114
+ largest = @palindromes.flatten.max
115
+ puts ">>>> So far we have found #{total} palindromes between #{MIN_RANGE} and #{MAX_RANGE}"
116
+ puts ">>>> The smallest one is #{smallest}"
117
+ puts ">>>> The largest one is #{largest}"
118
+ File.open('result', 'w') {|f| f.puts largest }
119
+ end
120
+
121
+ balanced_check = MAX_RANGE / CHECKERS
122
+
123
+ ranges = []
124
+ min_range = MIN_RANGE
125
+ begin
126
+ next_min_range = min_range + balanced_check
127
+ ranges << [min_range, next_min_range - 1]
128
+ min_range = next_min_range
129
+ end while min_range < MAX_RANGE
130
+
131
+ ranges.each do |range|
132
+ range_start = range.first
133
+ range_finish = [range.last, MAX_RANGE].min
134
+ range_info = {'start' => range_start, 'upto' => range_finish, 'min' => MIN_RANGE, 'max' => MAX_RANGE}
135
+
136
+ # Only want one checker to respond to this
137
+ NATS.request('palindromes-check.requests', nil, :max => 1) do |response|
138
+ checker_info = JSON.parse(response)
139
+ puts "Sending compute request to: #{checker_info}: #{range_info}"
140
+ NATS.publish("palindromes-check.#{checker_info['checker_id']}.compute", range_info.to_json) do
141
+ puts "Registered: #{range_info} to be done by #{checker_info['checker_id']}."
142
+ end
143
+ end
144
+
145
+ end
146
+ }
147
+ #+end_src
148
+
149
+ And each one of the checkers, has code as the one below to be able to
150
+ announce itself. Setting ~:procs 10~ to match the number of checkers
151
+ in the aggregator.
152
+
153
+ #+name: dist_palindrome_checker
154
+ #+begin_src ruby :procs 10
155
+ # palindrome_checker.rb
156
+ require 'nats/client'
157
+ require 'securerandom'
158
+ require 'json'
159
+
160
+ sleep 4 # wait a little before the server starts
161
+ $stdout.sync = true
162
+
163
+ CHECKER_ID = SecureRandom.uuid
164
+ CHECKER_INFO = {'checker_id' => CHECKER_ID }
165
+
166
+ @offerings = 0
167
+ @palindromes = []
168
+
169
+ def palindrome_check(number)
170
+ digits = number.to_s.split('').map(&:to_i)
171
+ reverse_is_equal = digits == digits.reverse ? true : false
172
+
173
+ reverse_is_equal
174
+ end
175
+
176
+ def compute_palindromes_in_range(range_info)
177
+ range = JSON.parse(range_info)
178
+
179
+ range_min = range['min']
180
+ range_max = range['max']
181
+ range_start = range['start']
182
+ range_upto = range['upto']
183
+
184
+ range_min.upto(range_max) do |i|
185
+ # Split this subrange among other checkers
186
+ range_start.upto(range_upto) do |j|
187
+ product = i * j
188
+ is_palindrome = palindrome_check(product)
189
+ @palindromes << product if is_palindrome
190
+ end
191
+ end
192
+
193
+ results = {'palindromes_found' => @palindromes }
194
+
195
+ results
196
+ end
197
+
198
+ NATS.start do
199
+ puts "[#{CHECKER_ID}] Ready for requests"
200
+ NATS.subscribe('palindromes-check.requests') do |msg, reply, sub|
201
+ EM.add_timer(@offerings) { NATS.publish(reply, CHECKER_INFO.to_json) }
202
+ @offerings += 1
203
+ end
204
+
205
+ NATS.subscribe("palindromes-check.#{CHECKER_ID}.compute") do |msg, reply, sub|
206
+ puts "Start working on: #{msg}"
207
+ results = compute_palindromes_in_range(msg)
208
+ @offerings -= 1
209
+ NATS.publish("palindromes-check.responses", results.to_json) do
210
+ puts "I'm done then."
211
+ NATS.stop
212
+ exit 0
213
+ end
214
+ end
215
+ end
216
+ #+end_src
217
+
218
+ **** Starting the run
219
+
220
+ Ruby implementation of NATS can be installed with:
221
+
222
+ #+begin_src sh
223
+ gem list | grep nats.*0.5.0.beta.12
224
+ [ $? -ne 0 ] && gem install nats --pre
225
+ #+end_src
226
+
227
+ And we execute the run as follows:
228
+
229
+ #+name: dist_nats_server_daemon
230
+ #+begin_src bash
231
+ # timeout nats in 30 seconds
232
+ (bundle exec nats-server) & sleep 40; kill $! 2> /dev/null || :
233
+ #+end_src
234
+
235
+ : palindrome_checks_aggregator.rb &
236
+ : for i in `seq 1 10`; do
237
+ : ruby palindrome_checker.rb &
238
+ : done
239
+
240
+ Or since this Gist is also written in literate Org mode style, it can be run as follows:
241
+
242
+ : gem install org-converge
243
+ : org-run palindromes.org
244
+
245
+ Sample output from this would look like this:
246
+
247
+ #+begin_src sh
248
+ [2014-05-27T04:40:51 +0900] Tangling 0 files...
249
+ [2014-05-27T04:40:51 +0900] Tangling succeeded!
250
+ [2014-05-27T04:40:51 +0900] Tangling 7 scripts within directory: /Users/mariko/Dropbox/repos/org-converge/run...
251
+ [2014-05-27T04:40:51 +0900] Running code blocks now! (7 runnable blocks found in total)
252
+ [2014-05-27T04:40:52 +0900] sequential_palindrome_check (87486) -- started with pid 87486
253
+ [2014-05-27T04:40:52 +0900] dist_palindrome_checks_aggregator (87487) -- started with pid 87487
254
+ [2014-05-27T04:40:52 +0900] dist_palindrome_checker-0 (87489) -- started with pid 87489
255
+ [2014-05-27T04:40:52 +0900] dist_palindrome_checker-1 (87491) -- started with pid 87491
256
+ [2014-05-27T04:40:52 +0900] dist_palindrome_checker-2 (87493) -- started with pid 87493
257
+ [2014-05-27T04:40:52 +0900] dist_palindrome_checker-3 (87494) -- started with pid 87494
258
+ [2014-05-27T04:40:52 +0900] dist_palindrome_checker-4 (87496) -- started with pid 87496
259
+ [2014-05-27T04:40:52 +0900] dist_palindrome_checker-5 (87498) -- started with pid 87498
260
+ [2014-05-27T04:40:52 +0900] dist_palindrome_checker-6 (87499) -- started with pid 87499
261
+ [2014-05-27T04:40:52 +0900] dist_palindrome_checker-7 (87500) -- started with pid 87500
262
+ [2014-05-27T04:40:52 +0900] dist_palindrome_checker-8 (87501) -- started with pid 87501
263
+ [2014-05-27T04:40:52 +0900] dist_palindrome_checker-9 (87502) -- started with pid 87502
264
+ [2014-05-27T04:40:52 +0900] dist_nats_server_daemon (87503) -- started with pid 87503
265
+ [2014-05-27T04:41:00 +0900] dist_palindrome_checker-0 (87489) -- [dc401559-c0c8-450b-a0fd-f2093b0f59e0] Ready for requests
266
+ [2014-05-27T04:41:00 +0900] dist_palindrome_checker-7 (87500) -- [7624024f-1be8-4962-aad6-aa2ae8366f0e] Ready for requests
267
+ [2014-05-27T04:41:00 +0900] dist_palindrome_checker-1 (87491) -- [218a8813-d5e9-4bc0-a206-c12ac5086126] Ready for requests
268
+ [2014-05-27T04:41:00 +0900] dist_palindrome_checker-4 (87496) -- [69b2b618-8a67-40c1-bf5a-988077a49251] Ready for requests
269
+ [2014-05-27T04:41:00 +0900] dist_palindrome_checker-8 (87501) -- [1e11550a-d609-461e-8ec6-9eae82c27ac6] Ready for requests
270
+ [2014-05-27T04:41:00 +0900] dist_palindrome_checker-2 (87493) -- [d1148625-360a-49ff-bd4d-257fecd9e7d6] Ready for requests
271
+ [2014-05-27T04:41:00 +0900] dist_palindrome_checker-5 (87498) -- [e72b34e7-22ff-42e0-9d6b-92aa26e15ace] Ready for requests
272
+ [2014-05-27T04:41:00 +0900] dist_palindrome_checker-3 (87494) -- [2f2b4180-3fcf-4461-8b59-632fdd5236a7] Ready for requests
273
+ [2014-05-27T04:41:00 +0900] dist_palindrome_checker-6 (87499) -- [d5129048-0994-4cd3-9cae-44c0d394de1e] Ready for requests
274
+ [2014-05-27T04:41:00 +0900] dist_palindrome_checker-9 (87502) -- [5c2b3866-41dd-4338-9c28-343d28291853] Ready for requests
275
+ [2014-05-27T04:41:02 +0900] dist_palindrome_checks_aggregator (87487) -- Sending compute request to: {"checker_id"=>"dc401559-c0c8-450b-a0fd-f2093b0f59e0"}: {"start"=>100, "upto"=>198, "min"=>100, "max"=>999}
276
+ [2014-05-27T04:41:02 +0900] dist_palindrome_checks_aggregator (87487) -- Registered: {"start"=>100, "upto"=>198, "min"=>100, "max"=>999} to be done by dc401559-c0c8-450b-a0fd-f2093b0f59e0.
277
+ [2014-05-27T04:41:02 +0900] dist_palindrome_checker-0 (87489) -- Start working on: {"start":100,"upto":198,"min":100,"max":999}
278
+ [2014-05-27T04:41:03 +0900] dist_palindrome_checks_aggregator (87487) -- Sending compute request to: {"checker_id"=>"7624024f-1be8-4962-aad6-aa2ae8366f0e"}: {"start"=>199, "upto"=>297, "min"=>100, "max"=>999}
279
+ [2014-05-27T04:41:03 +0900] dist_palindrome_checks_aggregator (87487) -- Registered: {"start"=>199, "upto"=>297, "min"=>100, "max"=>999} to be done by 7624024f-1be8-4962-aad6-aa2ae8366f0e.
280
+ [2014-05-27T04:41:03 +0900] dist_palindrome_checker-7 (87500) -- Start working on: {"start":199,"upto":297,"min":100,"max":999}
281
+ [2014-05-27T04:41:04 +0900] dist_palindrome_checks_aggregator (87487) -- Sending compute request to: {"checker_id"=>"218a8813-d5e9-4bc0-a206-c12ac5086126"}: {"start"=>298, "upto"=>396, "min"=>100, "max"=>999}
282
+ [2014-05-27T04:41:04 +0900] dist_palindrome_checker-1 (87491) -- Start working on: {"start":298,"upto":396,"min":100,"max":999}
283
+ [2014-05-27T04:41:04 +0900] dist_palindrome_checks_aggregator (87487) -- Registered: {"start"=>298, "upto"=>396, "min"=>100, "max"=>999} to be done by 218a8813-d5e9-4bc0-a206-c12ac5086126.
284
+ [2014-05-27T04:41:05 +0900] dist_palindrome_checks_aggregator (87487) -- Sending compute request to: {"checker_id"=>"1e11550a-d609-461e-8ec6-9eae82c27ac6"}: {"start"=>397, "upto"=>495, "min"=>100, "max"=>999}
285
+ [2014-05-27T04:41:05 +0900] dist_palindrome_checks_aggregator (87487) -- Registered: {"start"=>397, "upto"=>495, "min"=>100, "max"=>999} to be done by 1e11550a-d609-461e-8ec6-9eae82c27ac6.
286
+ [2014-05-27T04:41:05 +0900] dist_palindrome_checker-8 (87501) -- Start working on: {"start":397,"upto":495,"min":100,"max":999}
287
+ [2014-05-27T04:41:06 +0900] dist_palindrome_checks_aggregator (87487) -- Sending compute request to: {"checker_id"=>"d1148625-360a-49ff-bd4d-257fecd9e7d6"}: {"start"=>496, "upto"=>594, "min"=>100, "max"=>999}
288
+ [2014-05-27T04:41:06 +0900] dist_palindrome_checker-2 (87493) -- Start working on: {"start":496,"upto":594,"min":100,"max":999}
289
+ [2014-05-27T04:41:06 +0900] dist_palindrome_checks_aggregator (87487) -- Registered: {"start"=>496, "upto"=>594, "min"=>100, "max"=>999} to be done by d1148625-360a-49ff-bd4d-257fecd9e7d6.
290
+ [2014-05-27T04:41:07 +0900] dist_palindrome_checks_aggregator (87487) -- Sending compute request to: {"checker_id"=>"69b2b618-8a67-40c1-bf5a-988077a49251"}: {"start"=>595, "upto"=>693, "min"=>100, "max"=>999}
291
+ [2014-05-27T04:41:07 +0900] dist_palindrome_checks_aggregator (87487) -- Registered: {"start"=>595, "upto"=>693, "min"=>100, "max"=>999} to be done by 69b2b618-8a67-40c1-bf5a-988077a49251.
292
+ [2014-05-27T04:41:07 +0900] dist_palindrome_checker-4 (87496) -- Start working on: {"start":595,"upto":693,"min":100,"max":999}
293
+ [2014-05-27T04:41:08 +0900] dist_palindrome_checks_aggregator (87487) -- Sending compute request to: {"checker_id"=>"d5129048-0994-4cd3-9cae-44c0d394de1e"}: {"start"=>694, "upto"=>792, "min"=>100, "max"=>999}
294
+ [2014-05-27T04:41:08 +0900] dist_palindrome_checks_aggregator (87487) -- Registered: {"start"=>694, "upto"=>792, "min"=>100, "max"=>999} to be done by d5129048-0994-4cd3-9cae-44c0d394de1e.
295
+ [2014-05-27T04:41:08 +0900] dist_palindrome_checker-6 (87499) -- Start working on: {"start":694,"upto":792,"min":100,"max":999}
296
+ [2014-05-27T04:41:09 +0900] dist_palindrome_checks_aggregator (87487) -- Sending compute request to: {"checker_id"=>"e72b34e7-22ff-42e0-9d6b-92aa26e15ace"}: {"start"=>793, "upto"=>891, "min"=>100, "max"=>999}
297
+ [2014-05-27T04:41:09 +0900] dist_palindrome_checks_aggregator (87487) -- Registered: {"start"=>793, "upto"=>891, "min"=>100, "max"=>999} to be done by e72b34e7-22ff-42e0-9d6b-92aa26e15ace.
298
+ [2014-05-27T04:41:09 +0900] dist_palindrome_checker-5 (87498) -- Start working on: {"start":793,"upto":891,"min":100,"max":999}
299
+ [2014-05-27T04:41:10 +0900] dist_palindrome_checks_aggregator (87487) -- Thanks, got: 658 palindromes.
300
+ [2014-05-27T04:41:10 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> So far we have found 658 palindromes between 100 and 999
301
+ [2014-05-27T04:41:10 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The smallest one is 10201
302
+ [2014-05-27T04:41:10 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The largest one is 180081
303
+ [2014-05-27T04:41:10 +0900] dist_palindrome_checks_aggregator (87487) -- Sending compute request to: {"checker_id"=>"2f2b4180-3fcf-4461-8b59-632fdd5236a7"}: {"start"=>892, "upto"=>990, "min"=>100, "max"=>999}
304
+ [2014-05-27T04:41:10 +0900] dist_palindrome_checker-3 (87494) -- Start working on: {"start":892,"upto":990,"min":100,"max":999}
305
+ [2014-05-27T04:41:10 +0900] dist_palindrome_checks_aggregator (87487) -- Registered: {"start"=>892, "upto"=>990, "min"=>100, "max"=>999} to be done by 2f2b4180-3fcf-4461-8b59-632fdd5236a7.
306
+ [2014-05-27T04:41:11 +0900] dist_palindrome_checks_aggregator (87487) -- Sending compute request to: {"checker_id"=>"dc401559-c0c8-450b-a0fd-f2093b0f59e0"}: {"start"=>991, "upto"=>999, "min"=>100, "max"=>999}
307
+ [2014-05-27T04:41:11 +0900] dist_palindrome_checks_aggregator (87487) -- Registered: {"start"=>991, "upto"=>999, "min"=>100, "max"=>999} to be done by dc401559-c0c8-450b-a0fd-f2093b0f59e0.
308
+ [2014-05-27T04:41:11 +0900] dist_palindrome_checker-0 (87489) -- Start working on: {"start":991,"upto":999,"min":100,"max":999}
309
+ [2014-05-27T04:41:12 +0900] dist_palindrome_checks_aggregator (87487) -- Thanks, got: 662 palindromes.
310
+ [2014-05-27T04:41:12 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> So far we have found 1320 palindromes between 100 and 999
311
+ [2014-05-27T04:41:12 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The smallest one is 10201
312
+ [2014-05-27T04:41:12 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The largest one is 906609
313
+ [2014-05-27T04:41:14 +0900] dist_palindrome_checks_aggregator (87487) -- Thanks, got: 422 palindromes.
314
+ [2014-05-27T04:41:14 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> So far we have found 1742 palindromes between 100 and 999
315
+ [2014-05-27T04:41:14 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The smallest one is 10201
316
+ [2014-05-27T04:41:14 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The largest one is 906609
317
+ [2014-05-27T04:41:16 +0900] dist_palindrome_checks_aggregator (87487) -- Thanks, got: 287 palindromes.
318
+ [2014-05-27T04:41:16 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> So far we have found 2029 palindromes between 100 and 999
319
+ [2014-05-27T04:41:16 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The smallest one is 10201
320
+ [2014-05-27T04:41:16 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The largest one is 906609
321
+ [2014-05-27T04:41:18 +0900] dist_palindrome_checks_aggregator (87487) -- Thanks, got: 265 palindromes.
322
+ [2014-05-27T04:41:18 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> So far we have found 2294 palindromes between 100 and 999
323
+ [2014-05-27T04:41:18 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The smallest one is 10201
324
+ [2014-05-27T04:41:18 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The largest one is 906609
325
+ [2014-05-27T04:41:20 +0900] dist_palindrome_checks_aggregator (87487) -- Thanks, got: 204 palindromes.
326
+ [2014-05-27T04:41:20 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> So far we have found 2498 palindromes between 100 and 999
327
+ [2014-05-27T04:41:20 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The smallest one is 10201
328
+ [2014-05-27T04:41:20 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The largest one is 906609
329
+ [2014-05-27T04:41:20 +0900] dist_palindrome_checks_aggregator (87487) -- Thanks, got: 175 palindromes.
330
+ [2014-05-27T04:41:20 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> So far we have found 2673 palindromes between 100 and 999
331
+ [2014-05-27T04:41:20 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The smallest one is 10201
332
+ [2014-05-27T04:41:20 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The largest one is 906609
333
+ [2014-05-27T04:41:21 +0900] dist_palindrome_checks_aggregator (87487) -- Thanks, got: 162 palindromes.
334
+ [2014-05-27T04:41:21 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> So far we have found 2835 palindromes between 100 and 999
335
+ [2014-05-27T04:41:21 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The smallest one is 10201
336
+ [2014-05-27T04:41:21 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The largest one is 906609
337
+ [2014-05-27T04:41:21 +0900] dist_palindrome_checks_aggregator (87487) -- Thanks, got: 154 palindromes.
338
+ [2014-05-27T04:41:21 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> So far we have found 2989 palindromes between 100 and 999
339
+ [2014-05-27T04:41:21 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The smallest one is 10201
340
+ [2014-05-27T04:41:21 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The largest one is 906609
341
+ [2014-05-27T04:41:22 +0900] dist_palindrome_checks_aggregator (87487) -- Thanks, got: 139 palindromes.
342
+ [2014-05-27T04:41:22 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> So far we have found 3128 palindromes between 100 and 999
343
+ [2014-05-27T04:41:22 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The smallest one is 10201
344
+ [2014-05-27T04:41:22 +0900] dist_palindrome_checks_aggregator (87487) -- >>>> The largest one is 906609
345
+ [2014-05-27T04:41:34 +0900] sequential_palindrome_check (87486) -- The largest palindrome within this range is: 906609 (x: 913, y: 993) and it took 18.470000 0.270000 18.740000 ( 38.710531)
346
+ [2014-05-27T04:41:34 +0900] sequential_palindrome_check (87486) -- exited with code 0
347
+ #+end_src
@@ -5,7 +5,7 @@
5
5
  In this example, we will have scripts being chained one after another.
6
6
 
7
7
  #+name: first
8
- #+begin_src sh :shebang #!/bin/bash
8
+ #+begin_src bash :shebang #!/bin/bash
9
9
  sleep 5
10
10
  echo "first" > out.log
11
11
  #+end_src
@@ -119,7 +119,7 @@ describe OrgConverge::Command do
119
119
  success.should == true
120
120
  end
121
121
 
122
- it "should run 'expected_results' with example blocks" do
122
+ pending "should run 'expected_results' with example blocks" do
123
123
  example_dir = File.join(EXAMPLES_DIR, 'expected_results')
124
124
  setup_file = File.join(example_dir, 'spec2.org')
125
125
 
@@ -131,4 +131,18 @@ describe OrgConverge::Command do
131
131
  success = o.execute!
132
132
  success.should == true
133
133
  end
134
+
135
+ it "should run 'multi_proc' with the same number of defined :procs" do
136
+ example_dir = File.join(EXAMPLES_DIR, 'multi_proc')
137
+ setup_file = File.join(example_dir, 'run.org')
138
+
139
+ o = OrgConverge::Command.new({
140
+ '<org_file>' => setup_file,
141
+ '--root-dir' => example_dir
142
+ })
143
+ success = o.execute!
144
+ success.should == true
145
+ largest = File.open("#{example_dir}/result").read
146
+ largest.should == "906609\n"
147
+ end
134
148
  end
metadata CHANGED
@@ -1,71 +1,99 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: org-converge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
5
- prerelease:
4
+ version: 0.0.10
6
5
  platform: ruby
7
6
  authors:
8
7
  - Waldemar Quevedo
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-05-05 00:00:00.000000000 Z
11
+ date: 2014-05-26 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: docopt
16
- requirement: &70315024394420 !ruby/object:Gem::Requirement
17
- none: false
15
+ requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
21
- version: 0.5.0
19
+ version: '0.5'
22
20
  type: :runtime
23
21
  prerelease: false
24
- version_requirements: *70315024394420
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '0.5'
25
27
  - !ruby/object:Gem::Dependency
26
28
  name: org-ruby
27
- requirement: &70315024393940 !ruby/object:Gem::Requirement
28
- none: false
29
+ requirement: !ruby/object:Gem::Requirement
29
30
  requirements:
30
31
  - - ~>
31
32
  - !ruby/object:Gem::Version
32
- version: 0.9.6
33
+ version: '0.9'
33
34
  type: :runtime
34
35
  prerelease: false
35
- version_requirements: *70315024393940
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '0.9'
36
41
  - !ruby/object:Gem::Dependency
37
42
  name: foreman
38
- requirement: &70315024393480 !ruby/object:Gem::Requirement
39
- none: false
43
+ requirement: !ruby/object:Gem::Requirement
40
44
  requirements:
41
45
  - - ~>
42
46
  - !ruby/object:Gem::Version
43
- version: 0.63.0
47
+ version: '0.63'
44
48
  type: :runtime
45
49
  prerelease: false
46
- version_requirements: *70315024393480
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '0.63'
47
55
  - !ruby/object:Gem::Dependency
48
56
  name: tco
49
- requirement: &70315020658160 !ruby/object:Gem::Requirement
50
- none: false
57
+ requirement: !ruby/object:Gem::Requirement
51
58
  requirements:
52
59
  - - ~>
53
60
  - !ruby/object:Gem::Version
54
- version: 0.1.0
61
+ version: '0.1'
55
62
  type: :runtime
56
63
  prerelease: false
57
- version_requirements: *70315020658160
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '0.1'
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: rake
60
- requirement: &70315020657280 !ruby/object:Gem::Requirement
61
- none: false
71
+ requirement: !ruby/object:Gem::Requirement
62
72
  requirements:
63
73
  - - ~>
64
74
  - !ruby/object:Gem::Version
65
75
  version: '10.3'
66
76
  type: :runtime
67
77
  prerelease: false
68
- version_requirements: *70315020657280
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '10.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: diff-lcs
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '1.2'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '1.2'
69
97
  description: A light configuration management tool for Org mode
70
98
  email:
71
99
  - waldemar.quevedo@gmail.com
@@ -106,33 +134,33 @@ files:
106
134
  - spec/converge_examples/expected_results/spec.org
107
135
  - spec/converge_examples/expected_results/spec2.org
108
136
  - spec/converge_examples/linked_tasks/tasks.org
137
+ - spec/converge_examples/multi_proc/run.org
109
138
  - spec/converge_examples/runlist_example/setup.org
110
139
  - spec/converge_examples/specified_block/run.org
111
140
  - spec/converge_spec.rb
112
141
  - spec/spec_helper.rb
113
142
  homepage: https://github.com/wallyqs/org-converge
114
143
  licenses: []
144
+ metadata: {}
115
145
  post_install_message:
116
146
  rdoc_options: []
117
147
  require_paths:
118
148
  - lib
119
149
  required_ruby_version: !ruby/object:Gem::Requirement
120
- none: false
121
150
  requirements:
122
- - - ! '>='
151
+ - - '>='
123
152
  - !ruby/object:Gem::Version
124
153
  version: '0'
125
154
  required_rubygems_version: !ruby/object:Gem::Requirement
126
- none: false
127
155
  requirements:
128
- - - ! '>='
156
+ - - '>='
129
157
  - !ruby/object:Gem::Version
130
158
  version: '0'
131
159
  requirements: []
132
160
  rubyforge_project:
133
- rubygems_version: 1.8.10
161
+ rubygems_version: 2.2.2
134
162
  signing_key:
135
- specification_version: 3
163
+ specification_version: 4
136
164
  summary: Provides an 'org-converge' command which can be used for tangling and running
137
165
  Org mode code blocks
138
166
  test_files:
@@ -143,8 +171,8 @@ test_files:
143
171
  - spec/converge_examples/expected_results/spec.org
144
172
  - spec/converge_examples/expected_results/spec2.org
145
173
  - spec/converge_examples/linked_tasks/tasks.org
174
+ - spec/converge_examples/multi_proc/run.org
146
175
  - spec/converge_examples/runlist_example/setup.org
147
176
  - spec/converge_examples/specified_block/run.org
148
177
  - spec/converge_spec.rb
149
178
  - spec/spec_helper.rb
150
- has_rdoc: