que 1.3.0 → 2.0.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.
data/lib/que/job.rb CHANGED
@@ -12,7 +12,7 @@ module Que
12
12
  SQL[:insert_job] =
13
13
  %{
14
14
  INSERT INTO public.que_jobs
15
- (queue, priority, run_at, job_class, args, data, job_schema_version)
15
+ (queue, priority, run_at, job_class, args, kwargs, data, job_schema_version)
16
16
  VALUES
17
17
  (
18
18
  coalesce($1, 'default')::text,
@@ -21,6 +21,7 @@ module Que
21
21
  $4::text,
22
22
  coalesce($5, '[]')::jsonb,
23
23
  coalesce($6, '{}')::jsonb,
24
+ coalesce($7, '{}')::jsonb,
24
25
  #{Que.job_schema_version}
25
26
  )
26
27
  RETURNING *
@@ -56,13 +57,10 @@ module Que
56
57
  :priority,
57
58
  :run_at
58
59
 
59
- def enqueue(
60
- *args,
61
- job_options: {},
62
- **arg_opts
63
- )
64
- arg_opts, job_options = _extract_job_options(arg_opts, job_options.dup)
65
- args << arg_opts if arg_opts.any?
60
+ def enqueue(*args)
61
+ args, kwargs = Que.split_out_ruby2_keywords(args)
62
+
63
+ job_options = kwargs.delete(:job_options) || {}
66
64
 
67
65
  if job_options[:tags]
68
66
  if job_options[:tags].length > MAXIMUM_TAGS_COUNT
@@ -81,6 +79,7 @@ module Que
81
79
  priority: job_options[:priority] || resolve_que_setting(:priority),
82
80
  run_at: job_options[:run_at] || resolve_que_setting(:run_at),
83
81
  args: Que.serialize_json(args),
82
+ kwargs: Que.serialize_json(kwargs),
84
83
  data: job_options[:tags] ? Que.serialize_json(tags: job_options[:tags]) : "{}",
85
84
  job_class: \
86
85
  job_options[:job_class] || name ||
@@ -89,27 +88,31 @@ module Que
89
88
 
90
89
  if attrs[:run_at].nil? && resolve_que_setting(:run_synchronously)
91
90
  attrs[:args] = Que.deserialize_json(attrs[:args])
91
+ attrs[:kwargs] = Que.deserialize_json(attrs[:kwargs])
92
92
  attrs[:data] = Que.deserialize_json(attrs[:data])
93
93
  _run_attrs(attrs)
94
94
  else
95
95
  values =
96
96
  Que.execute(
97
97
  :insert_job,
98
- attrs.values_at(:queue, :priority, :run_at, :job_class, :args, :data),
98
+ attrs.values_at(:queue, :priority, :run_at, :job_class, :args, :kwargs, :data),
99
99
  ).first
100
-
101
100
  new(values)
102
101
  end
103
102
  end
103
+ ruby2_keywords(:enqueue) if respond_to?(:ruby2_keywords, true)
104
104
 
105
105
  def run(*args)
106
106
  # Make sure things behave the same as they would have with a round-trip
107
107
  # to the DB.
108
+ args, kwargs = Que.split_out_ruby2_keywords(args)
108
109
  args = Que.deserialize_json(Que.serialize_json(args))
110
+ kwargs = Que.deserialize_json(Que.serialize_json(kwargs))
109
111
 
110
112
  # Should not fail if there's no DB connection.
111
- _run_attrs(args: args)
113
+ _run_attrs(args: args, kwargs: kwargs)
112
114
  end
115
+ ruby2_keywords(:run) if respond_to?(:ruby2_keywords, true)
113
116
 
114
117
  def resolve_que_setting(setting, *args)
115
118
  value = send(setting) if respond_to?(setting)
@@ -136,27 +139,6 @@ module Que
136
139
  end
137
140
  end
138
141
  end
139
-
140
- def _extract_job_options(arg_opts, job_options)
141
- deprecated_job_option_names = []
142
-
143
- %i[queue priority run_at job_class tags].each do |option_name|
144
- next unless arg_opts.key?(option_name) && job_options[option_name].nil?
145
-
146
- job_options[option_name] = arg_opts.delete(option_name)
147
- deprecated_job_option_names << option_name
148
- end
149
-
150
- _log_job_options_deprecation(deprecated_job_option_names)
151
-
152
- [arg_opts, job_options]
153
- end
154
-
155
- def _log_job_options_deprecation(deprecated_job_option_names)
156
- return unless deprecated_job_option_names.any?
157
-
158
- warn "Passing job options like (#{deprecated_job_option_names.join(', ')}) to `JobClass.enqueue` as top level keyword args has been deprecated and will be removed in version 2.0. Please wrap job options in an explicit `job_options` keyword arg instead."
159
- end
160
142
  end
161
143
 
162
144
  # Set up some defaults.
@@ -6,7 +6,7 @@
6
6
 
7
7
  module Que
8
8
  class JobBuffer
9
- attr_reader :maximum_size, :minimum_size, :priority_queues
9
+ attr_reader :maximum_size, :priority_queues
10
10
 
11
11
  # Since we use a mutex, which is not reentrant, we have to be a little
12
12
  # careful to not call a method that locks the mutex when we've already
@@ -17,20 +17,11 @@ module Que
17
17
 
18
18
  def initialize(
19
19
  maximum_size:,
20
- minimum_size:,
21
20
  priorities:
22
21
  )
23
22
  @maximum_size = Que.assert(Integer, maximum_size)
24
23
  Que.assert(maximum_size >= 0) { "maximum_size for a JobBuffer must be at least zero!" }
25
24
 
26
- @minimum_size = Que.assert(Integer, minimum_size)
27
- Que.assert(minimum_size >= 0) { "minimum_size for a JobBuffer must be at least zero!" }
28
-
29
- Que.assert(minimum_size <= maximum_size) do
30
- "minimum buffer size (#{minimum_size}) is " \
31
- "greater than the maximum buffer size (#{maximum_size})!"
32
- end
33
-
34
25
  @stop = false
35
26
  @array = []
36
27
  @mutex = Mutex.new
@@ -39,12 +39,16 @@ module Que
39
39
  # Run the job with error handling and cleanup logic. Optionally support
40
40
  # overriding the args, because it's necessary when jobs are invoked from
41
41
  # ActiveJob.
42
- def _run(args: nil, reraise_errors: false)
42
+ def _run(args: nil, kwargs: nil, reraise_errors: false)
43
43
  if args.nil? && que_target
44
44
  args = que_target.que_attrs.fetch(:args)
45
45
  end
46
46
 
47
- run(*args)
47
+ if kwargs.nil? && que_target
48
+ kwargs = que_target.que_attrs.fetch(:kwargs)
49
+ end
50
+
51
+ run(*args, **kwargs)
48
52
  default_resolve_action if que_target && !que_target.que_resolved
49
53
  rescue => error
50
54
  raise error unless que_target
data/lib/que/locker.rb CHANGED
@@ -45,7 +45,6 @@ module Que
45
45
 
46
46
  DEFAULT_POLL_INTERVAL = 5.0
47
47
  DEFAULT_WAIT_PERIOD = 50
48
- DEFAULT_MINIMUM_BUFFER_SIZE = 2
49
48
  DEFAULT_MAXIMUM_BUFFER_SIZE = 8
50
49
  DEFAULT_WORKER_PRIORITIES = [10, 30, 50, nil, nil, nil].freeze
51
50
 
@@ -57,7 +56,6 @@ module Que
57
56
  poll_interval: DEFAULT_POLL_INTERVAL,
58
57
  wait_period: DEFAULT_WAIT_PERIOD,
59
58
  maximum_buffer_size: DEFAULT_MAXIMUM_BUFFER_SIZE,
60
- minimum_buffer_size: DEFAULT_MINIMUM_BUFFER_SIZE,
61
59
  worker_priorities: DEFAULT_WORKER_PRIORITIES,
62
60
  on_worker_start: nil
63
61
  )
