task_manager 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc CHANGED
@@ -1,2 +1,2 @@
1
- rvm use ruby-1.8.7-p334
1
+ rvm use ruby-1.8.7-p352
2
2
  rvm gemset use 'task_manager'
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ bundler_args: --without maintenance
3
+ rvm:
4
+ - 1.8.7
5
+ - jruby-18mode
6
+ - ree
data/Gemfile CHANGED
@@ -2,6 +2,9 @@ source "http://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- group :development do
5
+ group :maintenance do
6
6
  gem 'gem-release'
7
+ gem 'watchr'
8
+ # gem 'ruby-fsevent'
9
+ gem 'ruby-debug'
7
10
  end
data/Rakefile CHANGED
@@ -1,2 +1,11 @@
1
- require 'bundler'
2
- Bundler::GemHelper.install_tasks
1
+ # require 'bundler'
2
+ # Bundler::GemHelper.install_tasks
3
+
4
+ task :test do
5
+ $:.push(File.expand_path('../lib/', __FILE__))
6
+ $:.push(File.expand_path('../test/', __FILE__))
7
+
8
+ require './test/all'
9
+ end
10
+
11
+ task :default => :test
data/TODO CHANGED
@@ -1,4 +1,2 @@
1
1
  add a generator for rails
2
- add better test-coverage
3
- add basic documentation
4
- add examples
2
+ add example to README
data/bin/task_manager.rb CHANGED
@@ -1,77 +1,19 @@
1
1
  #!/usr/bin/env ruby
2
2
  # vim:ft=ruby:fileencoding=utf8
3
3
 
4
- # read environment variables or use default values
5
- # RAILS_ENV=${RAILS_ENV:-"staging"}
6
- # RUBY_BIN=${RUBY_BIN:-"ruby"}
7
- # BASEPATH=${BASEPATH:-"/home/application/projects/rails/$RAILS_ENV/current"}
8
- rails_env = Rails.env
9
- ruby_bin = 'ruby'
10
- base_path = Rails.root
4
+ require 'daemons'
5
+ require 'pathname'
11
6
 
7
+ base_path = Pathname.new('.').expand_path
12
8
 
13
- # variables that should only be changed if you REALLY know what you're doing
14
- # e.g. the log-filename is hardcoded in the scheduling-script
15
- # LOG="$BASEPATH/log/$RAILS_ENV.scheduler.log"
16
- # SCHEDULER_FILENAME='tasks.rb'
17
- # SCHEDULER="$BASEPATH/config/$SCHEDULER_FILENAME"
18
- log = base_path.join('log').join("#{rails_env}.scheduler.log")
19
- scheduler_fn = 'tasks.rb'
20
- scheduler = basepath.join('config').join(scheduler_fn)
9
+ Daemons.run(base_path.join('config/scheduler.rb'), {
10
+ :app_name => "#{ENV['RAILS_ENV']}.scheduler",
11
+ :dir_mode => :normal,
12
+ :dir => base_path.join('tmp/pids'),
13
+ :mutliple => false,
14
+ :monitor => true,
15
+ :log_dir => base_path.join('log'),
16
+ :log_output => true,
17
+ :keep_pid_files => false
18
+ })
21
19
 
