exekutor 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -3
  3. data/exe/exekutor +2 -2
  4. data/lib/active_job/queue_adapters/exekutor_adapter.rb +2 -1
  5. data/lib/exekutor/asynchronous.rb +143 -75
  6. data/lib/exekutor/cleanup.rb +27 -28
  7. data/lib/exekutor/configuration.rb +102 -48
  8. data/lib/exekutor/hook.rb +15 -11
  9. data/lib/exekutor/info/worker.rb +3 -3
  10. data/lib/exekutor/internal/base_record.rb +2 -1
  11. data/lib/exekutor/internal/callbacks.rb +55 -35
  12. data/lib/exekutor/internal/cli/app.rb +33 -23
  13. data/lib/exekutor/internal/cli/application_loader.rb +17 -6
  14. data/lib/exekutor/internal/cli/cleanup.rb +54 -40
  15. data/lib/exekutor/internal/cli/daemon.rb +9 -11
  16. data/lib/exekutor/internal/cli/default_option_value.rb +3 -1
  17. data/lib/exekutor/internal/cli/info.rb +117 -84
  18. data/lib/exekutor/internal/cli/manager.rb +234 -123
  19. data/lib/exekutor/internal/configuration_builder.rb +49 -30
  20. data/lib/exekutor/internal/database_connection.rb +6 -0
  21. data/lib/exekutor/internal/executable.rb +12 -7
  22. data/lib/exekutor/internal/executor.rb +50 -21
  23. data/lib/exekutor/internal/hooks.rb +11 -8
  24. data/lib/exekutor/internal/listener.rb +85 -43
  25. data/lib/exekutor/internal/logger.rb +29 -10
  26. data/lib/exekutor/internal/provider.rb +96 -77
  27. data/lib/exekutor/internal/reserver.rb +66 -19
  28. data/lib/exekutor/internal/status_server.rb +87 -54
  29. data/lib/exekutor/job.rb +1 -1
  30. data/lib/exekutor/job_error.rb +1 -1
  31. data/lib/exekutor/job_options.rb +22 -13
  32. data/lib/exekutor/plugins/appsignal.rb +7 -5
  33. data/lib/exekutor/plugins.rb +8 -4
  34. data/lib/exekutor/queue.rb +69 -30
  35. data/lib/exekutor/version.rb +1 -1
  36. data/lib/exekutor/worker.rb +89 -48
  37. data/lib/exekutor.rb +2 -2
  38. data/lib/generators/exekutor/configuration_generator.rb +11 -6
  39. data/lib/generators/exekutor/install_generator.rb +24 -15
  40. data/lib/generators/exekutor/templates/install/functions/exekutor_broadcast_job_enqueued.sql +10 -0
  41. data/lib/generators/exekutor/templates/install/functions/exekutor_requeue_orphaned_jobs.sql +11 -0
  42. data/lib/generators/exekutor/templates/install/migrations/create_exekutor_schema.rb.erb +23 -22
  43. data/lib/generators/exekutor/templates/install/triggers/exekutor_broadcast_job_enqueued.sql +7 -0
  44. data/lib/generators/exekutor/templates/install/triggers/exekutor_requeue_orphaned_jobs.sql +5 -0
  45. data.tar.gz.sig +0 -0
  46. metadata +67 -23
  47. metadata.gz.sig +0 -0
  48. data/lib/generators/exekutor/templates/install/functions/job_notifier.sql +0 -7
  49. data/lib/generators/exekutor/templates/install/functions/requeue_orphaned_jobs.sql +0 -7
  50. data/lib/generators/exekutor/templates/install/triggers/notify_workers.sql +0 -6
  51. data/lib/generators/exekutor/templates/install/triggers/requeue_orphaned_jobs.sql +0 -5
@@ -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 [Integer] :max_thread_idletime the maximum number of seconds a thread may be idle before being stopped
27
- # @option config [Integer] :polling_interval the polling interval in seconds
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 before exiting
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 [Integer] :healthcheck_timeout The timeout of a worker in minutes before the healthcheck server deems it as down
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
- @reserver = Internal::Reserver.new @record.id, config[:queues]
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
- provider_threads = 1
45
- provider_threads += 1 if config.fetch(:enable_listener, true)
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
- listener = Internal::Listener.new worker_id: @record.id, provider: @provider, pool: provider_pool,
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
- set_state :stopped
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: if @executor.running?
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 "Internal"
48
+ Exekutor.private_constant :Internal
49
49
  ActiveSupport.run_load_hooks(:exekutor, Exekutor)
@@ -1,18 +1,23 @@
1
1
  # frozen_string_literal: true
2
- require 'rails/generators'
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 'Create YAML configuration for Exekutor'
8
+ desc "Create YAML configuration for Exekutor"
7
9
 
8
- class_option :identifier, type: :string, aliases: %i(--id), desc: "The worker identifier"
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] = 8765
15
+ config[:status_port] = 12_677
13
16
  config[:set_db_connection_name] = true
14
17
  config[:wait_for_termination] = 120
15
- create_file "config/exekutor#{".#{options[:identifier]}" if options[:identifier]}.yml", { "exekutor" => config.stringify_keys }.to_yaml
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
- require 'rails/generators'
3
- require 'rails/generators/active_record'
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 'Create migrations for Exekutor'
10
+ desc "Create migrations for Exekutor"
9
11
 