@@ -77,7 +75,6 @@ module Que
77
75
  # ResultQueue to receive messages from workers.
78
76
  @job_buffer = JobBuffer.new(
79
77
  maximum_size: maximum_buffer_size,
80
- minimum_size: minimum_buffer_size,
81
78
  priorities: worker_priorities.uniq,
82
79
  )
83
80
 
@@ -93,7 +90,6 @@ module Que
93
90
  poll_interval: poll_interval,
94
91
  wait_period: wait_period,
95
92
  maximum_buffer_size: maximum_buffer_size,
96
- minimum_buffer_size: minimum_buffer_size,
97
93
  worker_priorities: worker_priorities,
98
94
  }
99
95
  end
@@ -0,0 +1,8 @@
1
+ DROP INDEX que_jobs_kwargs_gin_idx;
2
+ ALTER TABLE que_jobs DROP COLUMN kwargs;
3
+
4
+ ALTER INDEX que_poll_idx RENAME TO que_poll_idx_with_job_schema_version;
5
+ CREATE INDEX que_poll_idx ON que_jobs (queue, priority, run_at, id) WHERE (finished_at IS NULL AND expired_at IS NULL);
6
+
7
+ ALTER TABLE que_jobs ALTER COLUMN job_schema_version SET DEFAULT 1;
8
+ ALTER TABLE que_jobs ALTER COLUMN job_schema_version DROP NOT NULL;
@@ -0,0 +1,8 @@
1
+ ALTER TABLE que_jobs ADD COLUMN kwargs JSONB NOT NULL DEFAULT '{}';
2
+ CREATE INDEX que_jobs_kwargs_gin_idx ON que_jobs USING gin (kwargs jsonb_path_ops);
3
+
4
+ DROP INDEX que_poll_idx;
5
+ ALTER INDEX que_poll_idx_with_job_schema_version RENAME TO que_poll_idx;
6
+
7
+ ALTER TABLE que_jobs ALTER COLUMN job_schema_version DROP DEFAULT;
8
+ ALTER TABLE que_jobs ALTER COLUMN job_schema_version SET NOT NULL;
@@ -4,7 +4,7 @@ module Que
4
4
  module Migrations
5
5
  # In order to ship a schema change, add the relevant up and down sql files
6
6
  # to the migrations directory, and bump the version here.
7
- CURRENT_VERSION = 5
7
+ CURRENT_VERSION = 6
8
8
 
9
9
  class << self
10
10
  def migrate!(version:)
data/lib/que/poller.rb CHANGED
@@ -146,8 +146,6 @@ module Que
146
146
 
147
147
  return unless should_poll?
148
148
 
149
- expected_count = priorities.inject(0){|s,(_,c)| s + c}
150
-
151
149
  jobs =
152
150
  connection.execute_prepared(
153
151
  :poll_jobs,
@@ -159,7 +157,7 @@ module Que
159
157
  )
160
158
 
161
159
  @last_polled_at = Time.now
162
- @last_poll_satisfied = expected_count == jobs.count
160
+ @last_poll_satisfied = poll_satisfied?(priorities, jobs)
163
161
 
164
162
  Que.internal_log :poller_polled, self do
165
163
  {
@@ -265,5 +263,12 @@ module Que
265
263
  SQL
266
264
  end
267
265
  end
266
+
267
+ private
268
+
269
+ def poll_satisfied?(priorities, jobs)
270
+ lowest_priority = priorities.keys.max
271
+ jobs.count >= priorities[lowest_priority]
272
+ end
268
273
  end
269
274
  end
@@ -40,8 +40,11 @@ module Que
40
40
  where(QUALIFIED_TABLE[:data].pg_jsonb.contains(JSON.dump(tags: [tag])))
41
41
  end
42
42
 
43
- def by_args(*args)
44
- where(QUALIFIED_TABLE[:args].pg_jsonb.contains(JSON.dump(args)))
43
+ def by_args(*args, **kwargs)
44
+ where(
45
+ QUALIFIED_TABLE[:args].pg_jsonb.contains(JSON.dump(args)) &
46
+ QUALIFIED_TABLE[:kwargs].pg_jsonb.contains(JSON.dump(kwargs))
47
+ )
45
48
  end
46
49
  end
47
50
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Temporary module allowing ruby2 keyword args to be extracted from an *args splat
4
+ # Allows us to ensure consistent behaviour when running on ruby 2 vs ruby 3
5
+ # We can remove this if/when we drop support for ruby 2
6
+
7
+ require 'json'
8
+
9
+ module Que
10
+ module Utils
11
+ module Ruby2Keywords
12
+ def split_out_ruby2_keywords(args)
13
+ return [args, {}] unless args.last&.is_a?(Hash) && Hash.ruby2_keywords_hash?(args.last)
14
+
15
+ [args[0..-2], args.last]
16
+ end
17
+ end
18
+ end
19
+ end
data/lib/que/version.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Que
4
- VERSION = '1.3.0'
4
+ VERSION = '2.0.0'
5
5
 
6
6
  def self.job_schema_version
7
- 1
7
+ 2
8
8
  end
9
9
  end
data/lib/que/worker.rb CHANGED
@@ -125,7 +125,7 @@ module Que
125
125
  log_message[:event] = :job_worked
126
126
  end
127
127
 
128
- Que.log(log_message)
128
+ Que.log(**log_message)
129
129
  end
130
130
 
131
131
  instance
data/lib/que.rb CHANGED
@@ -29,8 +29,11 @@ module Que
29
29
  require_relative 'que/utils/logging'
30
30
  require_relative 'que/utils/middleware'
31
31
  require_relative 'que/utils/queue_management'
32
+ require_relative 'que/utils/ruby2_keywords'
32
33
  require_relative 'que/utils/transactions'
33
34
 
35
+ require_relative 'que/version'
36
+
34
37
  require_relative 'que/connection'
35
38
  require_relative 'que/connection_pool'
36
39
  require_relative 'que/job_methods'
@@ -41,7 +44,6 @@ module Que
41
44
  require_relative 'que/migrations'
42
45
  require_relative 'que/poller'
43
46
  require_relative 'que/result_queue'
44
- require_relative 'que/version'
45
47
  require_relative 'que/worker'
46
48
 
47
49
  class << self
@@ -60,6 +62,7 @@ module Que
60
62
  include Utils::Logging
61
63
  include Utils::Middleware
62
64
  include Utils::QueueManagement
65
+ include Utils::Ruby2Keywords
63
66
  include Utils::Transactions
64
67
 
65
68
  extend Forwardable
data/que.gemspec CHANGED
@@ -13,6 +13,8 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = 'https://github.com/que-rb/que'
14
14
  spec.license = 'MIT'
15
15
 
16
+ spec.required_ruby_version = '>= 2.7.0'
17
+
16
18
  files_to_exclude = [
17
19
  /\A\.circleci/,
18
20
  /\AGemfile/,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: que
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Hanks
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-25 00:00:00.000000000 Z
11
+ date: 2022-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -34,6 +34,7 @@ extra_rdoc_files: []
34
34
  files:
35
35
  - ".github/workflows/tests.yml"
36
36
  - ".gitignore"
37
+ - ".ruby-version"
37
38
  - CHANGELOG.md
38
39
  - Dockerfile
39
40
  - LICENSE.txt
@@ -71,6 +72,8 @@ files:
71
72
  - lib/que/migrations/4/up.sql
72
73
  - lib/que/migrations/5/down.sql
73
74
  - lib/que/migrations/5/up.sql
75
+ - lib/que/migrations/6/down.sql
76
+ - lib/que/migrations/6/up.sql
74
77
  - lib/que/poller.rb
75
78
  - lib/que/rails/railtie.rb
76
79
  - lib/que/result_queue.rb
@@ -84,6 +87,7 @@ files:
84
87
  - lib/que/utils/logging.rb
85
88
  - lib/que/utils/middleware.rb
86
89
  - lib/que/utils/queue_management.rb
90
+ - lib/que/utils/ruby2_keywords.rb
87
91
  - lib/que/utils/transactions.rb
88
92
  - lib/que/version.rb
89
93
  - lib/que/worker.rb
@@ -102,14 +106,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
102
106
  requirements:
103
107
  - - ">="
104
108
  - !ruby/object:Gem::Version
105
- version: '0'
109
+ version: 2.7.0
106
110
  required_rubygems_version: !ruby/object:Gem::Requirement
107
111
  requirements:
108
112
  - - ">="
109
113
  - !ruby/object:Gem::Version
110
114
  version: '0'
111
115
  requirements: []
112
- rubygems_version: 3.3.6
116
+ rubygems_version: 3.3.7
113
117
  signing_key:
114
118
  specification_version: 4
115
119
  summary: A PostgreSQL-based Job Queue