22
- # PID=`ps aux | grep -v 'grep' | egrep "$RAILS_ENV.*$SCHEDULER_FILENAME" | head -n1 | sed 's/^!gw*\W\+\(\w\+\).*$/\1/'`
23
- pid = `ps aux | grep -v 'grep' | egrep "$RAILS_ENV.*$SCHEDULER_FILENAME" | head -n1 | sed 's/^\w*\W\+\(\w\+\).*$/\1/'`
24
-
25
- # # start scheduler in the background
26
- # function start_scheduler() {
27
- # if [ -z "$PID" ]; then
28
- # $RUBY_BIN $SCHEDULER >>$LOG 2>&1 &
29
- # disown -a -h
30
- # fi
31
- # }
32
- #
33
- # # kill the scheduler if it's running
34
- # function kill_scheduler() {
35
- # if [ -n "$PID" ]; then
36
- # kill $PID
37
- # fi;
38
- # }
39
- #
40
- # # actual "init.d"-like interface
41
- # case "$1" in
42
- # start)
43
- # start_scheduler
44
- # ;;
45
- # stop)
46
- # kill_scheduler
47
- # ;;
48
- # restart)
49
- # kill_scheduler
50
- # start_scheduler
51
- # ;;
52
- # status)
53
- # if [ -n "$PID" ]; then
54
- # echo "Scheduling is active ($PID)"
55
- # else
56
- # echo "Scheduling is inactive"
57
- # fi
58
- # ;;
59
- # pid)
60
- # echo $PID
61
- # ;;
62
- # *)
63
- # echo "Usage: $0 {start|stop|restart|status|pid}"
64
- # echo ""
65
- # echo "recognized environment variables with default in parentheses:"
66
- # echo ""
67
- # echo " variables which should be given"
68
- # echo " BASEPATH ($BASEPATH)"
69
- # echo " RAILS_ENV ($RAILS_ENV)"
70
- # echo ""
71
- # echo " variables which can be given for optimization reasons"
72
- # echo " RUBY_BIN ($RUBY_BIN)"
73
- # ;;
74
- # esac
75
- #
76
- # # for the lack of a better return value, exit successfully
77
- # exit 0
@@ -1,7 +1,7 @@
1
1
  # vim:ft=ruby:fileencoding=utf-8
2
2
 
3
- module TaskManager
4
- VERSION = "0.0.2"
3
+ class TaskManager
4
+ VERSION = "0.0.4"
5
5
  DATE = File.mtime(__FILE__)
6
6
  SUMMARY = 'A simple wrapper around the Rufus::Scheduler to have a more configurable setup.'
7
7
  DESCRIPTION = <<-EOT
data/lib/task_manager.rb CHANGED
@@ -1,17 +1,25 @@
1
+ # vim:fileencoding=utf8
2
+
1
3
  # needs rufus-scheduler
2
4
  require 'rufus/scheduler'
3
5
  require 'pathname'
4
6
 
5
7
  class TaskManager
6
8
  attr_accessor :jobs
7
- attr_reader :env, :path
9
+ attr_reader :env, :path, :config
8
10
 
9
- # create the necessary scheduler/job-storages and store a basepath and a environment
11
+ # create the necessary scheduler/job-stores and store a basepath and a
12
+ # environment
13
+ #
14
+ # STDOUT is set to sync=true so that the log is not held back by some
15
+ # output-buffering
10
16
  def initialize(env = 'staging', path = '.')
11
17
  @path = Pathname.new(path)
12
18
  @env = env.to_sym
13
19
  @jobs = {}
14
20
  @schedulers = {}
21
+
22
+ $stdout.sync = true
15
23
  end
16
24
 
17
25
  # return a named scheduler
@@ -19,9 +27,20 @@ class TaskManager
19
27
  @schedulers[key] ||= Rufus::Scheduler.start_new
20
28
  end
21
29
 
30
+ # create a new job with a separate scheduler
31
+ def schedule(key)
32
+ raise ArgumentError unless block_given?
33
+ jobs[key] = yield scheduler(key)
34
+ end
35
+
36
+ # check wether a job is scheduled
37
+ def scheduled?(key)
38
+ !jobs[key].nil?
39
+ end
40
+
22
41
  # prevent RubyVM from quitting
23
42
  def persist
24
- say "Scheduler wird persistiert, alle Definitionen sollten geladen sein."
43
+ say "Scheduler will be persisted now, all definitions should be loaded now."
25
44
  scheduler(:internal).join
26
45
  end
27
46
 
@@ -36,15 +55,40 @@ class TaskManager
36
55
  def execute_task(cmd_string)
37
56
  shortened_cmd = cmd_string.gsub(/--trace/, '').strip
38
57
  say "starting #{shortened_cmd}"
39
- if system("cd #{path}; RAILS_ENV=#{env} #{cmd_string} >>#{path}/log/#{env}.scheduler.task_output.log 2>>#{path}/log/#{env}.scheduler.log")
58
+ if system(full_command_string(cmd_string))
40
59
  say "finished #{shortened_cmd}"
