elf 0.0.1.alpha → 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.
- data/README.md +53 -1
- data/lib/elf/child.rb +16 -8
- data/lib/elf/fork.rb +5 -3
- data/lib/elf/process.rb +8 -4
- data/lib/elf/sync.rb +5 -0
- data/lib/elf/version.rb +1 -1
- data/spec/elf/process_spec.rb +76 -2
- metadata +4 -4
data/README.md
CHANGED
@@ -18,7 +18,59 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
|
21
|
+
This code will run 4 parallel processes and will work about 10 seconds
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'elf'
|
25
|
+
|
26
|
+
Elf.new do |elf|
|
27
|
+
elf.fork("sleep 10")
|
28
|
+
elf.fork("sleep 10")
|
29
|
+
elf.fork("sleep 10")
|
30
|
+
elf.fork("sleep 10")
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
And this will run each process one by one
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
require 'elf'
|
38
|
+
|
39
|
+
Elf.new do |elf|
|
40
|
+
elf.sync("sleep 10")
|
41
|
+
elf.sync("sleep 10")
|
42
|
+
elf.sync("sleep 10")
|
43
|
+
elf.sync("sleep 10")
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
So why do we need this?
|
48
|
+
|
49
|
+
For example you have got some slow rake tasks, which should be started in particular order. Some of them could be started in parallel, while other shoud work synchronously.
|
50
|
+
|
51
|
+
You have got this task:
|
52
|
+
|
53
|
+
1. Download few big XML files from some server
|
54
|
+
2. Parse them and save to database
|
55
|
+
3. Then you need to combine all this new data and get new big XML file
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
Elf.new do |elf|
|
59
|
+
# let's asynchronously download files and after file is downloaded we will start parse it
|
60
|
+
elf.fork("wget file1.xml") do |f|
|
61
|
+
f.on_success{ elf.fork("rake some_parser_rake_task") }
|
62
|
+
end
|
63
|
+
elf.fork("wget file2.xml") do |f|
|
64
|
+
f.on_success{ elf.fork("rake some_parser_rake_task") }
|
65
|
+
end
|
66
|
+
elf.fork("wget file3.xml") do |f|
|
67
|
+
f.on_success{ elf.fork("rake some_parser_rake_task") }
|
68
|
+
end
|
69
|
+
|
70
|
+
# Here we are waiting while all data downloaded and parsed and then start new rake task for generating new xml
|
71
|
+
elf.sync("rake generate_new_xml")
|
72
|
+
end
|
73
|
+
```
|
22
74
|
|
23
75
|
## Contributing
|
24
76
|
|
data/lib/elf/child.rb
CHANGED
@@ -1,31 +1,39 @@
|
|
1
1
|
module Elf
|
2
2
|
class Child
|
3
|
+
attr_reader :success
|
4
|
+
|
3
5
|
def initialize(cmd)
|
4
6
|
@cmd = cmd
|
5
|
-
fire
|
6
7
|
end
|
7
8
|
|
8
|
-
def
|
9
|
+
def on_success(&blk)
|
9
10
|
@success = blk
|
10
|
-
|
11
|
+
if @status && @status.exitstatus == 0
|
12
|
+
success
|
13
|
+
end
|
11
14
|
end
|
12
15
|
|
13
|
-
def
|
16
|
+
def fire_success
|
14
17
|
puts "Success: #{@cmd}"
|
15
|
-
|
18
|
+
if @success
|
19
|
+
@success.call
|
20
|
+
end
|
16
21
|
end
|
17
22
|
|
18
|
-
def
|
23
|
+
def fire_error
|
19
24
|
puts "Failed: #{@cmd}"
|
20
25
|
end
|
21
26
|
|
22
27
|
def fire
|
28
|
+
puts "Fired: #{@cmd}"
|
23
29
|
fork_pid = ::Process.fork do
|
24
|
-
puts "Fired: #{@cmd}"
|
25
30
|
exec @cmd
|
26
31
|
end
|
32
|
+
fake = fork{ "sleep 10" }
|
27
33
|
pid, @status = ::Process.waitpid2(fork_pid)
|
28
|
-
@status.exitstatus == 0 ?
|
34
|
+
@status.exitstatus == 0 ? fire_success : fire_error
|
35
|
+
::Process.kill(9, fake) rescue nil
|
36
|
+
::Process.waitall
|
29
37
|
end
|
30
38
|
end
|
31
39
|
end
|
data/lib/elf/fork.rb
CHANGED
data/lib/elf/process.rb
CHANGED
@@ -1,16 +1,20 @@
|
|
1
1
|
module Elf
|
2
2
|
class Process
|
3
3
|
def initialize(&blk)
|
4
|
-
blk.call(self)
|
5
|
-
|
4
|
+
pid = blk.call(self)
|
5
|
+
::Process.waitall
|
6
6
|
end
|
7
7
|
|
8
8
|
def fork(cmd)
|
9
|
-
Elf::Fork.new(cmd)
|
9
|
+
elf = Elf::Fork.new(cmd)
|
10
|
+
yield elf if block_given?
|
11
|
+
pid = elf.fire
|
10
12
|
end
|
11
13
|
|
12
14
|
def sync(cmd)
|
13
|
-
Elf::Sync.new(cmd)
|
15
|
+
elf = Elf::Sync.new(cmd)
|
16
|
+
yield elf if block_given?
|
17
|
+
elf.fire
|
14
18
|
end
|
15
19
|
end
|
16
20
|
end
|
data/lib/elf/sync.rb
CHANGED
data/lib/elf/version.rb
CHANGED
data/spec/elf/process_spec.rb
CHANGED
@@ -16,8 +16,82 @@ describe Elf::Process do
|
|
16
16
|
start = Time.now
|
17
17
|
Elf::Process.new do |elf|
|
18
18
|
elf.sync("sleep 1")
|
19
|
-
elf.sync("sleep
|
20
|
-
elf.sync("sleep
|
19
|
+
elf.sync("sleep 1")
|
20
|
+
elf.sync("sleep 1")
|
21
|
+
end
|
22
|
+
(Time.now-start).to_i.must_equal(3)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should run 4 combined processes" do
|
26
|
+
start = Time.now
|
27
|
+
Elf::Process.new do |elf|
|
28
|
+
elf.fork("sleep 1")
|
29
|
+
elf.fork("sleep 1")
|
30
|
+
elf.sync("sleep 1")
|
31
|
+
elf.sync("sleep 1")
|
32
|
+
elf.fork("sleep 1")
|
33
|
+
end
|
34
|
+
(Time.now-start).to_i.must_equal(4)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should fire success process" do
|
38
|
+
start = Time.now
|
39
|
+
Elf::Process.new do |elf|
|
40
|
+
elf.fork("sleep 1") do |fork|
|
41
|
+
fork.on_success do
|
42
|
+
elf.fork("sleep 1")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
elf.sync("sleep 1") do |fork|
|
46
|
+
fork.on_success do
|
47
|
+
elf.sync("sleep 1")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
elf.sync("sleep 1")
|
51
|
+
end
|
52
|
+
(Time.now-start).to_i.must_equal(5)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should work with deep nested success jobs" do
|
56
|
+
start = Time.now
|
57
|
+
Elf::Process.new do |elf|
|
58
|
+
elf.fork("sleep 1") do |f1|
|
59
|
+
f1.on_success do
|
60
|
+
elf.fork("sleep 1") do |f2|
|
61
|
+
f2.on_success do
|
62
|
+
elf.fork("sleep 1") do |f3|
|
63
|
+
f3.on_success do
|
64
|
+
elf.fork("sleep 1")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
(Time.now-start).to_i.must_equal(4)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should work with deep nested complex sync async success jobs" do
|
76
|
+
start = Time.now
|
77
|
+
Elf::Process.new do |elf|
|
78
|
+
elf.fork("sleep 1") do |f1|
|
79
|
+
f1.on_success do
|
80
|
+
elf.fork("sleep 1") do |f2|
|
81
|
+
f2.on_success do
|
82
|
+
elf.fork("sleep 1") do |f3|
|
83
|
+
f3.on_success do
|
84
|
+
elf.fork("sleep 1")
|
85
|
+
elf.fork("sleep 1")
|
86
|
+
elf.fork("sleep 1")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
elf.sync("sleep 1")
|
92
|
+
elf.fork("sleep 1")
|
93
|
+
end
|
94
|
+
end
|
21
95
|
end
|
22
96
|
(Time.now-start).to_i.must_equal(6)
|
23
97
|
end
|
metadata
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Petr Yanovich
|
@@ -47,9 +47,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
47
47
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
48
|
none: false
|
49
49
|
requirements:
|
50
|
-
- - ! '
|
50
|
+
- - ! '>='
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version:
|
52
|
+
version: '0'
|
53
53
|
requirements: []
|
54
54
|
rubyforge_project:
|
55
55
|
rubygems_version: 1.8.15
|