rufus-scheduler 3.0.8 → 3.2.0

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.
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2006-2014, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2006-2015, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -25,8 +25,7 @@
25
25
  require 'date' if RUBY_VERSION < '1.9.0'
26
26
  require 'time'
27
27
  require 'thread'
28
- require 'tzinfo'
29
- require 'fileutils'
28
+ #require 'tzinfo'
30
29
 
31
30
 
32
31
  module Rufus
@@ -34,11 +33,13 @@ module Rufus
34
33
  class Scheduler
35
34
 
36
35
  require 'rufus/scheduler/util'
36
+ require 'rufus/scheduler/zotime'
37
37
  require 'rufus/scheduler/jobs'
38
38
  require 'rufus/scheduler/cronline'
39
39
  require 'rufus/scheduler/job_array'
40
+ require 'rufus/scheduler/locks'
40
41
 
41
- VERSION = '3.0.8'
42
+ VERSION = '3.2.0'
42
43
 
43
44
  #
44
45
  # A common error class for rufus-scheduler
@@ -93,7 +94,17 @@ module Rufus
93
94
 
94
95
  @thread_key = "rufus_scheduler_#{self.object_id}"
95
96
 
96
- lock || return
97
+ @scheduler_lock =
98
+ if lockfile = opts[:lockfile]
99
+ Rufus::Scheduler::FileLock.new(lockfile)
100
+ else
101
+ opts[:scheduler_lock] || Rufus::Scheduler::NullLock.new
102
+ end
103
+
104
+ @trigger_lock = opts[:trigger_lock] || Rufus::Scheduler::NullLock.new
105
+
106
+ # If we can't grab the @scheduler_lock, don't run.
107
+ @scheduler_lock.lock || return
97
108
 
98
109
  start
99
110
  end
@@ -324,6 +335,49 @@ module Rufus
324
335
  @jobs[job_id]
325
336
  end
326
337
 
338
+ # Returns true if the scheduler has acquired the [exclusive] lock and
339
+ # thus may run.
340
+ #
341
+ # Most of the time, a scheduler is run alone and this method should
342
+ # return true. It is useful in cases where among a group of applications
343
+ # only one of them should run the scheduler. For schedulers that should
344
+ # not run, the method should return false.
345
+ #
346
+ # Out of the box, rufus-scheduler proposes the
347
+ # :lockfile => 'path/to/lock/file' scheduler start option. It makes
348
+ # it easy for schedulers on the same machine to determine which should
349
+ # run (the first to write the lockfile and lock it). It uses "man 2 flock"
350
+ # so it probably won't work reliably on distributed file systems.
351
+ #
352
+ # If one needs to use a special/different locking mechanism, the scheduler
353
+ # accepts :scheduler_lock => lock_object. lock_object only needs to respond
354
+ # to #lock
355
+ # and #unlock, and both of these methods should be idempotent.
356
+ #
357
+ # Look at rufus/scheduler/locks.rb for an example.
358
+ #
359
+ def lock
360
+
361
+ @scheduler_lock.lock
362
+ end
363
+
364
+ # Sister method to #lock, is called when the scheduler shuts down.
365
+ #
366
+ def unlock
367
+
368
+ @trigger_lock.unlock
369
+ @scheduler_lock.unlock
370
+ end
371
+
372
+ # Callback called when a job is triggered. If the lock cannot be acquired,
373
+ # the job won't run (though it'll still be scheduled to run again if
374
+ # necessary).
375
+ #
376
+ def confirm_lock
377
+
378
+ @trigger_lock.lock
379
+ end
380
+
327
381
  # Returns true if this job is currently scheduled.
328
382
  #
329
383
  # Takes extra care to answer true if the job is a repeat job
@@ -331,9 +385,9 @@ module Rufus
331
385
  #
332
386
  def scheduled?(job_or_job_id)
333
387
 
334
- job, job_id = fetch(job_or_job_id)
388
+ job, _ = fetch(job_or_job_id)
335
389
 
336
- !! (job && job.next_time != nil)
390
+ !! (job && job.unscheduled_at.nil? && job.next_time != nil)
337
391
  end
338
392
 
339
393
  # Lists all the threads associated with this scheduler.
@@ -387,7 +441,7 @@ module Rufus
387
441
  if format == :timeline
388
442
  a = []
389
443
  h.each { |j, ts| ts.each { |t| a << [ t, j ] } }
390
- a.sort_by { |(t, j)| t }
444
+ a.sort_by { |(t, _)| t }
391
445
  else
392
446
  h
393
447
  end
@@ -423,7 +477,8 @@ module Rufus
423
477
  stderr.puts(" #{pre} opts:")
424
478
  stderr.puts(" #{pre} #{@opts.inspect}")
425
479
  stderr.puts(" #{pre} frequency: #{self.frequency}")
426
- stderr.puts(" #{pre} lockfile: #{@lockfile.inspect}")
480
+ stderr.puts(" #{pre} scheduler_lock: #{@scheduler_lock.inspect}")
481
+ stderr.puts(" #{pre} trigger_lock: #{@trigger_lock.inspect}")
427
482
  stderr.puts(" #{pre} uptime: #{uptime} (#{uptime_s})")
428
483
  stderr.puts(" #{pre} down?: #{down?}")
429
484
  stderr.puts(" #{pre} threads: #{self.threads.size}")
@@ -468,61 +523,6 @@ module Rufus
468
523
  end
469
524
  end
470
525
 
471
- # Returns true if the scheduler has acquired the [exclusive] lock and
472
- # thus may run.
473
- #
474
- # Most of the time, a scheduler is run alone and this method should
475
- # return true. It is useful in cases where among a group of applications
476
- # only one of them should run the scheduler. For schedulers that should
477
- # not run, the method should return false.
478
- #
479
- # Out of the box, rufus-scheduler proposes the
480
- # :lockfile => 'path/to/lock/file' scheduler start option. It makes
481
- # it easy for schedulers on the same machine to determine which should
482
- # run (to first to write the lockfile and lock it). It uses "man 2 flock"
483
- # so it probably won't work reliably on distributed file systems.
484
- #
485
- # If one needs to use a special/different locking mechanism, providing
486
- # overriding implementation for this #lock and the #unlock complement is
487
- # easy.
488
- #
489
- def lock
490
-
491
- @lockfile = nil
492
-
493
- return true unless f = @opts[:lockfile]
494
-
495
- raise ArgumentError.new(
496
- ":lockfile argument must be a string, not a #{f.class}"
497
- ) unless f.is_a?(String)
498
-
499
- FileUtils.mkdir_p(File.dirname(f))
500
-
501
- f = File.new(f, File::RDWR | File::CREAT)
502
- locked = f.flock(File::LOCK_NB | File::LOCK_EX)
503
-
504
- return false unless locked
505
-
506
- now = Time.now
507
-
508
- f.print("pid: #{$$}, ")
509
- f.print("scheduler.object_id: #{self.object_id}, ")
510
- f.print("time: #{now}, ")
511
- f.print("timestamp: #{now.to_f}")
512
- f.flush
513
-
514
- @lockfile = f
515
-
516
- true
517
- end
518
-
519
- # Sister method to #lock, is called when the scheduler shuts down.
520
- #
521
- def unlock
522
-
523
- @lockfile.flock(File::LOCK_UN) if @lockfile
524
- end
525
-
526
526
  def terminate_all_jobs
527
527
 
528
528
  jobs.each { |j| j.unschedule }
@@ -592,11 +592,11 @@ module Rufus
592
592
 
593
593
  job = t[:rufus_scheduler_job]
594
594
  to = t[:rufus_scheduler_timeout]
595
+ ts = t[:rufus_scheduler_time]
595
596
 
596
- next unless job && to
597
+ next unless job && to && ts
597
598
  # thread might just have become inactive (job -> nil)
598
599
 
599
- ts = t[:rufus_scheduler_time]
600
600
  to = to.is_a?(Time) ? to : ts + to
601
601
 
602
602
  next if to > Time.now
@@ -629,7 +629,7 @@ module Rufus
629
629
 
630
630
  job = job_class.new(self, t, opts, block || callable)
631
631
 