41
60
  else
42
61
  say "ERROR in #{shortened_cmd}"
43
62
  end
44
63
  end
45
64
 
65
+ # overwritable command_string which will be executed in the system
66
+ def full_command_string(cmd_string)
67
+ "cd #{path}; RAILS_ENV=#{env} #{cmd_string} >>#{path}/log/#{env}.scheduler.task_output.log 2>>#{path}/log/#{env}.scheduler.log"
68
+ end
69
+
46
70
  # output a message with Time
47
71
  def say(msg)
48
- puts "#{Time.now} - #{msg}"
72
+ $stdout.puts "#{Time.now} - #{msg}"
73
+ end
74
+
75
+ # store configuration from a hash
76
+ def config= hash
77
+ @config = {}
78
+
79
+ hash.keys.map do |key|
80
+ @config[key.to_sym] = hash[key].map do |r|
81
+ r.values.first
82
+ end
83
+ end
84
+
85
+ config
86
+ end
87
+
88
+ # apply configuration
89
+ def apply_configuration
90
+ config.each do |method, args|
91
+ send(method, *args)
92
+ end
49
93
  end
50
94
  end
data/task_manager.gemspec CHANGED
@@ -25,7 +25,10 @@ Gem::Specification.new do |s|
25
25
  # s.post_install_message = TaskManager::RELEASE_NOTES
26
26
 
27
27
  s.add_dependency 'rufus-scheduler', '~> 2.0.6'
28
+ s.add_dependency 'daemons', '~> 1.1.3'
28
29
 
29
30
  # for tests, needed
31
+ s.add_development_dependency 'rake'
30
32
  s.add_development_dependency 'more_unit_test'
33
+ s.add_development_dependency 'mocha'
31
34
  end
@@ -0,0 +1,12 @@
1
+ cnet_import:
2
+ - cron: '30 0 * * *'
3
+ - confirm: false
4
+ navision_import:
5
+ - every: '3h'
6
+ - stop_hour: 18
7
+ - stop_minute: 0
8
+ restart_jobs:
9
+ - cron: '* 6 * * *'
10
+ - restart:
11
+ - navision_import
12
+
@@ -1,10 +1,11 @@
1
- require File.expand_path('../test_helper', __FILE__)
1
+ require 'test_helper'
2
2
 
3
3
  class TaskManagerTest < Test::Unit::TestCase
4
4
  # remember to clean up after each test-run
5
5
  def teardown
6
6
  # @sut.unschedule(:internal)
7
7
  @sut = nil
8
+ @custom_tm = nil
8
9
  end
9
10
 
10
11
  # lets start by trying to create a taskmanager
@@ -35,7 +36,164 @@ class TaskManagerTest < Test::Unit::TestCase
35
36
 
36
37
  def test_taskmanager_can_output_messages
37
38
  assert_stdout_block MatchableString.new('testing') do
38
- TaskManager.new.say('testing')
39
+ tm.say('testing')
39
40
  end
40
41
  end