10
- TEMPLATE_DIR = File.join(__dir__, 'templates/install')
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 'initializers/exekutor.rb.erb', 'config/initializers/exekutor.rb'
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 'migrations/create_exekutor_schema.rb.erb', File.join(db_migrate_path, 'create_exekutor_schema.rb')
19
- if defined? Fx
20
- %w(job_notifier requeue_orphaned_jobs).each do |function|
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
@@ -0,0 +1,11 @@
1
+ CREATE
2
+ OR REPLACE FUNCTION exekutor_requeue_orphaned_jobs() RETURNS TRIGGER AS $$
3
+ BEGIN
4
+ UPDATE exekutor_jobs
5
+ SET status = 'p'
6
+ WHERE worker_id = OLD.id
7
+ AND status = 'e';
8
+ RETURN OLD;
9
+ END;
10
+ $$
11
+ 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 :created_at, null: false, default: -> { 'now()' }
11
- t.datetime :last_heartbeat_at, null: false, default: -> { 'now()' }
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: 'i'
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: 'default', limit: 200, index: true
21
- t.integer :priority, null: false, default: 16383, limit: 2
22
- t.datetime :enqueued_at, null: false, default: -> { 'now()' }
23
- t.datetime :scheduled_at, null: false, default: -> { 'now()' }
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: 'p'
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: %Q{"status"='p'}, name: :index_exekutor_jobs_on_dequeue_order
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: -> { 'now()' }
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 :job_notifier
45
- create_trigger :notify_workers
45
+ create_function :exekutor_broadcast_job_enqueued
46
+ create_trigger :exekutor_broadcast_job_enqueued, on: :exekutor_jobs
46
47
 
47
- create_function :requeue_orphaned_jobs
48
- create_trigger :requeue_orphaned_jobs
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 "job_notifier" %>
54
+ <%= function_sql "exekutor_broadcast_job_enqueued" %>
54
55
  SQL
55
56
  execute <<~SQL
56
- <%= trigger_sql "notify_workers" %>
57
+ <%= trigger_sql "exekutor_broadcast_job_enqueued" %>
57
58
  SQL
58
59
 
59
60
  execute <<~SQL
60
- <%= function_sql "requeue_orphaned_jobs" %>
61
+ <%= function_sql "exekutor_requeue_orphaned_jobs" %>
61
62
  SQL
62
63
  execute <<~SQL
63
- <%= trigger_sql "requeue_orphaned_jobs" %>
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 requeue_orphaned_jobs ON exekutor_workers
69
+ DROP TRIGGER exekutor_requeue_orphaned_jobs ON exekutor_workers
69
70
  SQL
70
71
  execute <<~SQL
71
- DROP FUNCTION requeue_orphaned_jobs
72
+ DROP FUNCTION exekutor_requeue_orphaned_jobs
72
73
  SQL
73
74
  execute <<~SQL
74
- DROP TRIGGER notify_exekutor_workers ON exekutor_jobs
75
+ DROP TRIGGER exekutor_broadcast_job_enqueued ON exekutor_jobs
75
76
  SQL
76
77
  execute <<~SQL
77
- DROP FUNCTION exekutor_job_notifier
78
+ DROP FUNCTION exekutor_broadcast_job_enqueued
78
79
  SQL
79
80
  end
80
81
  end
@@ -0,0 +1,7 @@
1
+ CREATE TRIGGER exekutor_broadcast_job_enqueued
2
+ AFTER INSERT OR
3
+ UPDATE OF queue, scheduled_at, status
4
+ ON exekutor_jobs
5
+ FOR EACH ROW
6
+ WHEN (NEW.status = 'p')
7
+ EXECUTE FUNCTION exekutor_broadcast_job_enqueued()
@@ -0,0 +1,5 @@
1
+ CREATE TRIGGER exekutor_requeue_orphaned_jobs
2
+ BEFORE DELETE
3
+ ON exekutor_workers
4
+ FOR EACH ROW
5
+ EXECUTE FUNCTION exekutor_requeue_orphaned_jobs()
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.0
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-03-23 00:00:00.000000000 Z
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: "PostgreSQL backed active job adapter which uses `LISTEN/NOTIFY` to listen
324
- for jobs and `FOR UPDATE SKIP LOCKED` to \nreserve jobs.\n"
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/job_notifier.sql
371
- - lib/generators/exekutor/templates/install/functions/requeue_orphaned_jobs.sql
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/notify_workers.sql
375
- - lib/generators/exekutor/templates/install/triggers/requeue_orphaned_jobs.sql
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.0.9
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
@@ -1,7 +0,0 @@
1
- CREATE OR REPLACE FUNCTION exekutor_job_notifier() RETURNS TRIGGER AS $$
2
- BEGIN
3
- PERFORM pg_notify('exekutor::job_enqueued',
4
- CONCAT('id:', NEW.id,';q:', NEW.queue,';t:', extract ('epoch' from NEW.scheduled_at)));
5
- RETURN NULL;
6
- END;
7
- $$ LANGUAGE plpgsql
@@ -1,7 +0,0 @@
1
- CREATE OR REPLACE FUNCTION requeue_orphaned_jobs() RETURNS TRIGGER AS $$ BEGIN
2
- UPDATE exekutor_jobs
3
- SET status = 'p'
4
- WHERE worker_id = OLD.id
5
- AND status = 'e';
6
- RETURN OLD; END;
7
- $$ LANGUAGE plpgsql
@@ -1,6 +0,0 @@
1
- CREATE TRIGGER notify_exekutor_workers
2
- AFTER INSERT OR UPDATE OF queue, scheduled_at, status
3
- ON exekutor_jobs
4
- FOR EACH ROW
5
- WHEN (NEW.status = 'p')
6
- EXECUTE FUNCTION exekutor_job_notifier()
@@ -1,5 +0,0 @@
1
- CREATE TRIGGER requeue_orphaned_jobs
2
- BEFORE DELETE
3
- ON exekutor_workers
4
- FOR EACH ROW
5
- EXECUTE FUNCTION requeue_orphaned_jobs()