exekutor 0.1.0 → 0.1.2
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
- checksums.yaml.gz.sig +2 -3
- data/exe/exekutor +2 -2
- data/lib/active_job/queue_adapters/exekutor_adapter.rb +2 -1
- data/lib/exekutor/asynchronous.rb +143 -75
- data/lib/exekutor/cleanup.rb +27 -28
- data/lib/exekutor/configuration.rb +102 -48
- data/lib/exekutor/hook.rb +15 -11
- data/lib/exekutor/info/worker.rb +3 -3
- data/lib/exekutor/internal/base_record.rb +2 -1
- data/lib/exekutor/internal/callbacks.rb +55 -35
- data/lib/exekutor/internal/cli/app.rb +33 -23
- data/lib/exekutor/internal/cli/application_loader.rb +17 -6
- data/lib/exekutor/internal/cli/cleanup.rb +54 -40
- data/lib/exekutor/internal/cli/daemon.rb +9 -11
- data/lib/exekutor/internal/cli/default_option_value.rb +3 -1
- data/lib/exekutor/internal/cli/info.rb +117 -84
- data/lib/exekutor/internal/cli/manager.rb +234 -123
- data/lib/exekutor/internal/configuration_builder.rb +49 -30
- data/lib/exekutor/internal/database_connection.rb +6 -0
- data/lib/exekutor/internal/executable.rb +12 -7
- data/lib/exekutor/internal/executor.rb +50 -21
- data/lib/exekutor/internal/hooks.rb +11 -8
- data/lib/exekutor/internal/listener.rb +85 -43
- data/lib/exekutor/internal/logger.rb +29 -10
- data/lib/exekutor/internal/provider.rb +96 -77
- data/lib/exekutor/internal/reserver.rb +66 -19
- data/lib/exekutor/internal/status_server.rb +87 -54
- data/lib/exekutor/job.rb +1 -1
- data/lib/exekutor/job_error.rb +1 -1
- data/lib/exekutor/job_options.rb +22 -13
- data/lib/exekutor/plugins/appsignal.rb +7 -5
- data/lib/exekutor/plugins.rb +8 -4
- data/lib/exekutor/queue.rb +69 -30
- data/lib/exekutor/version.rb +1 -1
- data/lib/exekutor/worker.rb +89 -48
- data/lib/exekutor.rb +2 -2
- data/lib/generators/exekutor/configuration_generator.rb +11 -6
- data/lib/generators/exekutor/install_generator.rb +24 -15
- data/lib/generators/exekutor/templates/install/functions/exekutor_broadcast_job_enqueued.sql +10 -0
- data/lib/generators/exekutor/templates/install/functions/exekutor_requeue_orphaned_jobs.sql +11 -0
- data/lib/generators/exekutor/templates/install/migrations/create_exekutor_schema.rb.erb +23 -22
- data/lib/generators/exekutor/templates/install/triggers/exekutor_broadcast_job_enqueued.sql +7 -0
- data/lib/generators/exekutor/templates/install/triggers/exekutor_requeue_orphaned_jobs.sql +5 -0
- data.tar.gz.sig +0 -0
- metadata +67 -23
- metadata.gz.sig +0 -0
- data/lib/generators/exekutor/templates/install/functions/job_notifier.sql +0 -7
- data/lib/generators/exekutor/templates/install/functions/requeue_orphaned_jobs.sql +0 -7
- data/lib/generators/exekutor/templates/install/triggers/notify_workers.sql +0 -6
- data/lib/generators/exekutor/templates/install/triggers/requeue_orphaned_jobs.sql +0 -5
data/lib/exekutor/worker.rb
CHANGED
@@ -23,64 +23,43 @@ module Exekutor
|
|
23
23
|
# @option config [Array<String>] :queues the queues to work on
|
24
24
|
# @option config [Integer] :min_threads the minimum number of execution threads that should be active
|
25
25
|
# @option config [Integer] :max_threads the maximum number of execution threads that may be active
|
26
|
-
# @option config [
|
27
|
-
#
|
26
|
+
# @option config [ActiveSupport::Duration] :max_thread_idletime the maximum duration a thread may be idle before
|
27
|
+
# being stopped
|
28
|
+
# @option config [ActiveSupport::Duration] :polling_interval the polling interval
|
28
29
|
# @option config [Float] :poling_jitter the polling jitter
|
29
30
|
# @option config [Boolean] :set_db_connection_name whether the DB connection name should be set
|
30
|
-
# @option config [Integer,Boolean] :wait_for_termination how long the worker should wait on jobs to be completed
|
31
|
+
# @option config [Integer,Boolean] :wait_for_termination how long the worker should wait on jobs to be completed
|
32
|
+
# before exiting
|
31
33
|
# @option config [Integer] :status_server_port the port to run the status server on
|
32
34
|
# @option config [String] :status_server_handler The name of the rack handler to use for the status server
|
33
|
-
# @option config [
|
35
|
+
# @option config [ActiveSupport::Duration] :healthcheck_timeout The timeout of a worker in minutes before the
|
36
|
+
# healthcheck server deems it as down
|
34
37
|
def initialize(config = {})
|
35
38
|
super()
|
36
39
|
@config = config
|
37
40
|
@record = create_record!
|
38
41
|
|
39
|
-
|
40
|
-
@executor = Internal::Executor.new(**config.slice(:min_threads, :max_threads, :max_thread_idletime,
|
41
|
-
:delete_completed_jobs, :delete_discarded_jobs,
|
42
|
-
:delete_failed_jobs))
|
42
|
+
provider_pool = create_provider_pool(config)
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
provider_threads += 1 if config[:status_server_port].to_i > 0
|
47
|
-
|
48
|
-
provider_pool = Concurrent::FixedThreadPool.new provider_threads, max_queue: provider_threads,
|
49
|
-
name: "exekutor-provider"
|
50
|
-
|
51
|
-
@provider = Internal::Provider.new reserver: @reserver, executor: @executor, pool: provider_pool,
|
52
|
-
**provider_options(config)
|
44
|
+
@executor = create_executor(config)
|
45
|
+
@provider = create_provider(config, @executor, provider_pool)
|
53
46
|
|
54
47
|
@executables = [@executor, @provider]
|
55
|
-
if config.fetch(:enable_listener, true)
|
56
|
-
|
57
|
-
**listener_options(config)
|
58
|
-
@executables << listener
|
59
|
-
end
|
60
|
-
if config[:status_server_port].to_i > 0
|
61
|
-
server = Internal::StatusServer.new worker: self, pool: provider_pool, **status_server_options(config)
|
62
|
-
@executables << server
|
63
|
-
end
|
48
|
+
create_listener(provider_pool, config) if config.fetch(:enable_listener, true)
|
49
|
+
create_status_server(provider_pool, config) if config[:status_server_port].to_i.positive?
|
64
50
|
@executables.freeze
|
65
|
-
|
66
|
-
@executor.after_execute(@record) do |_job, worker_info|
|
67
|
-
worker_info.heartbeat! rescue nil
|
68
|
-
@provider.poll if @provider.running?
|
69
|
-
end
|
70
|
-
@provider.on_queue_empty(@record) do |worker_info|
|
71
|
-
worker_info.heartbeat! rescue nil
|
72
|
-
@executor.prune_pool
|
73
|
-
end
|
74
51
|
end
|
75
52
|
|
76
53
|
# Starts the worker. Does nothing if the worker has already started.
|
77
54
|
# @return [Boolean] whether the worker was started
|
78
55
|
def start
|
79
56
|
return false unless compare_and_set_state(:pending, :started)
|
57
|
+
|
80
58
|
Internal::Hooks.run :startup, self do
|
81
59
|
@executables.each(&:start)
|
82
60
|
@record.update(status: "r")
|
83
61
|
end
|
62
|
+
|
84
63
|
true
|
85
64
|
end
|
86
65
|
|
@@ -89,22 +68,21 @@ module Exekutor
|
|
89
68
|
# @return true
|
90
69
|
def stop
|
91
70
|
Internal::Hooks.run :shutdown, self do
|
92
|
-
|
71
|
+
self.state = :stopped
|
93
72
|
unless @record.destroyed?
|
94
73
|
begin
|
95
74
|
@record.update(status: "s")
|
96
|
-
rescue
|
97
|
-
#ignored
|
75
|
+
rescue StandardError
|
76
|
+
# ignored
|
98
77
|
end
|
99
78
|
end
|
100
79
|
@executables.reverse_each(&:stop)
|
101
|
-
|
102
|
-
wait_for_termination @config[:wait_for_termination] if @config[:wait_for_termination]
|
80
|
+
wait_for_termination @config[:wait_for_termination]
|
103
81
|
|
104
82
|
begin
|
105
83
|
@record.destroy
|
106
|
-
rescue
|
107
|
-
#ignored
|
84
|
+
rescue StandardError
|
85
|
+
# ignored
|
108
86
|
end
|
109
87
|
@stop_event&.set if defined?(@stop_event)
|
110
88
|
end
|
@@ -121,8 +99,8 @@ module Exekutor
|
|
121
99
|
@executor.kill
|
122
100
|
begin
|
123
101
|
@record.destroy
|
124
|
-
rescue
|
125
|
-
#ignored
|
102
|
+
rescue StandardError
|
103
|
+
# ignored
|
126
104
|
end
|
127
105
|
true
|
128
106
|
end
|
@@ -138,7 +116,7 @@ module Exekutor
|
|
138
116
|
|
139
117
|
# Reserves and executes jobs.
|
140
118
|
def reserve_jobs
|
141
|
-
@provider.poll
|
119
|
+
@provider.poll if @provider&.running?
|
142
120
|
end
|
143
121
|
|
144
122
|
# The worker ID.
|
@@ -146,24 +124,76 @@ module Exekutor
|
|
146
124
|
@record.id
|
147
125
|
end
|
148
126
|
|
127
|
+
# @return [Time,nil] The timestamp of the last heartbeat. The timestamp is truncated to whole minutes.
|
149
128
|
def last_heartbeat
|
150
129
|
@record.last_heartbeat_at
|
151
130
|
end
|
152
131
|
|
132
|
+
# Returns the thread usage for this worker. The resulting hash will contain the following key-value pairs:
|
133
|
+
# - +:minimum+, (Integer) the minimum number of threads that should be active;
|
134
|
+
# - +:maximum+, (Integer) the maximum number of threads may should be active;
|
135
|
+
# - +:available+, (Integer) the number of threads that are available to execute new jobs;
|
136
|
+
# - +:usage_percent+, (Float, 0-100) the percentage of workers that are currently busy executing jobs.
|
137
|
+
# @return [Hash] the thread usage
|
153
138
|
def thread_stats
|
154
139
|
available = @executor.available_threads
|
140
|
+
usage_percent = (((100 - (available * 100.0 / @executor.maximum_threads))).round(2) if @executor.running?)
|
155
141
|
{
|
156
142
|
minimum: @executor.minimum_threads,
|
157
143
|
maximum: @executor.maximum_threads,
|
158
144
|
available: available,
|
159
|
-
usage_percent:
|
160
|
-
((1 - (available.to_f / @executor.maximum_threads)) * 100).round(2)
|
161
|
-
end
|
145
|
+
usage_percent: usage_percent
|
162
146
|
}
|
163
147
|
end
|
164
148
|
|
165
149
|
private
|
166
150
|
|
151
|
+
def create_provider_pool(config)
|
152
|
+
provider_threads = 1
|
153
|
+
provider_threads += 1 if config.fetch(:enable_listener, true)
|
154
|
+
provider_threads += 1 if config[:status_server_port].to_i.positive?
|
155
|
+
|
156
|
+
Concurrent::FixedThreadPool.new provider_threads, max_queue: provider_threads, name: "exekutor-provider"
|
157
|
+
end
|
158
|
+
|
159
|
+
def create_executor(worker_options)
|
160
|
+
executor = Internal::Executor.new(**executor_options(worker_options))
|
161
|
+
|
162
|
+
executor.after_execute(@record) do |_job, worker_info|
|
163
|
+
begin
|
164
|
+
worker_info.heartbeat!
|
165
|
+
rescue StandardError
|
166
|
+
# ignored
|
167
|
+
end
|
168
|
+
reserve_jobs
|
169
|
+
end
|
170
|
+
|
171
|
+
executor
|
172
|
+
end
|
173
|
+
|
174
|
+
def executor_options(worker_options)
|
175
|
+
worker_options.slice(:min_threads, :max_threads, :max_thread_idletime,
|
176
|
+
:delete_completed_jobs, :delete_discarded_jobs,
|
177
|
+
:delete_failed_jobs)
|
178
|
+
end
|
179
|
+
|
180
|
+
def create_provider(worker_options, executor, thread_pool)
|
181
|
+
@reserver = Internal::Reserver.new @record.id, **worker_options.slice(:queues, :min_priority, :max_priority)
|
182
|
+
provider = Internal::Provider.new reserver: @reserver, executor: executor, pool: thread_pool,
|
183
|
+
**provider_options(worker_options)
|
184
|
+
|
185
|
+
provider.on_queue_empty(@record, executor) do |worker_info, thr_executor|
|
186
|
+
begin
|
187
|
+
worker_info.heartbeat!
|
188
|
+
rescue StandardError
|
189
|
+
# ignored
|
190
|
+
end
|
191
|
+
thr_executor.prune_pool
|
192
|
+
end
|
193
|
+
|
194
|
+
provider
|
195
|
+
end
|
196
|
+
|
167
197
|
def provider_options(worker_options)
|
168
198
|
worker_options.slice(:polling_interval, :polling_jitter).transform_keys do |key|
|
169
199
|
case key
|
@@ -175,10 +205,21 @@ module Exekutor
|
|
175
205
|
end
|
176
206
|
end
|
177
207
|
|
208
|
+
def create_listener(provider_pool, config)
|
209
|
+
listener = Internal::Listener.new worker_id: @record.id, provider: @provider, pool: provider_pool,
|
210
|
+
**listener_options(config)
|
211
|
+
@executables << listener
|
212
|
+
end
|
213
|
+
|
178
214
|
def listener_options(worker_options)
|
179
215
|
worker_options.slice(:queues, :set_db_connection_name)
|
180
216
|
end
|
181
217
|
|
218
|
+
def create_status_server(provider_pool, config)
|
219
|
+
server = Internal::StatusServer.new worker: self, pool: provider_pool, **status_server_options(config)
|
220
|
+
@executables << server
|
221
|
+
end
|
222
|
+
|
182
223
|
def status_server_options(worker_options)
|
183
224
|
worker_options.slice(:status_server_port, :status_server_handler, :healthcheck_timeout).transform_keys do |key|
|
184
225
|
case key
|
data/lib/exekutor.rb
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
require_relative "exekutor/version"
|
4
4
|
|
5
|
+
# The Exekutor namespace
|
5
6
|
module Exekutor
|
6
|
-
|
7
7
|
# Base error class
|
8
8
|
class Error < StandardError; end
|
9
9
|
|
@@ -45,5 +45,5 @@ ActiveSupport.on_load(:active_record) do
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
Exekutor.private_constant
|
48
|
+
Exekutor.private_constant :Internal
|
49
49
|
ActiveSupport.run_load_hooks(:exekutor, Exekutor)
|
@@ -1,18 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
require "rails/generators"
|
3
4
|
|
4
5
|
module Exekutor
|
6
|
+
# Generates a YAML configuration file
|
5
7
|
class ConfigurationGenerator < Rails::Generators::Base
|
6
|
-
desc
|
8
|
+
desc "Create YAML configuration for Exekutor"
|
7
9
|
|
8
|
-
class_option :identifier, type: :string, aliases: %i
|
10
|
+
class_option :identifier, type: :string, aliases: %i[--id], desc: "The worker identifier"
|
9
11
|
|
12
|
+
# Creates the configuration file at +config/exekutor.yml+. Uses the current worker configuration as the base.
|
10
13
|
def create_configuration_file
|
11
14
|
config = { queues: %w[queues to watch] }.merge(Exekutor.config.worker_options)
|
12
|
-
config[:status_port] =
|
15
|
+
config[:status_port] = 12_677
|
13
16
|
config[:set_db_connection_name] = true
|
14
17
|
config[:wait_for_termination] = 120
|
15
|
-
|
18
|
+
|
19
|
+
filename = "config/exekutor#{".#{options[:identifier]}" if options[:identifier]}.yml"
|
20
|
+
create_file filename, { "exekutor" => config.stringify_keys }.to_yaml
|
16
21
|
end
|
17
22
|
end
|
18
|
-
end
|
23
|
+
end
|
@@ -1,29 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
require "rails/generators/active_record"
|
4
5
|
|
5
6
|
module Exekutor
|
7
|
+
# Generates the initializer and migrations
|
6
8
|
class InstallGenerator < Rails::Generators::Base
|
7
9
|
include ActiveRecord::Generators::Migration
|
8
|
-
desc
|
10
|
+
desc "Create migrations for Exekutor"
|
9
11
|
|
10
|
-
TEMPLATE_DIR = File.join(__dir__,
|
12
|
+
TEMPLATE_DIR = File.join(__dir__, "templates/install")
|
11
13
|
source_paths << TEMPLATE_DIR
|
12
14
|
|
15
|
+
# Creates the initializer file at +config/initializers/exekutor.rb+
|
13
16
|
def create_initializer_file
|
14
|
-
template
|
17
|
+
template "initializers/exekutor.rb.erb", "config/initializers/exekutor.rb"
|
15
18
|
end
|
16
19
|
|
20
|
+
# Creates the migration file in the migrations folder
|
17
21
|
def create_migration_file
|
18
|
-
migration_template
|
19
|
-
|
20
|
-
|
21
|
-
copy_file "functions/#{function}.sql", Fx::Definition.new(name: function, version: 1).full_path
|
22
|
-
end
|
23
|
-
%w(notify_workers requeue_orphaned_jobs).each do |trigger|
|
24
|
-
copy_file "triggers/#{trigger}.sql", Fx::Definition.new(name: trigger, version: 1, type: "trigger").full_path
|
25
|
-
end
|
26
|
-
end
|
22
|
+
migration_template "migrations/create_exekutor_schema.rb.erb",
|
23
|
+
File.join(db_migrate_path, "create_exekutor_schema.rb")
|
24
|
+
create_fx_files
|
27
25
|
end
|
28
26
|
|
29
27
|
protected
|
@@ -39,5 +37,16 @@ module Exekutor
|
|
39
37
|
def trigger_sql(name)
|
40
38
|
File.read File.join(TEMPLATE_DIR, "triggers/#{name}.sql")
|
41
39
|
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def create_fx_files
|
44
|
+
return unless defined?(Fx)
|
45
|
+
|
46
|
+
%w[exekutor_broadcast_job_enqueued exekutor_requeue_orphaned_jobs].each do |name|
|
47
|
+
copy_file "functions/#{name}.sql", Fx::Definition.new(name: name, version: 1).full_path
|
48
|
+
copy_file "triggers/#{name}.sql", Fx::Definition.new(name: name, version: 1, type: "trigger").full_path
|
49
|
+
end
|
50
|
+
end
|
42
51
|
end
|
43
|
-
end
|
52
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
CREATE
|
2
|
+
OR REPLACE FUNCTION exekutor_broadcast_job_enqueued() RETURNS TRIGGER AS $$
|
3
|
+
BEGIN
|
4
|
+
PERFORM
|
5
|
+
pg_notify('exekutor::job_enqueued',
|
6
|
+
CONCAT('id:', NEW.id,';q:', NEW.queue,';p:', NEW.priority, ';t:', extract ('epoch' from NEW.scheduled_at)));
|
7
|
+
RETURN NULL;
|
8
|
+
END;
|
9
|
+
$$
|
10
|
+
LANGUAGE plpgsql
|
@@ -7,20 +7,20 @@ class CreateExekutorSchema < ActiveRecord::Migration[<%= migration_version %>]
|
|
7
7
|
|
8
8
|
t.jsonb :info, null: false
|
9
9
|
|
10
|
-
t.datetime :
|
11
|
-
t.datetime :last_heartbeat_at, null: false, default: -> {
|
10
|
+
t.datetime :started_at, null: false, default: -> { "now()" }
|
11
|
+
t.datetime :last_heartbeat_at, null: false, default: -> { "now()" }
|
12
12
|
|
13
|
-
t.column :status, :char, null: false, default:
|
13
|
+
t.column :status, :char, null: false, default: "i"
|
14
14
|
|
15
15
|
t.index [:hostname, :pid], unique: true
|
16
16
|
end
|
17
17
|
|
18
18
|
create_table :exekutor_jobs, id: :uuid do |t|
|
19
19
|
# Worker options
|
20
|
-
t.string :queue, null: false, default:
|
21
|
-
t.integer :priority, null: false, default:
|
22
|
-
t.datetime :enqueued_at, null: false, default: -> {
|
23
|
-
t.datetime :scheduled_at, null: false, default: -> {
|
20
|
+
t.string :queue, null: false, default: "default", limit: 200, index: true
|
21
|
+
t.integer :priority, null: false, default: 16_383, limit: 2
|
22
|
+
t.datetime :enqueued_at, null: false, default: -> { "now()" }
|
23
|
+
t.datetime :scheduled_at, null: false, default: -> { "now()" }
|
24
24
|
|
25
25
|
# Job options
|
26
26
|
t.uuid :active_job_id, null: false, index: true
|
@@ -28,53 +28,54 @@ class CreateExekutorSchema < ActiveRecord::Migration[<%= migration_version %>]
|
|
28
28
|
t.jsonb :options
|
29
29
|
|
30
30
|
# Execution options
|
31
|
-
t.column :status, :char, index: true, null: false, default:
|
31
|
+
t.column :status, :char, index: true, null: false, default: "p"
|
32
32
|
t.float :runtime
|
33
33
|
t.references :worker, type: :uuid, foreign_key: { to_table: :exekutor_workers, on_delete: :nullify }
|
34
34
|
|
35
|
-
t.index [:priority, :scheduled_at, :enqueued_at], where: %
|
35
|
+
t.index [:priority, :scheduled_at, :enqueued_at], where: %q("status"='p'),
|
36
|
+
name: :index_exekutor_jobs_on_dequeue_order
|
36
37
|
end
|
37
38
|
|
38
39
|
create_table :exekutor_job_errors, id: :uuid do |t|
|
39
40
|
t.references :job, type: :uuid, null: false, foreign_key: { to_table: :exekutor_jobs, on_delete: :cascade }
|
40
|
-
t.datetime :created_at, null: false, default: -> {
|
41
|
+
t.datetime :created_at, null: false, default: -> { "now()" }
|
41
42
|
t.jsonb :error, null: false
|
42
43
|
end
|
43
44
|
<% if defined? Fx %>
|
44
|
-
create_function :
|
45
|
-
create_trigger :
|
45
|
+
create_function :exekutor_broadcast_job_enqueued
|
46
|
+
create_trigger :exekutor_broadcast_job_enqueued, on: :exekutor_jobs
|
46
47
|
|
47
|
-
create_function :
|
48
|
-
create_trigger :
|
48
|
+
create_function :exekutor_requeue_orphaned_jobs
|
49
|
+
create_trigger :exekutor_requeue_orphaned_jobs, on: :exekutor_workers
|
49
50
|
<% else %>
|
50
51
|
reversible do |direction|
|
51
52
|
direction.up do
|
52
53
|
execute <<~SQL
|
53
|
-
<%= function_sql "
|
54
|
+
<%= function_sql "exekutor_broadcast_job_enqueued" %>
|
54
55
|
SQL
|
55
56
|
execute <<~SQL
|
56
|
-
<%= trigger_sql "
|
57
|
+
<%= trigger_sql "exekutor_broadcast_job_enqueued" %>
|
57
58
|
SQL
|
58
59
|
|
59
60
|
execute <<~SQL
|
60
|
-
<%= function_sql "
|
61
|
+
<%= function_sql "exekutor_requeue_orphaned_jobs" %>
|
61
62
|
SQL
|
62
63
|
execute <<~SQL
|
63
|
-
<%= trigger_sql "
|
64
|
+
<%= trigger_sql "exekutor_requeue_orphaned_jobs" %>
|
64
65
|
SQL
|
65
66
|
end
|
66
67
|
direction.down do
|
67
68
|
execute <<~SQL
|
68
|
-
DROP TRIGGER
|
69
|
+
DROP TRIGGER exekutor_requeue_orphaned_jobs ON exekutor_workers
|
69
70
|
SQL
|
70
71
|
execute <<~SQL
|
71
|
-
DROP FUNCTION
|
72
|
+
DROP FUNCTION exekutor_requeue_orphaned_jobs
|
72
73
|
SQL
|
73
74
|
execute <<~SQL
|
74
|
-
DROP TRIGGER
|
75
|
+
DROP TRIGGER exekutor_broadcast_job_enqueued ON exekutor_jobs
|
75
76
|
SQL
|
76
77
|
execute <<~SQL
|
77
|
-
DROP FUNCTION
|
78
|
+
DROP FUNCTION exekutor_broadcast_job_enqueued
|
78
79
|
SQL
|
79
80
|
end
|
80
81
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exekutor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roy
|
@@ -34,7 +34,7 @@ cert_chain:
|
|
34
34
|
LMMHpsz0vpxVqcs8USL9494hQUWRVlYd1F2PJeWtdKi0bU8dCduphJd8cTvCtS2l
|
35
35
|
CAY756btGBLeeWMBZ/DRMj1Cz3ifI9DV+KHqXg==
|
36
36
|
-----END CERTIFICATE-----
|
37
|
-
date: 2023-
|
37
|
+
date: 2023-12-19 00:00:00.000000000 Z
|
38
38
|
dependencies:
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: activejob
|
@@ -152,20 +152,6 @@ dependencies:
|
|
152
152
|
- - "~>"
|
153
153
|
- !ruby/object:Gem::Version
|
154
154
|
version: '3.0'
|
155
|
-
- !ruby/object:Gem::Dependency
|
156
|
-
name: brakeman
|
157
|
-
requirement: !ruby/object:Gem::Requirement
|
158
|
-
requirements:
|
159
|
-
- - "~>"
|
160
|
-
- !ruby/object:Gem::Version
|
161
|
-
version: '5.4'
|
162
|
-
type: :development
|
163
|
-
prerelease: false
|
164
|
-
version_requirements: !ruby/object:Gem::Requirement
|
165
|
-
requirements:
|
166
|
-
- - "~>"
|
167
|
-
- !ruby/object:Gem::Version
|
168
|
-
version: '5.4'
|
169
155
|
- !ruby/object:Gem::Dependency
|
170
156
|
name: combustion
|
171
157
|
requirement: !ruby/object:Gem::Requirement
|
@@ -264,6 +250,48 @@ dependencies:
|
|
264
250
|
- - "~>"
|
265
251
|
- !ruby/object:Gem::Version
|
266
252
|
version: '1.21'
|
253
|
+
- !ruby/object:Gem::Dependency
|
254
|
+
name: rubocop-minitest
|
255
|
+
requirement: !ruby/object:Gem::Requirement
|
256
|
+
requirements:
|
257
|
+
- - "~>"
|
258
|
+
- !ruby/object:Gem::Version
|
259
|
+
version: '0.29'
|
260
|
+
type: :development
|
261
|
+
prerelease: false
|
262
|
+
version_requirements: !ruby/object:Gem::Requirement
|
263
|
+
requirements:
|
264
|
+
- - "~>"
|
265
|
+
- !ruby/object:Gem::Version
|
266
|
+
version: '0.29'
|
267
|
+
- !ruby/object:Gem::Dependency
|
268
|
+
name: rubocop-performance
|
269
|
+
requirement: !ruby/object:Gem::Requirement
|
270
|
+
requirements:
|
271
|
+
- - "~>"
|
272
|
+
- !ruby/object:Gem::Version
|
273
|
+
version: '1.16'
|
274
|
+
type: :development
|
275
|
+
prerelease: false
|
276
|
+
version_requirements: !ruby/object:Gem::Requirement
|
277
|
+
requirements:
|
278
|
+
- - "~>"
|
279
|
+
- !ruby/object:Gem::Version
|
280
|
+
version: '1.16'
|
281
|
+
- !ruby/object:Gem::Dependency
|
282
|
+
name: rubocop-rails
|
283
|
+
requirement: !ruby/object:Gem::Requirement
|
284
|
+
requirements:
|
285
|
+
- - "~>"
|
286
|
+
- !ruby/object:Gem::Version
|
287
|
+
version: '2.18'
|
288
|
+
type: :development
|
289
|
+
prerelease: false
|
290
|
+
version_requirements: !ruby/object:Gem::Requirement
|
291
|
+
requirements:
|
292
|
+
- - "~>"
|
293
|
+
- !ruby/object:Gem::Version
|
294
|
+
version: '2.18'
|
267
295
|
- !ruby/object:Gem::Dependency
|
268
296
|
name: simplecov
|
269
297
|
requirement: !ruby/object:Gem::Requirement
|
@@ -292,6 +320,20 @@ dependencies:
|
|
292
320
|
- - "~>"
|
293
321
|
- !ruby/object:Gem::Version
|
294
322
|
version: '0.9'
|
323
|
+
- !ruby/object:Gem::Dependency
|
324
|
+
name: webrick
|
325
|
+
requirement: !ruby/object:Gem::Requirement
|
326
|
+
requirements:
|
327
|
+
- - "~>"
|
328
|
+
- !ruby/object:Gem::Version
|
329
|
+
version: '1.6'
|
330
|
+
type: :development
|
331
|
+
prerelease: false
|
332
|
+
version_requirements: !ruby/object:Gem::Requirement
|
333
|
+
requirements:
|
334
|
+
- - "~>"
|
335
|
+
- !ruby/object:Gem::Version
|
336
|
+
version: '1.6'
|
295
337
|
- !ruby/object:Gem::Dependency
|
296
338
|
name: yard
|
297
339
|
requirement: !ruby/object:Gem::Requirement
|
@@ -320,8 +362,9 @@ dependencies:
|
|
320
362
|
- - "~>"
|
321
363
|
- !ruby/object:Gem::Version
|
322
364
|
version: '0.0'
|
323
|
-
description:
|
324
|
-
for jobs and `FOR UPDATE SKIP LOCKED` to
|
365
|
+
description: |
|
366
|
+
PostgreSQL backed active job adapter which uses `LISTEN/NOTIFY` to listen for jobs and `FOR UPDATE SKIP LOCKED` to
|
367
|
+
reserve jobs.
|
325
368
|
email:
|
326
369
|
- roy@devdicated.com
|
327
370
|
executables:
|
@@ -367,12 +410,12 @@ files:
|
|
367
410
|
- lib/exekutor/worker.rb
|
368
411
|
- lib/generators/exekutor/configuration_generator.rb
|
369
412
|
- lib/generators/exekutor/install_generator.rb
|
370
|
-
- lib/generators/exekutor/templates/install/functions/
|
371
|
-
- lib/generators/exekutor/templates/install/functions/
|
413
|
+
- lib/generators/exekutor/templates/install/functions/exekutor_broadcast_job_enqueued.sql
|
414
|
+
- lib/generators/exekutor/templates/install/functions/exekutor_requeue_orphaned_jobs.sql
|
372
415
|
- lib/generators/exekutor/templates/install/initializers/exekutor.rb.erb
|
373
416
|
- lib/generators/exekutor/templates/install/migrations/create_exekutor_schema.rb.erb
|
374
|
-
- lib/generators/exekutor/templates/install/triggers/
|
375
|
-
- lib/generators/exekutor/templates/install/triggers/
|
417
|
+
- lib/generators/exekutor/templates/install/triggers/exekutor_broadcast_job_enqueued.sql
|
418
|
+
- lib/generators/exekutor/templates/install/triggers/exekutor_requeue_orphaned_jobs.sql
|
376
419
|
homepage: https://github.com/devdicated/exekutor
|
377
420
|
licenses:
|
378
421
|
- MIT
|
@@ -381,6 +424,7 @@ metadata:
|
|
381
424
|
source_code_uri: https://github.com/devdicated/exekutor
|
382
425
|
changelog_uri: https://github.com/devdicated/exekutor/blob/master/CHANGELOG.md
|
383
426
|
allowed_push_host: https://rubygems.org
|
427
|
+
rubygems_mfa_required: 'true'
|
384
428
|
post_install_message:
|
385
429
|
rdoc_options: []
|
386
430
|
require_paths:
|
@@ -396,7 +440,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
396
440
|
- !ruby/object:Gem::Version
|
397
441
|
version: '0'
|
398
442
|
requirements: []
|
399
|
-
rubygems_version: 3.
|
443
|
+
rubygems_version: 3.4.13
|
400
444
|
signing_key:
|
401
445
|
specification_version: 4
|
402
446
|
summary: ActiveJob adapter with PostgreSQL backend.
|
metadata.gz.sig
CHANGED
Binary file
|