632
- raise ArgumentError.new(
632
+ fail ArgumentError.new(
633
633
  "job frequency (#{job.frequency}) is higher than " +
634
634
  "scheduler frequency (#{@frequency})"
635
635
  ) if job.respond_to?(:frequency) && job.frequency < @frequency
@@ -22,42 +22,17 @@ job scheduler for Ruby (at, cron, in and every jobs).
22
22
  #s.files = `git ls-files`.split("\n")
23
23
  s.files = Dir[
24
24
  'Rakefile',
25
- 'lib/**/*.rb', 'spec/**/*.rb', 'test/**/*.rb',
25
+ 'lib/**/*.rb', #'spec/**/*.rb', 'test/**/*.rb',
26
26
  '*.gemspec', '*.txt', '*.rdoc', '*.md'
27
27
  ]
28
28
 
29
- s.add_runtime_dependency 'tzinfo'
29
+ #s.add_runtime_dependency 'tzinfo'
30
30
 
31
31
  s.add_development_dependency 'rake'
32
32
  s.add_development_dependency 'rspec', '>= 2.13.0'
33
33
  s.add_development_dependency 'chronic'
34
+ s.add_development_dependency 'tzinfo'
34
35
 
35
36
  s.require_path = 'lib'
36
-
37
- s.post_install_message =
38
- %{
39
- ***
40
-
41
- Thanks for installing rufus-scheduler #{s.version}
42
-
43
- It might not be 100% compatible with rufus-scheduler 2.x.
44
-
45
- If you encounter issues with this new rufus-scheduler, especially
46
- if your app worked fine with previous versions of it, you can
47
-
48
- A) Forget it and peg your Gemfile to rufus-scheduler 2.0.24
49
-
50
- and / or
51
-
52
- B) Take some time to carefully report the issue at
53
- https://github.com/jmettraux/rufus-scheduler/issues
54
-
55
- For general help about rufus-scheduler, ask via:
56
- http://stackoverflow.com/questions/ask?tags=rufus-scheduler+ruby
57
-
58
- Cheers.
59
-
60
- ***
61
- }
62
37
  end
63
38
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rufus-scheduler
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.8
4
+ version: 3.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,17 +9,17 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-06-08 00:00:00.000000000 Z
12
+ date: 2015-12-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: tzinfo
15
+ name: rake
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
21
  version: '0'
22
- type: :runtime
22
+ type: :development
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
@@ -28,13 +28,13 @@ dependencies:
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
30
  - !ruby/object:Gem::Dependency
31
- name: rake
31
+ name: rspec
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
35
35
  - - ! '>='
36
36
  - !ruby/object:Gem::Version
37
- version: '0'
37
+ version: 2.13.0
38
38
  type: :development
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,15 +42,15 @@ dependencies:
42
42
  requirements:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
- version: '0'
45
+ version: 2.13.0
46
46
  - !ruby/object:Gem::Dependency
47
- name: rspec
47
+ name: chronic
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
51
  - - ! '>='
52
52
  - !ruby/object:Gem::Version
53
- version: 2.13.0
53
+ version: '0'
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,9 +58,9 @@ dependencies:
58
58
  requirements:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
- version: 2.13.0
61
+ version: '0'
62
62
  - !ruby/object:Gem::Dependency
63
- name: chronic
63
+ name: tzinfo
64
64
  requirement: !ruby/object:Gem::Requirement
65
65
  none: false
66
66
  requirements:
@@ -83,50 +83,25 @@ extensions: []
83
83
  extra_rdoc_files: []
84
84
  files:
85
85
  - Rakefile
86
- - lib/rufus-scheduler.rb
87
- - lib/rufus/scheduler.rb
88
86
  - lib/rufus/scheduler/cronline.rb
89
- - lib/rufus/scheduler/util.rb
90
- - lib/rufus/scheduler/jobs.rb
91
87
  - lib/rufus/scheduler/job_array.rb
