elf 0.0.1.alpha → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -18,7 +18,59 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
- Elves are creatures to manage background processes.
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
 
@@ -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 success=(&blk)
9
+ def on_success(&blk)
9
10
  @success = blk
10
- success if @status.exitstatus == 0
11
+ if @status && @status.exitstatus == 0
12
+ success
13
+ end
11
14
  end
12
15
 
13
- def success
16
+ def fire_success
14
17
  puts "Success: #{@cmd}"
15
- @success.call if @success
18
+ if @success
19
+ @success.call
20
+ end
16
21
  end
17
22
 
18
- def error
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 ? success : error
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
@@ -1,10 +1,12 @@
1
1
  module Elf
2
2
  class Fork < Child
3
- alias :sync_fire :fire
4
3
 
4
+ #
5
+ # We can't use Thread's here. because they don't work :)
6
+ #
5
7
  def fire
6
- fork do
7
- sync_fire
8
+ pid = fork do
9
+ super
8
10
  end
9
11
  end
10
12
 
@@ -1,16 +1,20 @@
1
1
  module Elf
2
2
  class Process
3
3
  def initialize(&blk)
4
- blk.call(self)
5
- st = ::Process.waitall
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
@@ -1,5 +1,10 @@
1
1
  module Elf
2
2
  class Sync < Child
3
3
 
4
+ def fire
5
+ ::Process.waitall
6
+ super
7
+ end
8
+
4
9
  end
5
10
  end
@@ -1,3 +1,3 @@
1
1
  module Elf
2
- VERSION = "0.0.1.alpha"
2
+ VERSION = "0.0.1"
3
3
  end
@@ -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 2")
20
- elf.sync("sleep 3")
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.alpha
5
- prerelease: 6
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: 1.3.1
52
+ version: '0'
53
53
  requirements: []
54
54
  rubyforge_project:
55
55
  rubygems_version: 1.8.15