42
+
43
+ # we will be configuring the taskmanager with a hash, so lets define one
44
+ # this configuration would expect the necessary methods on a subclass of the TaskManager
45
+ def configuration
46
+ {
47
+ "restart_jobs"=>[
48
+ {"cron"=>"* 6 * * *"},
49
+ {"restart"=>["navision_import"]}
50
+ ],
51
+ "navision_import"=>[
52
+ {"every"=>"3h"},
53
+ {"stop_hour"=>18},
54
+ {"stop_minute"=>0}
55
+ ],
56
+ "cnet_import"=>[
57
+ {"cron"=>"30 0 * * *"},
58
+ {"confirm"=>false}
59
+ ]
60
+ }
61
+ end
62
+
63
+ def test_taskmanager_can_be_configured_with_hash
64
+ assert_respond_to tm, :'config='
65
+ assert_respond_to tm, :config
66
+
67
+ tm.config = configuration
68
+
69
+ expected = {
70
+ :restart_jobs=>["* 6 * * *", ["navision_import"]],
71
+ :navision_import=>["3h", 18, 0],
72
+ :cnet_import=>["30 0 * * *", false]
73
+ }
74
+
75
+ assert_equal expected, tm.config
76
+ end
77
+
78
+ def test_taskmanager_can_apply_the_configration
79
+ tm.expects(:restart_jobs).with('* 6 * * *', ["navision_import"])
80
+ tm.expects(:navision_import).with('3h', 18, 0)
81
+ tm.expects(:cnet_import).with('30 0 * * *', false)
82
+
83
+ tm.config = configuration
84
+
85
+ assert_respond_to tm, :apply_configuration
86
+
87
+ tm.apply_configuration
88
+ end
89
+
90
+ # lets create a TaskManager so we can test a little more
91
+ class CustomTaskManager < TaskManager
92
+ def navision_import(frequency, end_hr, end_min = 0)
93
+ schedule(:navision_import) do |scheduler|
94
+ scheduler.every(frequency, :blocking => true) do
95
+ (Time.now.hour >= end_hr && Time.now.min >= end_min) ?
96
+ unschedule(:navision_import) :
97
+ execute_task('echo "importing from navision"')
98
+ end
99
+ end
100
+ end
101
+
102
+ def cnet_import(cron_def, param)
103
+ schedule(:cnet_import) do |scheduler|
104
+ scheduler.cron(cron_def) do
105
+ arg = param ? "production" : "test"
106
+ execute_task(%(echo "importing from cnet server #{arg}" ))
107
+ end
108
+ end
109
+ end
110
+
111
+ def restart_jobs(cron_def, tasks)
112
+ schedule(:restart_jobs) do |scheduler|
113
+ scheduler.cron(cron_def) do
114
+ tasks.each do |task|
115
+ send(task, *config[task]) unless scheduled?(task)
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ # verify that the building blocks are there
123
+ def test_taskmanager_has_a_schedule_method
124
+ assert_respond_to tm, :schedule
125
+ assert_equal 1, tm.method(:schedule).arity
126
+
127
+ assert_raise ArgumentError do
128
+ tm.schedule(:blah)
129
+ end
130
+
131
+ assert_nothing_raised do
132
+ tm.schedule(:blah) do |scheduler|
133
+ # the scheduler should be returned again
134
+ scheduler
135
+ end
136
+ end
137
+ end
138
+
139
+ def test_schedule_method_stores_the_job
140
+ prev_size = tm.jobs.size
141
+
142
+ tm.schedule(:blah) do |scheduler|
143
+ # the scheduler should be returned again
144
+ scheduler
145
+ end
146
+
147
+ assert_equal (prev_size + 1), tm.jobs.size
148
+ assert_not_nil tm.jobs[:blah], tm.jobs.inspect
149
+ end
150
+
151
+ def test_taskmanager_knows_what_is_scheduled
152
+ assert_respond_to tm, :'scheduled?'
153
+ assert !tm.scheduled?(:undefined)
154
+
155
+ tm.schedule(:defined) do |s|
156
+ s
157
+ end
158
+
159
+ assert tm.scheduled?(:defined)
160
+ end
161
+
162
+ # as we know that we have everyhing we need in the CustomTaskManager, lets test this one
163
+ def custom_tm
164
+ @custom_tm ||= CustomTaskManager.new
165
+ end
166
+
167
+ def test_custom_taskmanager_can_take_configuration
168
+ assert_nothing_raised Exception do
169
+ custom_tm.config = configuration
170
+ custom_tm.apply_configuration
171
+ assert_equal 3, custom_tm.jobs.size
172
+ end
173
+ end
174
+
175
+ # on more thing we can tweak from our subclass is the actual command we execute
176
+ def test_taskmanager_calls_method_to_construct_system_call
177
+ cmd = %(echo "importing from navision")
178
+ # I deliberatly redirect the result to /dev/null here because I don't test
179
+ # that the command is right it should just be executed. The next test shows
180
+ # what the full command string really looks like.
181
+ full_cmd = %(cd .; RAILS_ENV=staging echo "importing from navision" > /dev/null)
182
+
183
+ custom_tm.expects(:full_command_string).with(cmd).returns(full_cmd)
184
+
185
+ assert_stdout_block MatchableString.new(cmd) do
186
+ custom_tm.execute_task(cmd)
187
+ end
188
+ end
189
+
190
+ # somewhat more in depth, it works like this
191
+ def test_taskmanager_can_construct_a_full_command_string
192
+ assert_respond_to tm, :full_command_string
193
+ assert_equal 1, tm.method(:full_command_string).arity
194
+
195
+ expected = %(cd .; RAILS_ENV=staging echo "test" >>./log/staging.scheduler.task_output.log 2>>./log/staging.scheduler.log)
196
+
197
+ assert_equal expected, tm.full_command_string('echo "test"')
198
+ end
41
199
  end
data/test/test_helper.rb CHANGED
@@ -2,7 +2,20 @@ require 'rubygems'
2
2
 
3
3
  require 'more_unit_test/assert_stdout'
4
4
  require 'test/unit'
5
+ require 'mocha'
5
6
 
6
- $:.push(File.expand_path('../../lib/', __FILE__))
7
+ class Test::Unit::Catch_IO
8
+ def sync=(value)
9
+ value
10
+ end
11
+
12
+ def puts(string)
13
+ write("#{string}\n")
14
+ end
15
+
16
+ def print(string)
17
+ write(string)
18
+ end
19
+ end
7
20
 
8
21
  require 'task_manager'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: task_manager
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease: false
4
+ hash: 23
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 4
10
+ version: 0.0.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - Mattthias Viehweger
@@ -15,8 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-24 00:00:00 +02:00
19
- default_executable:
18
+ date: 2012-03-21 00:00:00 Z
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
21
  name: rufus-scheduler
@@ -35,9 +34,25 @@ dependencies:
35
34
  type: :runtime
36
35
  version_requirements: *id001
37
36
  - !ruby/object:Gem::Dependency
38
- name: more_unit_test
37
+ name: daemons
39
38
  prerelease: false
40
39
  requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 21
45
+ segments:
46
+ - 1
47
+ - 1
48
+ - 3
49
+ version: 1.1.3
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: rake
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
41
56
  none: false
42
57
  requirements:
43
58
  - - ">="
@@ -47,7 +62,35 @@ dependencies:
47
62
  - 0
48
63
  version: "0"
49
64
  type: :development
50
- version_requirements: *id002
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: more_unit_test
68
+ prerelease: false
69
+ requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ type: :development
79
+ version_requirements: *id004
80
+ - !ruby/object:Gem::Dependency
81
+ name: mocha
82
+ prerelease: false
83
+ requirement: &id005 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ type: :development
93
+ version_requirements: *id005
51
94
  description: " A simple wrapper around the Rufus::Scheduler to have a more configurable setup.\n\n The Task to be scheduled should be defined in a subclass.\n"
52
95
  email:
53
96
  - kronn@kronn.de
@@ -60,6 +103,7 @@ extra_rdoc_files: []
60
103
 
61
104
  files:
62
105
  - .rvmrc
106
+ - .travis.yml
63
107
  - Gemfile
64
108
  - README
65
109
  - Rakefile
@@ -71,9 +115,9 @@ files:
71
115
  - lib/task_manager/version.rb
72
116
  - task_manager.gemspec
73
117
  - test/all.rb
118
+ - test/fixtures/config.yml
74
119
  - test/task_manager_test.rb
75
120
  - test/test_helper.rb
76
- has_rdoc: true
77
121
  homepage: http://github.com/kronn/task_manager
78
122
  licenses: []
79
123
 
@@ -103,11 +147,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
147
  requirements: []
104
148
 
105
149
  rubyforge_project: task_manager
106
- rubygems_version: 1.3.7
150
+ rubygems_version: 1.8.19
107
151
  signing_key:
108
152
  specification_version: 3
109
153
  summary: A simple wrapper around the Rufus::Scheduler to have a more configurable setup.
110
- test_files:
111
- - test/all.rb
112
- - test/task_manager_test.rb
113
- - test/test_helper.rb
154
+ test_files: []
155
+