sidekiq-repeat 0.1.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.
- 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: []
|