sidekiq-repeat 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,11 @@
1
+ module Sidekiq
2
+ module Repeat
3
+ class Middleware
4
+ def call(worker, item, queue)
5
+ yield
6
+ ensure
7
+ worker.class.reschedule if worker.class.respond_to?(:reschedule)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -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
@@ -0,0 +1,5 @@
1
+ module Sidekiq
2
+ module Repeat
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ require 'parse-cron'
2
+ require 'sidekiq'
3
+ require 'sidekiq/api'
4
+
5
+ require 'sidekiq/repeat/middleware'
6
+ require 'sidekiq/repeat/mini_ice_cube'
7
+ require 'sidekiq/repeat/repeatable'
8
+ require 'sidekiq/repeat/version'
@@ -0,0 +1,11 @@
1
+ require 'sidekiq/repeat'
2
+
3
+ Sidekiq.configure_server do |config|
4
+ config.server_middleware do |chain|
5
+ chain.add Sidekiq::Repeat::Middleware
6
+ end
7
+
8
+ config.on(:startup) do
9
+ Sidekiq::Repeat::Repeatable.reschedule_all
10
+ end
11
+ 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: []