92
- - spec/job_spec.rb
93
- - spec/schedule_in_spec.rb
94
- - spec/spec_helper.rb
95
- - spec/job_array_spec.rb
96
- - spec/schedule_interval_spec.rb
97
- - spec/job_at_spec.rb
98
- - spec/schedule_at_spec.rb
99
- - spec/error_spec.rb
100
- - spec/schedule_cron_spec.rb
101
- - spec/job_interval_spec.rb
102
- - spec/job_repeat_spec.rb
103
- - spec/lockfile_spec.rb
104
- - spec/schedule_every_spec.rb
105
- - spec/threads_spec.rb
106
- - spec/cronline_spec.rb
107
- - spec/job_in_spec.rb
108
- - spec/parse_spec.rb
109
- - spec/scheduler_spec.rb
110
- - spec/custom_locks_spec.rb
111
- - spec/basics_spec.rb
112
- - spec/job_cron_spec.rb
113
- - spec/job_every_spec.rb
88
+ - lib/rufus/scheduler/jobs.rb
89
+ - lib/rufus/scheduler/locks.rb
90
+ - lib/rufus/scheduler/util.rb
91
+ - lib/rufus/scheduler/zones.rb
92
+ - lib/rufus/scheduler/zotime.rb
93
+ - lib/rufus/scheduler.rb
94
+ - lib/rufus-scheduler.rb
114
95
  - rufus-scheduler.gemspec
115
96
  - CHANGELOG.txt
116
- - TODO.txt
117
- - LICENSE.txt
118
97
  - CREDITS.txt
98
+ - LICENSE.txt
99
+ - TODO.txt
119
100
  - README.md
120
101
  homepage: http://github.com/jmettraux/rufus-scheduler
121
102
  licenses:
122
103
  - MIT
123
- post_install_message: ! "\n***\n\nThanks for installing rufus-scheduler 3.0.8\n\nIt
124
- might not be 100% compatible with rufus-scheduler 2.x.\n\nIf you encounter issues
125
- with this new rufus-scheduler, especially\nif your app worked fine with previous
126
- versions of it, you can\n\nA) Forget it and peg your Gemfile to rufus-scheduler
127
- 2.0.24\n\nand / or\n\nB) Take some time to carefully report the issue at\n https://github.com/jmettraux/rufus-scheduler/issues\n\nFor
128
- general help about rufus-scheduler, ask via:\nhttp://stackoverflow.com/questions/ask?tags=rufus-scheduler+ruby\n\nCheers.\n\n***\n
129
- \ "
104
+ post_install_message:
130
105
  rdoc_options: []
131
106
  require_paths:
132
107
  - lib
@@ -144,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
119
  version: '0'
145
120
  requirements: []
146
121
  rubyforge_project: rufus
147
- rubygems_version: 1.8.23
122
+ rubygems_version: 1.8.23.2
148
123
  signing_key:
149
124
  specification_version: 3
150
125
  summary: job scheduler for Ruby (at, cron, in and every jobs)
data/spec/basics_spec.rb DELETED
@@ -1,49 +0,0 @@
1
-
2
- #
3
- # Specifying rufus-scheduler
4
- #
5
- # Sun Jun 1 05:52:24 JST 2014
6
- #
7
-
8
- require 'spec_helper'
9
-
10
-
11
- describe 'basics' do
12
-
13
- def tts(time)
14
-
15
- time.strftime('%Y-%m-%d %H:%M:%S %z') + (time.dst? ? ' dst' : '')
16
- end
17
-
18
- describe 'Time.new' do
19
-
20
- it 'accepts a timezone final argument' do
21
-
22
- pending if jruby? or ruby18?
23
-
24
- expect(
25
- tts(Time.new(2014, 1, 1, 1, 0, 0, '+01:00'))
26
- ).to eq('2014-01-01 01:00:00 +0100')
27
- expect(
28
- tts(Time.new(2014, 8, 1, 1, 0, 0, '+01:00'))
29
- ).to eq('2014-08-01 01:00:00 +0100')
30
- expect(
31
- tts(Time.new(2014, 8, 1, 1, 0, 0, '+01:00'))
32
- ).to eq('2014-08-01 01:00:00 +0100')
33
- end
34
- end
35
-
36
- describe 'Time.local' do
37
-
38
- it 'works as expected' do
39
-
40
- expect(
41
- tts(in_zone('Europe/Berlin') { Time.local(2014, 1, 1, 1, 0, 0) })
42
- ).to eq('2014-01-01 01:00:00 +0100')
43
- expect(
44
- tts(in_zone('Europe/Berlin') { Time.local(2014, 8, 1, 1, 0, 0) })
45
- ).to eq('2014-08-01 01:00:00 +0200 dst')
46
- end
47
- end
48
- end
49
-