rerun_task 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rerun_task.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ Rerun Task
2
+ ==========
3
+
4
+
5
+ Rerun task is gem for checking if your rake task was executed successfully. You have to place all your rake code to `WatchProcess.new("task_name").call{}`. I write below some examples.
6
+
7
+ Examples
8
+ ====
9
+ task :dummy_task => :environment do
10
+ WatchProcess.new("task_name").call do
11
+ # your code write here
12
+ end
13
+ end
14
+
15
+ Now if you run rake task, then is created pid-files of your process. To your crontab place task, which every 5th minute check if all task done successfully.
16
+
17
+ non-rails app
18
+ ====
19
+ If you use as non-rails app, you have to copy /bin/rerun_task_crontab.rb from gem to your app
20
+
21
+ */5 * * * * ruby /path/to/the/your-app/bin/rerun_task_crontab.rb
22
+
23
+ rails app
24
+ ====
25
+
26
+ If you use it in rails app, you can use rails runner
27
+
28
+ */5 * * * * cd path/to/your-app; bundle exec rails runner RerunTask::UnfinishedRunner.crontab_retry
29
+
30
+ Notes
31
+ ====
32
+ In this version is not allowed to run same process in same time.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ load "#{File.dirname(__FILE__)}/../lib/rerun_task.rb"
2
+
3
+ RerunTask::UnfinishedRunner.crontab_retry
@@ -0,0 +1 @@
1
+ pid_dir: "/tmp"
@@ -0,0 +1,4 @@
1
+ require 'yaml'
2
+ module RerunTask
3
+ CONFIG = YAML.load_file("#{File.dirname(__FILE__)}/../../config/rerun_task.yml")
4
+ end
@@ -0,0 +1,16 @@
1
+ module RerunTask
2
+ class Crontab
3
+ attr_accessor :content
4
+ def initialize
5
+ @content = %x[crontab -l]
6
+ @content = @content.split("\n")
7
+ end
8
+
9
+ def find_task(task_name)
10
+ match = @content.reject{|i| !i.include?(task_name)}
11
+ return nil if match.size == 0
12
+ match.first.split(" ")[5,9].join(" ")
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ module RerunTask
2
+ class Pids
3
+ def self.unfinished
4
+ res = []
5
+ Dir.glob("#{RerunTask::CONFIG['pid_dir']}/rerun_task/pids/*.pid").each do |file_path|
6
+ args = {}
7
+ File.open(file_path, 'r') do |f|
8
+ args = ProcessFile.parse_file(f.read)
9
+ end
10
+ next if args[:process_name].nil? || args[:pid].nil?
11
+ p = ProcessFile.load_file("#{RerunTask::CONFIG['pid_dir']}/rerun_task/pids", args[:process_name])
12
+ begin
13
+ p.process_exists?
14
+ rescue
15
+ res << p
16
+ next
17
+ end
18
+ end
19
+ res
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,79 @@
1
+ require 'pathname'
2
+
3
+ module RerunTask
4
+ class ProcessFile
5
+ attr_accessor :process_name, :pid
6
+
7
+ def initialize(pid_dir)
8
+ @pid_dir = pid_dir
9
+ FileUtils.mkdir_p(@pid_dir) unless Dir.exists?(@pid_dir)
10
+ end
11
+
12
+ def create_pid_file
13
+ if File.exists?(path)
14
+ puts "file exists #{path}"
15
+
16
+ process_from_file = ProcessFile.load_file(@pid_dir, process_name)
17
+ raise RuntimeError.new("Process #{process_name} is already running with pid #{process_from_file.pid}") if process_from_file.process_exists?
18
+ end
19
+
20
+ File.open(path, 'w+') do |f|
21
+ f.write(self.to_s)
22
+ end
23
+ end
24
+
25
+ def path
26
+ ProcessFile.create_file_path(@pid_dir, process_name)
27
+ end
28
+
29
+ def self.create_file_path(pid_dir, process_name)
30
+ basename = Pathname.new("#{pid_dir}/#{process_name}.pid").basename
31
+ "#{pid_dir}/#{basename}"
32
+ end
33
+
34
+ def process_name
35
+ @process_name = @process_name || extract_process_name(Process.pid)
36
+ end
37
+
38
+ def to_s
39
+ "#{Process.pid}\n#{process_name}"
40
+ end
41
+
42
+ def process_exists?
43
+ extract_process_name(pid) == @process_name
44
+ end
45
+
46
+ def self.load_file(pid_dir, process_name)
47
+ f = File.open(create_file_path(pid_dir, process_name), 'r')
48
+ p = ProcessFile.new(pid_dir)
49
+ args = parse_file(f.read)
50
+ p.process_name = process_name.nil? ? args[:process_name] : process_name
51
+ p.pid = args[:pid]
52
+ f.close
53
+ p
54
+ end
55
+
56
+ def self.parse_file(string)
57
+ a = string.split("\n")
58
+ { pid: a.first, process_name: a.last }
59
+ end
60
+
61
+ def destroy
62
+ FileUtils.rm(path)
63
+ end
64
+
65
+ private
66
+
67
+ def extract_process_name(pid)
68
+ ps_res = %x[ps ax]
69
+ ps_res = ps_res.split("\n")
70
+ name = ""
71
+ ps_res.each do |line|
72
+ rows = line.split(" ")
73
+ name = rows.last if rows.first == pid.to_s
74
+ end
75
+ raise RuntimeError.new("process_name not found for pid #{pid}") if name === ""
76
+ name
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,14 @@
1
+ module RerunTask
2
+ class UnfinishedRunner
3
+
4
+ def self.crontab_retry
5
+ crontab = Crontab.new()
6
+ Pids.unfinished.each do |process_file|
7
+ cmd = crontab.find_task(process_file.process_name)
8
+ next if cmd.nil?
9
+ puts "Running command #{cmd} again"
10
+ system("#{cmd} &")
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module RerunTask
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ module RerunTask
2
+ class WatchProcess
3
+
4
+ def initialize(rake_task_name)
5
+ @name = rake_task_name
6
+ @pid_dir = "#{RerunTask::CONFIG['pid_dir']}/rerun_task/pids"
7
+ @process_file = ProcessFile.new(@pid_dir)
8
+ end
9
+
10
+ def call(&block)
11
+ start
12
+ block.call
13
+ finished
14
+ end
15
+
16
+ def start
17
+ @process_file.create_pid_file
18
+ end
19
+
20
+ def finished
21
+ @process_file.destroy
22
+ end
23
+
24
+ end
25
+ end
data/lib/rerun_task.rb ADDED
@@ -0,0 +1,11 @@
1
+ require "rerun_task/version"
2
+ require "rerun_task/config"
3
+ require "rerun_task/watch_process"
4
+ require "rerun_task/process_file"
5
+ require "rerun_task/pids"
6
+ require "rerun_task/crontab"
7
+ require "rerun_task/unfinished_runner"
8
+
9
+ module RerunTask
10
+
11
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rerun_task/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rerun_task"
7
+ s.version = RerunTask::VERSION
8
+ s.authors = ["lukasvotypka"]
9
+ s.email = ["lukas.votypka@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Re-run task if is not finished}
12
+ s.description = %q{This gem is developed for handling rake task and re-run them if didn't finished successfully}
13
+
14
+ s.rubyforge_project = "rerun_task"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "test-unit"
22
+ s.add_development_dependency "mocha"
23
+ end
@@ -0,0 +1,70 @@
1
+ require 'test/unit'
2
+ require "mocha/setup"
3
+ require 'rerun_task'
4
+
5
+ class WatchProcessTest < Test::Unit::TestCase
6
+
7
+ # Called before every test method runs. Can be used
8
+ # to set up fixture information.
9
+ def setup
10
+ @process_file = RerunTask::ProcessFile.new("#{RerunTask::CONFIG['pid_dir']}/rerun_task/pids")
11
+ begin
12
+ FileUtils.rm(@process_file.path)
13
+ rescue
14
+ end
15
+ end
16
+
17
+ # Called after every test method runs. Can be used to tear
18
+ # down fixture information.
19
+
20
+ def teardown
21
+ # Do nothing
22
+ end
23
+
24
+ def test_should_start
25
+ #assert_equal("/tmp/rerun_task/pids/watch_process_test.rb.pid", @process_file.path)
26
+ @w = RerunTask::WatchProcess.new("my_test")
27
+ assert_equal(false, File.exists?(@process_file.path))
28
+ @w.start
29
+ assert_equal(true, File.exists?(@process_file.path))
30
+ @w.finished
31
+ assert_equal(false, File.exists?(@process_file.path))
32
+
33
+ @w = RerunTask::WatchProcess.new("my_test")
34
+ @w.start
35
+ @w2 = RerunTask::WatchProcess.new("my_test")
36
+ assert_raise_kind_of(RuntimeError) do
37
+ @w2.start
38
+ end
39
+ @w.finished
40
+ end
41
+
42
+ def test_list_pids
43
+ path = "#{RerunTask::CONFIG['pid_dir']}/rerun_task/pids"
44
+ filename = "#{path}/test_example_task.rb.pid"
45
+ FileUtils.rm(filename) if File.exists?(filename)
46
+ File.open(filename, 'w') do |f|
47
+ f.write("1234\ntest_example_task.rb")
48
+ end
49
+
50
+ unfinished = RerunTask::Pids.unfinished
51
+ assert_equal(1, unfinished.size)
52
+ assert_equal('test_example_task.rb', unfinished.first.process_name)
53
+ end
54
+
55
+ def test_run_from_crontab
56
+ path = "#{RerunTask::CONFIG['pid_dir']}/rerun_task/pids"
57
+ filename = "#{path}/test_example_task.rb.pid"
58
+ FileUtils.rm(filename) if File.exists?(filename)
59
+ File.open(filename, 'w') do |f|
60
+ f.write("1234\ntest_example_task.rb")
61
+ end
62
+
63
+ crontab = RerunTask::Crontab.new()
64
+ crontab.content = ["0 0 1,5,9,13,17,21,25,29 * * ruby test_example_task.rb"]
65
+ res = crontab.find_task('test_example_task.rb')
66
+ assert_equal("ruby test_example_task.rb", res)
67
+
68
+ RerunTask::UnfinishedRunner.crontab_retry()
69
+ end
70
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rerun_task
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - lukasvotypka
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2013-12-23 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: test-unit
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :development
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: mocha
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :development
36
+ version_requirements: *id002
37
+ description: This gem is developed for handling rake task and re-run them if didn't finished successfully
38
+ email:
39
+ - lukas.votypka@gmail.com
40
+ executables:
41
+ - rerun_task_crontab.rb
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - .gitignore
48
+ - Gemfile
49
+ - README.md
50
+ - Rakefile
51
+ - bin/rerun_task_crontab.rb
52
+ - config/rerun_task.yml
53
+ - lib/rerun_task.rb
54
+ - lib/rerun_task/config.rb
55
+ - lib/rerun_task/crontab.rb
56
+ - lib/rerun_task/pids.rb
57
+ - lib/rerun_task/process_file.rb
58
+ - lib/rerun_task/unfinished_runner.rb
59
+ - lib/rerun_task/version.rb
60
+ - lib/rerun_task/watch_process.rb
61
+ - rerun_task.gemspec
62
+ - test/watch_process_test.rb
63
+ homepage: ""
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options: []
68
+
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ requirements: []
84
+
85
+ rubyforge_project: rerun_task
86
+ rubygems_version: 1.8.24
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Re-run task if is not finished
90
+ test_files:
91
+ - test/watch_process_test.rb
92
+ has_rdoc: