task_manager 0.0.2 → 0.0.4

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/.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
+