rcron 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,14 @@
1
+ 0.1.2 / 2012/07/12
2
+ ------------------
3
+ * Added support for hyphen+slash syntax
4
+ * e.g. `2-20/5,45-10/8 * * * *`
5
+ * Uses `Logger` for logging
6
+
7
+ 0.1.1 / 2011/09/06
8
+ ------------------
9
+ * RCron#enq and RCron::Task#deq as aliases of q and dq
10
+
11
+ 0.1.0 / 2011/08/31
12
+ ------------------
13
+ * Initial release
14
+
data/Gemfile CHANGED
@@ -1,14 +1,4 @@
1
- source "http://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
1
+ source 'https://rubygems.org'
5
2
 
6
- # Add dependencies to develop your gem here.
7
- # Include everything needed to run rake, tests, features, etc.
8
- group :development do
9
- gem "yard", "~> 0.6.0"
10
- gem "bundler", "~> 1.0.0"
11
- gem "jeweler", "~> 1.6.4"
12
- gem "rcov", ">= 0"
13
- gem "simplecov"
14
- end
3
+ # Specify your gem's dependencies in rcron.gemspec
4
+ gemspec
@@ -1,4 +1,6 @@
1
- Copyright (c) 2011 Junegunn Choi
1
+ Copyright (c) 2012 Junegunn Choi
2
+
3
+ MIT License
2
4
 
3
5
  Permission is hereby granted, free of charge, to any person obtaining
4
6
  a copy of this software and associated documentation files (the
@@ -17,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
19
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
20
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
21
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -3,9 +3,18 @@
3
3
  A simple cron-like scheduler for Ruby.
4
4
 
5
5
  ## Installation
6
- ```ruby
7
- gem install rcron
8
- ```
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rcron'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rcron
9
18
 
10
19
  ## Cron format
11
20
  As of now, most of the expressions except for ? and W are supported.
@@ -59,23 +68,21 @@ rcron.enq('Every ten-minutes during summer',
59
68
  end
60
69
 
61
70
  # log to $stderr instead of default $stdout
62
- rcron.start $stderr
71
+ rcron.start Logger.new($stderr)
63
72
  ```
64
73
 
65
74
  ## Notes
66
75
  - Minimum interval for each task is one-minute just like cron. So rcron usually sleeps most of the time and wakes up only once a minute. (Except when short timeouts for the tasks are specified. In that case, rcron wakes up more frequently to check whether the task should be terminated)
67
76
  - rcron checks to start tasks at the very first second of every minute. e.g. When you first start it at 12:00:45, it will sleep 15 seconds before doing anything.
68
- - Tested on Ruby 1.8.7, Ruby 1.9.2 and JRuby 1.6.4
69
- - 99.67% test coverage. (a false sense of security, though)
70
-
71
- ## Contributing to rcron
72
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
73
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
74
- * Fork the project
75
- * Start a feature/bugfix branch
76
- * Commit and push until you are happy with your contribution
77
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
78
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
77
+ - Tested on Ruby 1.8.7, Ruby 1.9.3 and JRuby 1.6.7.2
78
+
79
+ ## Contributing
80
+
81
+ 1. Fork it
82
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
83
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
84
+ 4. Push to the branch (`git push origin my-new-feature`)
85
+ 5. Create new Pull Request
79
86
 
80
87
  ## Copyright
81
88
 
data/Rakefile CHANGED
@@ -1,29 +1,5 @@
1
- # encoding: utf-8
2
-
3
- require 'rubygems'
4
- require 'bundler'
5
- begin
6
- Bundler.setup(:default, :development)
7
- rescue Bundler::BundlerError => e
8
- $stderr.puts e.message
9
- $stderr.puts "Run `bundle install` to install missing gems"
10
- exit e.status_code
11
- end
12
- require 'rake'
13
-
14
- require 'jeweler'
15
- Jeweler::Tasks.new do |gem|
16
- # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
- gem.name = "rcron"
18
- gem.homepage = "http://github.com/junegunn/rcron"
19
- gem.license = "MIT"
20
- gem.summary = %Q{A simple cron-like scheduler}
21
- gem.description = %Q{A simple cron-like scheduler for Ruby}
22
- gem.email = "junegunn.c@gmail.com"
23
- gem.authors = ["Junegunn Choi"]
24
- # dependencies defined in Gemfile
25
- end
26
- Jeweler::RubygemsDotOrgTasks.new
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
27
3
 
28
4
  require 'rake/testtask'
29
5
  Rake::TestTask.new(:test) do |test|
@@ -31,16 +7,3 @@ Rake::TestTask.new(:test) do |test|
31
7
  test.pattern = 'test/**/test_*.rb'
32
8
  test.verbose = true
33
9
  end
34
-
35
- require 'rcov/rcovtask'
36
- Rcov::RcovTask.new do |test|
37
- test.libs << 'test'
38
- test.pattern = 'test/**/test_*.rb'
39
- test.verbose = true
40
- test.rcov_opts << '--exclude "gems/*"'
41
- end
42
-
43
- task :default => :test
44
-
45
- require 'yard'
46
- YARD::Rake::YardocTask.new
@@ -1,3 +1,4 @@
1
+ require 'rcron/version'
1
2
  require 'rcron/task'
2
3
  require 'rcron/alarm'
3
4
  require 'rcron/parser'
@@ -9,7 +9,7 @@ class RCron
9
9
  parser = lambda { |type, min, len, element, subs, extra|
10
10
  return nil if element.nil?
11
11
 
12
- max = min + len
12
+ max = min + len - 1
13
13
 
14
14
  (subs || {}).each do |k, v|
15
15
  element = element.gsub(/\b#{k}\b/i, v.to_s)
@@ -25,7 +25,22 @@ class RCron
25
25
  raise err if ei < min || ei > max
26
26
  ei
27
27
  when %r|^\*/([1-9][0-9]*)$|
28
- (min...max).select { |m| m % $1.to_i == 0 }
28
+ (min..max).select { |m| m % $1.to_i == 0 }
29
+ when %r|^([0-9]+)-([0-9]+)/([1-9][0-9]*)$|
30
+ f, t = $1.to_i, $2.to_i
31
+ raise err if f < min || f > max
32
+ raise err if t < min || t > max
33
+
34
+ if f < t
35
+ (f..t).select { |m| (m - f) % $3.to_i == 0 }
36
+ else
37
+ (f..max).select { |m| (m - f) % $3.to_i == 0 } +
38
+ (min..t).select { |m|
39
+ m = m + max + 1 - min
40
+ (m - f) % $3.to_i == 0
41
+ }
42
+ end
43
+
29
44
  when %r|^([0-9]+)-([0-9]+)$|
30
45
  f, t = $1.to_i, $2.to_i
31
46
 
@@ -35,7 +50,7 @@ class RCron
35
50
  if f < t
36
51
  (f..t).to_a
37
52
  else
38
- (f...max).to_a + (min..t).to_a
53
+ (f..max).to_a + (min..t).to_a
39
54
  end
40
55
  else
41
56
  extra && extra.call(e) || raise(err)
@@ -1,12 +1,16 @@
1
1
  require 'thread'
2
+ require 'logger'
3
+ require 'forwardable'
2
4
 
3
5
  class RCron
6
+ extend Forwardable
7
+
8
+ def_delegators :@logger, :info, :warn, :error
9
+
4
10
  def initialize
5
- @tasks = []
6
- @mutex = Mutex.new
11
+ @tasks = []
12
+ @mutex = Mutex.new
7
13
  @sleeping = false
8
- @log_mutex = Mutex.new
9
- @log_ostream = $stdout
10
14
  end
11
15
 
12
16
  # Enqueues a task to be run
@@ -29,16 +33,16 @@ class RCron
29
33
  alias q enq
30
34
 
31
35
  # Starts the scheduler
32
- # @param log_output_stream Stream to output scheduler log. Should implement puts method.
33
- def start log_output_stream = $stdout
34
- raise ArgumentError.new(
35
- "Log output stream should implement puts method") unless
36
- log_output_stream.respond_to? :puts
36
+ # @param logger Logger instance. Default is a Logger to standard output.
37
+ def start logger = Logger.new($stdout)
38
+ unless [:info, :warn, :error].all? { |m| logger.respond_to? m }
39
+ raise ArgumentError.new("Invalid Logger")
40
+ end
37
41
 
38
- @log_ostream = log_output_stream
42
+ @logger = logger
39
43
  @thread = Thread.current
40
44
 
41
- log "rcron started"
45
+ info "rcron started"
42
46
 
43
47
  now = Time.now
44
48
  while @tasks.length > 0
@@ -68,15 +72,15 @@ class RCron
68
72
  now = Time.now
69
73
  @tasks.select { |e| e.queued? && e.scheduled?(now) }.each do |t|
70
74
  if t.running? && t.exclusive?
71
- log "[#{t.name}] already running exclusively"
75
+ warn "[#{t.name}] already running exclusively"
72
76
  next
73
77
  end
74
78
 
75
- log "[#{t.name}] started"
79
+ info "[#{t.name}] started"
76
80
  t.send :start, now
77
81
  end if now >= next_tick
78
82
  end#while
79
- log "rcron completed"
83
+ info "rcron completed"
80
84
  end#start
81
85
 
82
86
  # Crontab-like tasklist
@@ -94,10 +98,4 @@ private
94
98
  end
95
99
  }
96
100
  end
97
-
98
- def log msg
99
- @log_mutex.synchronize do
100
- @log_ostream.puts "[#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}] #{msg}"
101
- end
102
- end
103
101
  end#RCron
@@ -141,11 +141,11 @@ class RCron
141
141
  task.run
142
142
  @ended_at = Time.now
143
143
 
144
- task.rcron.send :log, "[#{task.name}] completed (#{'%.2f' % elapsed}s)"
144
+ task.rcron.send :info, "[#{task.name}] completed (#{'%.2f' % elapsed}s)"
145
145
  rescue Exception => e
146
146
  @ended_at = Time.now
147
147
 
148
- task.rcron.send :log, "[#{task.name}] terminated: #{[e, e.backtrace].join($/)}"
148
+ task.rcron.send :error, "[#{task.name}] terminated: #{[e, e.backtrace].join($/)}"
149
149
  # Ignore exception?
150
150
  end
151
151
  task.rcron.send :wake_up
@@ -0,0 +1,3 @@
1
+ class RCron
2
+ VERSION = "0.1.2"
3
+ end
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/rcron/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Junegunn Choi"]
6
+ gem.email = ["junegunn.c@gmail.com"]
7
+ gem.description = %q{A simple cron-like scheduler}
8
+ gem.summary = %q{A simple cron-like scheduler for Ruby}
9
+ gem.homepage = "https://github.com/junegunn/rcron"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "rcron"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = RCron::VERSION
17
+ gem.add_development_dependency "simplecov"
18
+ end
@@ -1,17 +1,29 @@
1
- $LOAD_PATH << "."
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
2
  require 'helper'
3
3
 
4
4
  class TestRcron < Test::Unit::TestCase
5
- class LogStream
5
+ class FakeLogger
6
6
  def initialize
7
7
  @lines = []
8
8
  end
9
9
 
10
- def puts str
11
- $stdout.puts str
10
+ def log header, str
11
+ $stdout.puts header + ' ' + str
12
12
  @lines << str
13
13
  end
14
14
 
15
+ def info msg
16
+ log '[I]', msg
17
+ end
18
+
19
+ def warn msg
20
+ log '[W]', msg
21
+ end
22
+
23
+ def error msg
24
+ log '[E]', msg
25
+ end
26
+
15
27
  def count pat
16
28
  @lines.select { |e| e =~ pat }.count
17
29
  end
@@ -19,10 +31,10 @@ class TestRcron < Test::Unit::TestCase
19
31
 
20
32
  def test_empty_q
21
33
  rcron = RCron.new
22
- log = LogStream.new
23
- rcron.start(log)
34
+ logger = FakeLogger.new
35
+ rcron.start(logger)
24
36
 
25
- assert_equal 1, log.count(/completed/)
37
+ assert_equal 1, logger.count(/completed/)
26
38
  end
27
39
 
28
40
  def test_blockless
@@ -108,7 +120,7 @@ class TestRcron < Test::Unit::TestCase
108
120
  def test_non_exclusive
109
121
  puts 'non exclusive'
110
122
  counter = 0
111
- log = LogStream.new
123
+ log = FakeLogger.new
112
124
  rcron = RCron.new
113
125
  truth = true
114
126
  rcron.q('non-exclusive', '* * * * *') do |task|
@@ -127,7 +139,7 @@ class TestRcron < Test::Unit::TestCase
127
139
  def test_exclusive
128
140
  puts 'exclusive'
129
141
  counter = 0
130
- log = LogStream.new
142
+ log = FakeLogger.new
131
143
  rcron = RCron.new
132
144
  rcron.q('exclusive', '* * * * *', :exclusive => true) do |task|
133
145
  counter += 1
@@ -161,7 +173,7 @@ class TestRcron < Test::Unit::TestCase
161
173
  end
162
174
 
163
175
  def test_exception
164
- log = LogStream.new
176
+ log = FakeLogger.new
165
177
  rcron = RCron.new
166
178
  rcron.q('Exceptional', '* * * * *') do |task|
167
179
  task.dq
@@ -1,4 +1,4 @@
1
- $LOAD_PATH << "."
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
2
  require 'helper'
3
3
 
4
4
  class TestRcronParser < Test::Unit::TestCase
@@ -57,6 +57,19 @@ class TestRcronParser < Test::Unit::TestCase
57
57
  RCron::Parser.parse('*/23,*/24 * * * *')[:minutes])
58
58
  end
59
59
 
60
+ def test_dividend_with_offset
61
+ assert_equal({2 => true, 7 => true, 12 => true, 17 => true},
62
+ RCron::Parser.parse('2-20/5 * * * *')[:minutes])
63
+ assert_equal({2 => true, 7 => true, 12 => true, 17 => true, 45 => true, 53 => true},
64
+ RCron::Parser.parse('2-20/5,45-59/8 * * * *')[:minutes])
65
+ assert_equal({2 => true, 7 => true, 12 => true, 17 => true, 45 => true, 53 => true, 1 => true, 9 => true},
66
+ RCron::Parser.parse('2-20/5,45-10/8 * * * *')[:minutes])
67
+ assert_equal({4 => true, 7 => true, 10 => true},
68
+ RCron::Parser.parse('* * * apr-oct/3 *')[:months])
69
+ assert_equal({10 => true, 1 => true, 4 => true},
70
+ RCron::Parser.parse('* * * oct-jun/3 *')[:months])
71
+ end
72
+
60
73
  def test_months
61
74
  assert_equal({1 => true, 2 => true, 3 => true, 6 => true, 7 => true, 8 => true},
62
75
  RCron::Parser.parse('* * * jan-MAR,Jun-Aug *')[:months])
@@ -1,4 +1,4 @@
1
- $LOAD_PATH << "."
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
2
  require 'helper'
3
3
 
4
4
  class TestRcronTask < Test::Unit::TestCase
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rcron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,44 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-06 00:00:00.000000000Z
12
+ date: 2012-07-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: yard
16
- requirement: &2153035480 !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ~>
20
- - !ruby/object:Gem::Version
21
- version: 0.6.0
22
- type: :development
23
- prerelease: false
24
- version_requirements: *2153035480
25
- - !ruby/object:Gem::Dependency
26
- name: bundler
27
- requirement: &2153034680 !ruby/object:Gem::Requirement
28
- none: false
29
- requirements:
30
- - - ~>
31
- - !ruby/object:Gem::Version
32
- version: 1.0.0
33
- type: :development
34
- prerelease: false
35
- version_requirements: *2153034680
36
- - !ruby/object:Gem::Dependency
37
- name: jeweler
38
- requirement: &2153033680 !ruby/object:Gem::Requirement
39
- none: false
40
- requirements:
41
- - - ~>
42
- - !ruby/object:Gem::Version
43
- version: 1.6.4
44
- type: :development
45
- prerelease: false
46
- version_requirements: *2153033680
47
- - !ruby/object:Gem::Dependency
48
- name: rcov
49
- requirement: &2153032540 !ruby/object:Gem::Requirement
15
+ name: simplecov
16
+ requirement: !ruby/object:Gem::Requirement
50
17
  none: false
51
18
  requirements:
52
19
  - - ! '>='
@@ -54,47 +21,40 @@ dependencies:
54
21
  version: '0'
55
22
  type: :development
56
23
  prerelease: false
57
- version_requirements: *2153032540
58
- - !ruby/object:Gem::Dependency
59
- name: simplecov
60
- requirement: &2153029720 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
61
25
  none: false
62
26
  requirements:
63
27
  - - ! '>='
64
28
  - !ruby/object:Gem::Version
65
29
  version: '0'
66
- type: :development
67
- prerelease: false
68
- version_requirements: *2153029720
69
- description: A simple cron-like scheduler for Ruby
70
- email: junegunn.c@gmail.com
30
+ description: A simple cron-like scheduler
31
+ email:
32
+ - junegunn.c@gmail.com
71
33
  executables: []
72
34
  extensions: []
73
- extra_rdoc_files:
74
- - LICENSE.txt
75
- - README.markdown
35
+ extra_rdoc_files: []
76
36
  files:
77
37
  - .document
78
- - CHANGELOG.rdoc
38
+ - .gitignore
39
+ - CHANGELOG.md
79
40
  - Gemfile
80
- - Gemfile.lock
81
- - LICENSE.txt
82
- - README.markdown
41
+ - LICENSE
42
+ - README.md
83
43
  - Rakefile
84
- - VERSION
85
44
  - lib/rcron.rb
86
45
  - lib/rcron/alarm.rb
87
46
  - lib/rcron/parser.rb
88
47
  - lib/rcron/scheduler.rb
89
48
  - lib/rcron/task.rb
90
49
  - lib/rcron/timeout.rb
50
+ - lib/rcron/version.rb
51
+ - rcron.gemspec
91
52
  - test/helper.rb
92
53
  - test/test_rcron.rb
93
54
  - test/test_rcron_parser.rb
94
55
  - test/test_rcron_task.rb
95
- homepage: http://github.com/junegunn/rcron
96
- licenses:
97
- - MIT
56
+ homepage: https://github.com/junegunn/rcron
57
+ licenses: []
98
58
  post_install_message:
99
59
  rdoc_options: []
100
60
  require_paths:
@@ -105,9 +65,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
105
65
  - - ! '>='
106
66
  - !ruby/object:Gem::Version
107
67
  version: '0'
108
- segments:
109
- - 0
110
- hash: -994378731135453233
111
68
  required_rubygems_version: !ruby/object:Gem::Requirement
112
69
  none: false
113
70
  requirements:
@@ -116,8 +73,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
73
  version: '0'
117
74
  requirements: []
118
75
  rubyforge_project:
119
- rubygems_version: 1.8.6
76
+ rubygems_version: 1.8.24
120
77
  signing_key:
121
78
  specification_version: 3
122
- summary: A simple cron-like scheduler
123
- test_files: []
79
+ summary: A simple cron-like scheduler for Ruby
80
+ test_files:
81
+ - test/helper.rb
82
+ - test/test_rcron.rb
83
+ - test/test_rcron_parser.rb
84
+ - test/test_rcron_task.rb
@@ -1,6 +0,0 @@
1
- === 0.1.1 / 2011/09/06
2
- * RCron#enq and RCron::Task#deq as aliases of q and dq
3
-
4
- === 0.1.0 / 2011/08/31
5
- * Initial release
6
-
@@ -1,26 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- git (1.2.5)
5
- jeweler (1.6.4)
6
- bundler (~> 1.0)
7
- git (>= 1.2.5)
8
- rake
9
- rake (0.9.2)
10
- rcov (0.9.10)
11
- rcov (0.9.10-java)
12
- simplecov (0.4.2)
13
- simplecov-html (~> 0.4.4)
14
- simplecov-html (0.4.5)
15
- yard (0.6.8)
16
-
17
- PLATFORMS
18
- java
19
- ruby
20
-
21
- DEPENDENCIES
22
- bundler (~> 1.0.0)
23
- jeweler (~> 1.6.4)
24
- rcov
25
- simplecov
26
- yard (~> 0.6.0)
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.1.1