que-scheduler 0.5.0 → 0.6.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 +4 -4
- data/README.md +26 -11
- data/lib/que/scheduler/defined_job.rb +32 -0
- data/lib/que/scheduler/schedule_parser.rb +13 -16
- data/lib/que/scheduler/scheduler_job.rb +25 -16
- data/lib/que/scheduler/scheduler_job_args.rb +1 -0
- data/lib/que/scheduler/version.rb +1 -1
- metadata +16 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e2783e68e146ba7ba266c283c887e256963b451
|
4
|
+
data.tar.gz: 55c52e08b23cab6ef75e3b9c8e8d0cc368f123c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 551365361fc0f13a520c396243577d972fed0b8b3dfe798fb92990f2d1b2779bf79544b9dfb6a258439bcd5bc17a773c45bb142fa39f3b9930eec8b7487fba5d
|
7
|
+
data.tar.gz: 363661214b0d6375a813ecc68b9dbd04e1cf367dca2ff978a9047a7e2aa99825df1ae64ebda7f533919a628845f804cea4f8ea9c32a6cb805754c61a80e10f8e
|
data/README.md
CHANGED
@@ -45,20 +45,35 @@ For example:
|
|
45
45
|
CancelAbandonedOrders:
|
46
46
|
cron: "*/5 * * * *"
|
47
47
|
|
48
|
+
# Specify the job_class, using any name for the key.
|
48
49
|
queue_documents_for_indexing:
|
49
50
|
cron: "0 0 * * *"
|
50
|
-
|
51
|
-
# If you want to have a different job name and class name, provide the 'class' option
|
52
|
-
class: "QueueDocuments"
|
53
|
-
queue: high
|
54
|
-
args: ['reports', 'expenses']
|
55
|
-
|
56
|
-
clear_leaderboards_contributors:
|
57
|
-
cron: "30 6 * * 1"
|
58
|
-
class: "ClearLeaderboards"
|
59
|
-
queue: low
|
60
|
-
args: contributors
|
51
|
+
class: QueueDocuments
|
61
52
|
|
53
|
+
# Specify job queues
|
54
|
+
ReportOrders:
|
55
|
+
cron: "0 0 * * *"
|
56
|
+
queue: reporting
|
57
|
+
|
58
|
+
# Specify job priority using Que's number system
|
59
|
+
BatchOrders:
|
60
|
+
cron: "0 0 * * *"
|
61
|
+
priority: 25
|
62
|
+
|
63
|
+
# Specify job queues
|
64
|
+
SendOrders:
|
65
|
+
cron: "0 0 * * *"
|
66
|
+
args: ['open']
|
67
|
+
|
68
|
+
# Altogether now
|
69
|
+
all_args_job:
|
70
|
+
cron: "0 0 * * *"
|
71
|
+
class: QueueDocuments
|
72
|
+
queue: reporting
|
73
|
+
priority: 25
|
74
|
+
args: ['open']
|
75
|
+
|
76
|
+
# Ensure you never miss a job, even after downtime
|
62
77
|
DailyBatchReport:
|
63
78
|
cron: "0 3 * * *"
|
64
79
|
# This job will be run every day, and if workers are offline for several days, then the backlog
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require 'fugit'
|
3
|
+
|
4
|
+
# This is the definition of one scheduled job in the yml file.
|
5
|
+
module Que
|
6
|
+
module Scheduler
|
7
|
+
class DefinedJob < Hashie::Dash
|
8
|
+
include Hashie::Extensions::Dash::PropertyTranslation
|
9
|
+
|
10
|
+
def self.err_field(f, v)
|
11
|
+
suffix = "in que-scheduler config #{QUE_SCHEDULER_CONFIG_LOCATION}"
|
12
|
+
raise "Invalid #{f} '#{v}' #{suffix}"
|
13
|
+
end
|
14
|
+
|
15
|
+
property :name, required: true
|
16
|
+
property :job_class, required: true
|
17
|
+
property :cron, transform_with: ->(v) { Fugit::Cron.new(v) || err_field(:cron, v) }
|
18
|
+
property :queue, transform_with: ->(v) { v.is_a?(String) ? v : err_field(:queue, v) }
|
19
|
+
property :priority, transform_with: ->(v) { v.is_a?(Integer) ? v : err_field(:priority, v) }
|
20
|
+
property :args
|
21
|
+
property :unmissable, default: false
|
22
|
+
|
23
|
+
# Given a "last time", return the next Time the event will occur, or nil if it
|
24
|
+
# is after "to".
|
25
|
+
def next_run_time(from, to)
|
26
|
+
next_time = cron.next_time(from)
|
27
|
+
next_run = next_time.to_local_time.in_time_zone(next_time.zone)
|
28
|
+
next_run <= to ? next_run : nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'fugit'
|
2
|
+
require 'backports/2.4.0/hash/compact'
|
2
3
|
|
3
4
|
module Que
|
4
5
|
module Scheduler
|
@@ -15,7 +16,7 @@ module Que
|
|
15
16
|
# If it is "unmissable" then we schedule all of them, with the missed time as an arg,
|
16
17
|
# otherwise just schedule it once.
|
17
18
|
scheduler_config.each do |desc|
|
18
|
-
job_name = desc
|
19
|
+
job_name = desc.name
|
19
20
|
schedule_dictionary << job_name
|
20
21
|
|
21
22
|
# If we have never seen this job before, we don't want to scheduled any jobs for it.
|
@@ -26,7 +27,7 @@ module Que
|
|
26
27
|
missed = calculate_missed_runs(
|
27
28
|
desc, scheduler_job_args.last_run_time, scheduler_job_args.as_time
|
28
29
|
)
|
29
|
-
missed_jobs[desc
|
30
|
+
missed_jobs[desc.job_class] = missed unless missed.empty?
|
30
31
|
end
|
31
32
|
|
32
33
|
ScheduleParserResult.new(missed_jobs, schedule_dictionary)
|
@@ -39,7 +40,7 @@ module Que
|
|
39
40
|
def calculate_missed_runs(desc, last_run_time, as_time)
|
40
41
|
missed_times = []
|
41
42
|
last_time = last_run_time
|
42
|
-
while (next_run = next_run_time(
|
43
|
+
while (next_run = desc.next_run_time(last_time, as_time))
|
43
44
|
missed_times << next_run
|
44
45
|
last_time = next_run
|
45
46
|
end
|
@@ -47,28 +48,24 @@ module Que
|
|
47
48
|
generate_required_jobs_list(desc, missed_times)
|
48
49
|
end
|
49
50
|
|
50
|
-
# Given a cron, and a "last time", return the next Time the event will occur, or nil if it
|
51
|
-
# is after "to".
|
52
|
-
def next_run_time(cron, from, to)
|
53
|
-
fugit_cron = Fugit::Cron.parse(cron)
|
54
|
-
next_time = fugit_cron.next_time(from)
|
55
|
-
next_run = next_time.to_local_time.in_time_zone(next_time.zone)
|
56
|
-
next_run <= to ? next_run : nil
|
57
|
-
end
|
58
|
-
|
59
51
|
# Given a job description, and the timestamps of the missed events, generate a list of jobs
|
60
52
|
# that can be enqueued as an array of arrays of args.
|
61
53
|
def generate_required_jobs_list(desc, missed_times)
|
62
54
|
jobs_for_class = []
|
55
|
+
|
63
56
|
unless missed_times.empty?
|
64
|
-
|
57
|
+
options = {
|
58
|
+
args: desc.args,
|
59
|
+
queue: desc.queue,
|
60
|
+
priority: desc.priority
|
61
|
+
}.compact
|
65
62
|
|
66
|
-
if desc
|
63
|
+
if desc.unmissable
|
67
64
|
missed_times.each do |time_missed|
|
68
|
-
jobs_for_class << [time_missed] +
|
65
|
+
jobs_for_class << options.merge(args: [time_missed] + (desc.args || []))
|
69
66
|
end
|
70
67
|
else
|
71
|
-
jobs_for_class <<
|
68
|
+
jobs_for_class << options
|
72
69
|
end
|
73
70
|
end
|
74
71
|
jobs_for_class
|
@@ -1,10 +1,16 @@
|
|
1
1
|
require 'que'
|
2
2
|
require 'yaml'
|
3
|
+
require 'backports/2.4.0/hash/compact'
|
4
|
+
|
5
|
+
require_relative 'defined_job'
|
3
6
|
require_relative 'schedule_parser'
|
4
7
|
require_relative 'scheduler_job_args'
|
5
8
|
|
6
9
|
module Que
|
7
10
|
module Scheduler
|
11
|
+
QUE_SCHEDULER_CONFIG_LOCATION =
|
12
|
+
ENV.fetch('QUE_SCHEDULER_CONFIG_LOCATION', 'config/que_schedule.yml')
|
13
|
+
|
8
14
|
class SchedulerJob < Que::Job
|
9
15
|
SCHEDULER_FREQUENCY = 60
|
10
16
|
|
@@ -17,22 +23,25 @@ module Que
|
|
17
23
|
|
18
24
|
::ActiveRecord::Base.transaction do
|
19
25
|
scheduler_job_args = SchedulerJobArgs.prepare_scheduler_job_args(options)
|
20
|
-
|
21
|
-
result = enqueue_required_jobs(scheduler_job_args)
|
26
|
+
logs = ["que-scheduler last ran at #{scheduler_job_args.last_run_time}."]
|
27
|
+
result = enqueue_required_jobs(scheduler_job_args, logs)
|
22
28
|
enqueue_self_again(scheduler_job_args, result.schedule_dictionary)
|
29
|
+
|
30
|
+
# Only now we're sure nothing errored, log the results
|
31
|
+
logs.each { |str| Que.log(message: str) }
|
23
32
|
destroy
|
24
33
|
end
|
25
34
|
end
|
26
35
|
|
27
36
|
private
|
28
37
|
|
29
|
-
def enqueue_required_jobs(scheduler_job_args)
|
38
|
+
def enqueue_required_jobs(scheduler_job_args, logs)
|
30
39
|
# Obtain the hash of missed jobs. Keys are the job classes, and the values are arrays
|
31
40
|
# each containing more arrays for the arguments of that instance.
|
32
41
|
result = ScheduleParser.parse(SchedulerJob.scheduler_config, scheduler_job_args)
|
33
42
|
result.missed_jobs.each do |job_class, args_arrays|
|
34
43
|
args_arrays.each do |args|
|
35
|
-
|
44
|
+
logs << "que-scheduler enqueueing #{job_class} with options: #{args}"
|
36
45
|
job_class.enqueue(*args)
|
37
46
|
end
|
38
47
|
end
|
@@ -50,8 +59,7 @@ module Que
|
|
50
59
|
class << self
|
51
60
|
def scheduler_config
|
52
61
|
@scheduler_config ||= begin
|
53
|
-
|
54
|
-
jobs_list(YAML.load_file(location))
|
62
|
+
jobs_list(YAML.load_file(QUE_SCHEDULER_CONFIG_LOCATION))
|
55
63
|
end
|
56
64
|
end
|
57
65
|
|
@@ -59,16 +67,17 @@ module Que
|
|
59
67
|
# "unmissable" parameters.
|
60
68
|
def jobs_list(schedule)
|
61
69
|
schedule.map do |k, v|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
70
|
+
Que::Scheduler::DefinedJob.new(
|
71
|
+
{
|
72
|
+
name: k,
|
73
|
+
job_class: Object.const_get(v['class'] || k),
|
74
|
+
queue: v['queue'],
|
75
|
+
args: v['args'],
|
76
|
+
priority: v['priority'],
|
77
|
+
cron: v['cron'],
|
78
|
+
unmissable: v['unmissable']
|
79
|
+
}.compact
|
80
|
+
)
|
72
81
|
end
|
73
82
|
end
|
74
83
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: que-scheduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Harry Lascelles
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0.10'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: backports
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.10'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.10'
|
69
83
|
description: A lightweight cron scheduler for the async job worker Que
|
70
84
|
email:
|
71
85
|
- harry@harrylascelles.com
|
@@ -75,6 +89,7 @@ extra_rdoc_files: []
|
|
75
89
|
files:
|
76
90
|
- README.md
|
77
91
|
- lib/que/scheduler.rb
|
92
|
+
- lib/que/scheduler/defined_job.rb
|
78
93
|
- lib/que/scheduler/schedule_parser.rb
|
79
94
|
- lib/que/scheduler/scheduler_job.rb
|
80
95
|
- lib/que/scheduler/scheduler_job_args.rb
|