sidekiq-repeat 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/sidekiq/repeat/middleware.rb +11 -0
- data/lib/sidekiq/repeat/mini_ice_cube.rb +96 -0
- data/lib/sidekiq/repeat/repeatable.rb +47 -0
- data/lib/sidekiq/repeat/version.rb +5 -0
- data/lib/sidekiq/repeat.rb +8 -0
- data/lib/sidekiq-repeat.rb +11 -0
- metadata +106 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 640363fb32bb0a5e6c6d7b9ce47109bb4d26244e
|
4
|
+
data.tar.gz: 43481093dd233b479c4fa4c5809cee3b547911d2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2957cc62da166c65fc5ea481a39a903d6a6e2a533aa3f4b0a81171a0975b9d0ce253b995bdd3d9a61b4e729d4d7cb1252c515346750840e04c66955af3eed0b5
|
7
|
+
data.tar.gz: cb43747010d8c0aa4243a4d8d161270d54d4b2e19a75acb2dd9f446415157d70047bfa889a3e5ff61187abd7be7905019bf8e50abc88bb5cc7be36ab17e2727c
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module Repeat
|
3
|
+
##
|
4
|
+
# This is a mini compatibility layer for the ice_cube syntax. Nothing fancy.
|
5
|
+
# It only supports interval-based -ly functions like "hourly(4)" and array
|
6
|
+
# list information like .minute_of_hour(0,15,30,45), as these are the ones
|
7
|
+
# that we use.
|
8
|
+
module MiniIceCube
|
9
|
+
module IceCubeDslErrorHandling
|
10
|
+
IceCubeSyntaxError = Class.new(StandardError)
|
11
|
+
|
12
|
+
def unsupported(msg)
|
13
|
+
fail IceCubeSyntaxError, "Sidekiq::Repeat: Unsupported ice_cube syntax. Please refer to the documentation. (#{msg})"
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(meth, *args, &block)
|
17
|
+
unsupported("method not found: #{meth}")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class CronSyntax
|
22
|
+
include IceCubeDslErrorHandling
|
23
|
+
|
24
|
+
class << self
|
25
|
+
def define_items_method(name, slot)
|
26
|
+
define_method(name) do |*args|
|
27
|
+
unsupported("invalid arguments for #{name}") unless args.any? && args.all? { |i| i.is_a?(Integer) || i =~ /\d+/ }
|
28
|
+
@slots[slot] = args.map(&:to_s).join(',')
|
29
|
+
self
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(*args)
|
35
|
+
@slots = args
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
@slots.map(&:to_s).join(' ')
|
40
|
+
end
|
41
|
+
|
42
|
+
define_items_method(:minute_of_hour, 0)
|
43
|
+
define_items_method(:hour_of_day, 1)
|
44
|
+
define_items_method(:day_of_month, 2)
|
45
|
+
end
|
46
|
+
|
47
|
+
class MainDsl
|
48
|
+
include IceCubeDslErrorHandling
|
49
|
+
|
50
|
+
class << self
|
51
|
+
def define_interval_method(name, base, *stars_prefix)
|
52
|
+
define_method(name) do |*args|
|
53
|
+
stars = stars_prefix.dup || []
|
54
|
+
|
55
|
+
if args.any?
|
56
|
+
interval = args.first.to_i
|
57
|
+
unsupported("invalid interval: #{interval}") unless interval && interval >= 0 && interval <= base
|
58
|
+
|
59
|
+
# Instead of always calculating the next() occurrence as ice_cube does,
|
60
|
+
# we can only have fixed run times (as per cron syntax). Hence we calculate
|
61
|
+
# the run times based on integer division of interval and time frame, using
|
62
|
+
# a random start offset based on the remaining time.
|
63
|
+
#
|
64
|
+
# NOTE: This effectivly means that after the last run in the time frame the
|
65
|
+
# next run will be scheduled after interval+remainder.
|
66
|
+
#
|
67
|
+
# Example: minutely(17) will run 3 times per hour. After the last run each
|
68
|
+
# hour the skip will be 17 + 9 = 26 minutes. A random offset in
|
69
|
+
# [0,26) will be applied, so a possible cron line could be '4,21,38'.
|
70
|
+
|
71
|
+
times = []
|
72
|
+
nruns = (base / interval).floor
|
73
|
+
rnoff = rand(interval + base % interval).floor
|
74
|
+
runs = nruns.times.map { |i| i * interval + rnoff }
|
75
|
+
stars << runs.map(&:to_s).join(',')
|
76
|
+
end
|
77
|
+
|
78
|
+
stars.fill('*', stars.size..4)
|
79
|
+
CronSyntax.new(*stars)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def weekly(*args)
|
85
|
+
unsupported('interval argument unsupported for weekly') unless args.empty?
|
86
|
+
CronSyntax.new(0, 3, '*', '*', 0) # Sundays at 3AM.
|
87
|
+
end
|
88
|
+
|
89
|
+
define_interval_method(:minutely, 60)
|
90
|
+
define_interval_method(:hourly, 24, 0) # At first minute of hour.
|
91
|
+
define_interval_method(:daily, 31, 0, 3) # At night, 3AM.
|
92
|
+
define_interval_method(:monthly, 12, 0, 3, 0) # First day of the month, 3AM.
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module Repeat
|
3
|
+
module Repeatable
|
4
|
+
module ClassMethods
|
5
|
+
def repeat(&block)
|
6
|
+
@cronline = MiniIceCube::MainDsl.new.instance_eval(&block).to_s
|
7
|
+
@cronline = CronParser.new(@cronline)
|
8
|
+
rescue ArgumentError
|
9
|
+
fail "repeat '#{@cronline}' in class #{self.name} is not a valid cron line"
|
10
|
+
end
|
11
|
+
|
12
|
+
def reschedule
|
13
|
+
return unless repeat_configured?
|
14
|
+
return if already_scheduled?
|
15
|
+
|
16
|
+
ts = @cronline.next
|
17
|
+
self.perform_at ts.to_f
|
18
|
+
Sidekiq.logger.info "Scheduled #{self.name} for #{ts}."
|
19
|
+
end
|
20
|
+
|
21
|
+
def repeat_configured?
|
22
|
+
!!@cronline
|
23
|
+
end
|
24
|
+
|
25
|
+
def already_scheduled?
|
26
|
+
@ss ||= Sidekiq::ScheduledSet.new
|
27
|
+
@ss.any? { |job| job.klass == self.name }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class << self
|
32
|
+
def repeatables
|
33
|
+
@repeatables ||= []
|
34
|
+
end
|
35
|
+
|
36
|
+
def reschedule_all
|
37
|
+
repeatables.each(&:reschedule)
|
38
|
+
end
|
39
|
+
|
40
|
+
def included(klass)
|
41
|
+
klass.extend(Sidekiq::Repeat::Repeatable::ClassMethods)
|
42
|
+
repeatables << klass
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sidekiq-repeat
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- FlavourSys Technology GmbH
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sidekiq
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: parse-cron
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.4'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.4'
|
69
|
+
description: This gem adds recurring jobs to Sidekiq. It is heavily inspired by the
|
70
|
+
sidekiq-dejavu and sidetiq gems.
|
71
|
+
email: technology@flavoursys.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- lib/sidekiq-repeat.rb
|
77
|
+
- lib/sidekiq/repeat.rb
|
78
|
+
- lib/sidekiq/repeat/middleware.rb
|
79
|
+
- lib/sidekiq/repeat/mini_ice_cube.rb
|
80
|
+
- lib/sidekiq/repeat/repeatable.rb
|
81
|
+
- lib/sidekiq/repeat/version.rb
|
82
|
+
homepage: https://github.com/FlavourSys/sidekiq-repeat
|
83
|
+
licenses:
|
84
|
+
- MIT
|
85
|
+
metadata: {}
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 2.2.2
|
103
|
+
signing_key:
|
104
|
+
specification_version: 4
|
105
|
+
summary: Repeat is a clockless recurring job system for Sidekiq.
|
106
|
+
test_files: []
|