pgbus 0.19.0 → 0.19.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
- data/CHANGELOG.md +329 -147
- data/README.md +65 -27
- data/app/controllers/pgbus/deploy_tasks_controller.rb +38 -0
- data/app/helpers/pgbus/deploy_tasks_helper.rb +77 -0
- data/app/helpers/pgbus/processes_helper.rb +1 -1
- data/app/models/pgbus/deploy_task.rb +104 -0
- data/app/models/pgbus/deploy_task_run.rb +45 -0
- data/app/views/layouts/pgbus/application.html.erb +2 -0
- data/app/views/pgbus/deploy_tasks/_rollover_banner.html.erb +25 -0
- data/app/views/pgbus/deploy_tasks/_tasks_table.html.erb +71 -0
- data/app/views/pgbus/deploy_tasks/index.html.erb +6 -0
- data/app/views/pgbus/deploy_tasks/show.html.erb +134 -0
- data/config/i18n-tasks.yml +2 -0
- data/config/locales/da.yml +97 -0
- data/config/locales/de.yml +97 -0
- data/config/locales/en.yml +98 -1
- data/config/locales/es.yml +97 -0
- data/config/locales/fi.yml +97 -0
- data/config/locales/fr.yml +97 -0
- data/config/locales/it.yml +97 -0
- data/config/locales/ja.yml +97 -0
- data/config/locales/nb.yml +97 -0
- data/config/locales/nl.yml +97 -0
- data/config/locales/pt.yml +97 -0
- data/config/locales/sv.yml +97 -0
- data/config/routes.rb +7 -0
- data/lib/generators/pgbus/add_batch_callback_jobs_generator.rb +4 -1
- data/lib/generators/pgbus/add_deploy_tasks_generator.rb +51 -0
- data/lib/generators/pgbus/templates/add_deploy_tasks_tables.rb.erb +43 -0
- data/lib/generators/pgbus/templates/deploy_tasks.yml.erb +42 -0
- data/lib/generators/pgbus/templates/migration.rb.erb +43 -0
- data/lib/pgbus/active_job/batch_id.rb +10 -4
- data/lib/pgbus/batch/builder.rb +92 -0
- data/lib/pgbus/batch.rb +97 -22
- data/lib/pgbus/configuration/deploy_settings.rb +46 -0
- data/lib/pgbus/configuration.rb +3 -0
- data/lib/pgbus/deploy/revision.rb +59 -0
- data/lib/pgbus/deploy/rollover.rb +65 -0
- data/lib/pgbus/deploy/runner.rb +259 -0
- data/lib/pgbus/deploy/task.rb +105 -0
- data/lib/pgbus/engine.rb +17 -0
- data/lib/pgbus/generators/migration_detector.rb +12 -1
- data/lib/pgbus/instrumentation.rb +14 -0
- data/lib/pgbus/integrations/appsignal/subscriber.rb +15 -0
- data/lib/pgbus/mcp/server.rb +2 -1
- data/lib/pgbus/mcp/tools/deploy_tasks_tool.rb +86 -0
- data/lib/pgbus/mcp.rb +1 -0
- data/lib/pgbus/metrics/subscriber.rb +12 -0
- data/lib/pgbus/outbox/poller.rb +1 -0
- data/lib/pgbus/process/consumer.rb +57 -3
- data/lib/pgbus/process/dispatcher.rb +18 -1
- data/lib/pgbus/process/heartbeat.rb +7 -2
- data/lib/pgbus/process/supervisor.rb +35 -3
- data/lib/pgbus/process/worker.rb +1 -0
- data/lib/pgbus/recurring/scheduler.rb +54 -20
- data/lib/pgbus/version.rb +1 -1
- data/lib/pgbus/web/data_source/deploy_task_list.rb +114 -0
- data/lib/pgbus/web/data_source/list_counts.rb +2 -1
- data/lib/pgbus/web/data_source.rb +1 -0
- data/lib/pgbus/web/deploy_task_state.rb +51 -0
- data/lib/pgbus.rb +11 -0
- data/sig/pgbus/configuration.rbs +10 -0
- data/sig/pgbus.rbs +9 -0
- metadata +21 -1
|
@@ -7,24 +7,33 @@ module Pgbus
|
|
|
7
7
|
class Scheduler
|
|
8
8
|
include Process::SignalHandler
|
|
9
9
|
|
|
10
|
-
attr_reader :schedule, :config
|
|
10
|
+
attr_reader :schedule, :config, :deploy_runner
|
|
11
11
|
|
|
12
12
|
def initialize(config: Pgbus.configuration)
|
|
13
13
|
@config = config
|
|
14
14
|
@schedule = Schedule.new(config: config)
|
|
15
|
+
# Deploy tasks (issue #536) ride this loop: the scheduler is already
|
|
16
|
+
# the one-per-deployment process, dedup'd across the overlap window.
|
|
17
|
+
@deploy_runner = Deploy::Runner.new(config: config) if config.deploy_tasks_enabled && config.deploy_tasks&.any?
|
|
15
18
|
@shutting_down = false
|
|
16
19
|
@last_runs = {}
|
|
17
20
|
@loop_tick_at = Concurrent::AtomicReference.new(nil)
|
|
21
|
+
@deploy_error = nil
|
|
18
22
|
end
|
|
19
23
|
|
|
24
|
+
# The order is load-bearing: the heartbeat registers this scheduler's row
|
|
25
|
+
# before it arms deploy tasks, so an old-revision scheduler in the
|
|
26
|
+
# overlap window sees it as lagging. A failed registration is logged and
|
|
27
|
+
# sync still runs; the new release's workers keep the old gate closed.
|
|
20
28
|
def run
|
|
21
29
|
setup_signals
|
|
22
30
|
start_heartbeat
|
|
23
31
|
sync_recurring_tasks
|
|
32
|
+
deploy_runner&.sync!
|
|
24
33
|
|
|
25
34
|
Pgbus.logger.info do
|
|
26
35
|
"[Pgbus] Scheduler started: #{schedule.tasks.size} recurring tasks, " \
|
|
27
|
-
"interval=#{config.recurring_schedule_interval}s"
|
|
36
|
+
"#{deploy_task_count} deploy tasks, interval=#{config.recurring_schedule_interval}s"
|
|
28
37
|
end
|
|
29
38
|
|
|
30
39
|
loop do
|
|
@@ -44,22 +53,12 @@ module Pgbus
|
|
|
44
53
|
end
|
|
45
54
|
|
|
46
55
|
def tick(now)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
run_at: run_at
|
|
54
|
-
) do
|
|
55
|
-
schedule.enqueue_task(task, run_at: run_at)
|
|
56
|
-
@last_runs[task.key] = now
|
|
57
|
-
end
|
|
58
|
-
rescue StandardError => e
|
|
59
|
-
Pgbus.logger.error do
|
|
60
|
-
"[Pgbus] Error scheduling recurring task #{task.key}: #{e.class}: #{e.message}"
|
|
61
|
-
end
|
|
62
|
-
end
|
|
56
|
+
tick_recurring(now) if config.recurring_enabled
|
|
57
|
+
tick_deploy_tasks(now)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def deploy_task_count
|
|
61
|
+
deploy_runner&.task_count || 0
|
|
63
62
|
end
|
|
64
63
|
|
|
65
64
|
def last_run_at(key)
|
|
@@ -94,9 +93,43 @@ module Pgbus
|
|
|
94
93
|
|
|
95
94
|
private
|
|
96
95
|
|
|
96
|
+
def tick_recurring(now)
|
|
97
|
+
schedule.due_tasks(now).each do |task, run_at|
|
|
98
|
+
Pgbus::Instrumentation.instrument(
|
|
99
|
+
"pgbus.recurring.enqueue",
|
|
100
|
+
task: task.key,
|
|
101
|
+
class_name: task.class_name,
|
|
102
|
+
queue: task.queue_name,
|
|
103
|
+
run_at: run_at
|
|
104
|
+
) do
|
|
105
|
+
schedule.enqueue_task(task, run_at: run_at)
|
|
106
|
+
@last_runs[task.key] = now
|
|
107
|
+
end
|
|
108
|
+
rescue StandardError => e
|
|
109
|
+
Pgbus.logger.error do
|
|
110
|
+
"[Pgbus] Error scheduling recurring task #{task.key}: #{e.class}: #{e.message}"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# A persistent failure (the tables missing, the database down) is logged
|
|
116
|
+
# and reported once per distinct error, then at debug, not every tick.
|
|
117
|
+
def tick_deploy_tasks(now)
|
|
118
|
+
deploy_runner&.tick(now)
|
|
119
|
+
@deploy_error = nil
|
|
120
|
+
rescue StandardError => e
|
|
121
|
+
signature = "#{e.class}: #{e.message}"
|
|
122
|
+
if signature == @deploy_error
|
|
123
|
+
Pgbus.logger.debug { "[Pgbus] Error running deploy tasks (repeated): #{signature}" }
|
|
124
|
+
else
|
|
125
|
+
@deploy_error = signature
|
|
126
|
+
ErrorReporter.report(e, { action: "deploy_tasks_tick" }) # logs at error itself
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
97
130
|
def sync_recurring_tasks
|
|
98
131
|
tasks = config.recurring_tasks
|
|
99
|
-
return if tasks.nil?
|
|
132
|
+
return if tasks.nil? || !config.recurring_enabled
|
|
100
133
|
|
|
101
134
|
RecurringTask.sync_from_config!(tasks)
|
|
102
135
|
Pgbus.logger.info { "[Pgbus] Synced #{tasks.size} recurring task(s) from configuration" }
|
|
@@ -116,8 +149,9 @@ module Pgbus
|
|
|
116
149
|
def start_heartbeat
|
|
117
150
|
@heartbeat = Process::Heartbeat.new(
|
|
118
151
|
kind: "scheduler",
|
|
152
|
+
config: @config,
|
|
119
153
|
metadata: { pid: ::Process.pid, tasks: schedule.tasks.size, started_at: Time.now.to_f,
|
|
120
|
-
supervisor_pid: ::Process.ppid },
|
|
154
|
+
supervisor_pid: ::Process.ppid }.merge(deploy_runner ? { deploy_tasks: deploy_task_count } : {}),
|
|
121
155
|
loop_tick_supplier: -> { @loop_tick_at.get }
|
|
122
156
|
)
|
|
123
157
|
@heartbeat.start
|
data/lib/pgbus/version.rb
CHANGED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pgbus
|
|
4
|
+
module Web
|
|
5
|
+
class DataSource
|
|
6
|
+
# The Deploy tasks page (issue #536): declared tasks with their last
|
|
7
|
+
# rollover and manual runs, one task's run history, the rollover the
|
|
8
|
+
# scheduler acts on, and the two actions (Run now, Enable/Disable).
|
|
9
|
+
module DeployTaskList
|
|
10
|
+
RUN_HISTORY = 25
|
|
11
|
+
|
|
12
|
+
# page/per_page nil returns every task (the MCP tool's default). An
|
|
13
|
+
# install without the tables (pgbus:add_deploy_tasks not run) gets the
|
|
14
|
+
# empty state, whose hint names the generator, not an error per refresh.
|
|
15
|
+
def deploy_tasks(page: nil, per_page: nil)
|
|
16
|
+
return [] unless DeployTask.table_exists?
|
|
17
|
+
|
|
18
|
+
scope = DeployTask.order(:key)
|
|
19
|
+
scope = scope.limit(per_page).offset(((page || 1) - 1) * per_page) if per_page
|
|
20
|
+
records = scope.to_a
|
|
21
|
+
runs = DeployTaskRun.latest_for(records.map(&:key)).group_by(&:task_key)
|
|
22
|
+
records.map { |record| deploy_task_row(record, runs.fetch(record.key, [])) }
|
|
23
|
+
rescue StandardError => e
|
|
24
|
+
Pgbus.logger.error { "[Pgbus::Web] Error fetching deploy tasks: #{e.class}: #{e.message}" }
|
|
25
|
+
[]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def deploy_task(id)
|
|
29
|
+
return nil unless DeployTask.table_exists?
|
|
30
|
+
|
|
31
|
+
record = DeployTask.find_by(id: id)
|
|
32
|
+
return nil unless record
|
|
33
|
+
|
|
34
|
+
# The state reads the same unbounded latest-per-trigger runs as the
|
|
35
|
+
# list, so a run older than the 25 shown still counts.
|
|
36
|
+
runs = DeployTaskRun.for_task(record.key).recent(RUN_HISTORY).to_a
|
|
37
|
+
deploy_task_row(record, DeployTaskRun.latest_for([record.key]).to_a).merge(
|
|
38
|
+
arguments: record.parsed_arguments,
|
|
39
|
+
runs: runs.map { |run| deploy_run_hash(run).merge(queue_name: run.queue_name, msg_id: run.msg_id) }
|
|
40
|
+
)
|
|
41
|
+
rescue StandardError => e
|
|
42
|
+
Pgbus.logger.error { "[Pgbus::Web] Error fetching deploy task #{id}: #{e.class}: #{e.message}" }
|
|
43
|
+
nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def toggle_deploy_task(id)
|
|
47
|
+
record = DeployTask.find_by(id: id)
|
|
48
|
+
return nil unless record
|
|
49
|
+
|
|
50
|
+
record.update!(enabled: !record.enabled)
|
|
51
|
+
record.enabled ? :enabled : :disabled
|
|
52
|
+
rescue StandardError => e
|
|
53
|
+
Pgbus.logger.error { "[Pgbus::Web] Error toggling deploy task #{id}: #{e.message}" }
|
|
54
|
+
nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Run now: the scheduler's enqueue path with no gate and no claim. It
|
|
58
|
+
# leaves a pending rollover arm alone and records a manual run.
|
|
59
|
+
# :enqueued or :failed, the real outcome.
|
|
60
|
+
def enqueue_deploy_task_now(id)
|
|
61
|
+
record = DeployTask.find_by(id: id)
|
|
62
|
+
return :failed unless record
|
|
63
|
+
# The hidden button is not the boundary: a disabled task is not run.
|
|
64
|
+
return disabled_enqueue(record) unless record.enabled
|
|
65
|
+
|
|
66
|
+
Deploy::Runner.new(config: Pgbus.configuration).enqueue(record.to_task, triggered_by: Deploy::Runner::MANUAL)
|
|
67
|
+
rescue StandardError => e
|
|
68
|
+
Pgbus.logger.error { "[Pgbus::Web] Error enqueuing deploy task #{id}: #{e.class}: #{e.message}" }
|
|
69
|
+
:failed
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# The rollover judged against the newest live scheduler's revision,
|
|
73
|
+
# not this web process's; that one only when no scheduler is live
|
|
74
|
+
# (scheduler: false says so). nil when it cannot be read.
|
|
75
|
+
def deploy_rollover(now: Time.current)
|
|
76
|
+
scheduler, revision = Deploy::Rollover.scheduler_revision(now: now)
|
|
77
|
+
revision = Deploy::Revision.current unless scheduler
|
|
78
|
+
status = Deploy::Rollover.check(revision: revision, now: now)
|
|
79
|
+
{ revision: revision, reason: status.reason, lagging: status.lagging, workers_live: status.workers_live,
|
|
80
|
+
live_by_revision: status.live_by_revision, scheduler: scheduler }
|
|
81
|
+
rescue StandardError => e
|
|
82
|
+
Pgbus.logger.error { "[Pgbus::Web] Error reading the deploy rollover: #{e.class}: #{e.message}" }
|
|
83
|
+
nil
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def disabled_enqueue(record)
|
|
89
|
+
Pgbus.logger.warn { "[Pgbus::Web] Deploy task #{record.key} is disabled; Run now refused" }
|
|
90
|
+
:failed
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def deploy_task_row(record, latest_runs)
|
|
94
|
+
by_trigger = latest_runs.index_by(&:triggered_by)
|
|
95
|
+
{
|
|
96
|
+
id: record.id, key: record.key, class_name: record.class_name, command: record.command,
|
|
97
|
+
version: record.version, every_deploy: record.every_deploy, queue_name: record.queue_name,
|
|
98
|
+
priority: record.priority, description: record.description, enabled: record.enabled,
|
|
99
|
+
static: record.static, armed_at: record.armed_at, armed_for: record.armed_for,
|
|
100
|
+
last_rollover_run: deploy_run_hash(by_trigger[Deploy::Runner::ROLLOVER]),
|
|
101
|
+
last_manual_run: deploy_run_hash(by_trigger[Deploy::Runner::MANUAL]),
|
|
102
|
+
created_at: record.created_at, updated_at: record.updated_at
|
|
103
|
+
}
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def deploy_run_hash(run)
|
|
107
|
+
return nil unless run
|
|
108
|
+
|
|
109
|
+
{ run_at: run.run_at, revision: run.revision, version: run.version, triggered_by: run.triggered_by }
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -34,13 +34,14 @@ module Pgbus
|
|
|
34
34
|
# names rather than lambdas, so the constant is plain frozen data.
|
|
35
35
|
LIST_MODELS = {
|
|
36
36
|
batches: :BatchEntry,
|
|
37
|
+
deploy_tasks: :DeployTask,
|
|
37
38
|
job_locks: :UniquenessKey,
|
|
38
39
|
outbox: :OutboxEntry,
|
|
39
40
|
processed_events: :ProcessedEvent,
|
|
40
41
|
recurring_tasks: :RecurringTask
|
|
41
42
|
}.freeze
|
|
42
43
|
|
|
43
|
-
# list – :batches, :job_locks, :concurrency_keys, :outbox, :processed_events or :recurring_tasks.
|
|
44
|
+
# list – :batches, :deploy_tasks, :job_locks, :concurrency_keys, :outbox, :processed_events or :recurring_tasks.
|
|
44
45
|
def list_count(list)
|
|
45
46
|
raise ArgumentError, "unknown list: #{list.inspect}" unless list == :concurrency_keys || LIST_MODELS.key?(list)
|
|
46
47
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pgbus
|
|
4
|
+
module Web
|
|
5
|
+
# The Deploy tasks page's words for one task (issue #536), derived from
|
|
6
|
+
# its row and the rollover the scheduler acts on (DataSource#deploy_rollover),
|
|
7
|
+
# so the page prints the reason the scheduler waits for. Pure.
|
|
8
|
+
#
|
|
9
|
+
# States: disabled, waiting (armed, gate closed, with the gate's reason),
|
|
10
|
+
# due (armed, gate open), ran (not armed, has a rollover run), never. A
|
|
11
|
+
# manual run is appended to any state through manual_args.
|
|
12
|
+
module DeployTaskState
|
|
13
|
+
BADGE_TONES = { "disabled" => :gray, "waiting" => :yellow, "due" => :indigo, "ran" => :green,
|
|
14
|
+
"never" => :gray }.freeze
|
|
15
|
+
|
|
16
|
+
Result = Data.define(:state, :reason_key, :reason_args, :badge_tone, :manual_args)
|
|
17
|
+
|
|
18
|
+
module_function
|
|
19
|
+
|
|
20
|
+
# row – a DataSource#deploy_tasks row. rollover – DataSource#deploy_rollover, or nil when unreadable.
|
|
21
|
+
def present(row, rollover)
|
|
22
|
+
state, key, args = derive(row, rollover)
|
|
23
|
+
manual = row[:last_manual_run]
|
|
24
|
+
Result.new(state: state, reason_key: key, reason_args: args, badge_tone: BADGE_TONES.fetch(state),
|
|
25
|
+
manual_args: manual ? { ago: manual[:run_at] } : nil)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def derive(row, rollover)
|
|
29
|
+
return ["disabled", row[:armed_at] ? "disabled_armed" : "disabled", {}] unless row[:enabled]
|
|
30
|
+
return armed(rollover) if row[:armed_at]
|
|
31
|
+
|
|
32
|
+
run = row[:last_rollover_run]
|
|
33
|
+
return ["never", "never", {}] unless run
|
|
34
|
+
|
|
35
|
+
["ran", "ran", { ago: run[:run_at], revision: run[:revision] }]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def armed(rollover)
|
|
39
|
+
return ["waiting", "waiting_unknown", {}] unless rollover
|
|
40
|
+
return ["waiting", "waiting_no_scheduler", {}] unless rollover[:scheduler]
|
|
41
|
+
|
|
42
|
+
case rollover[:reason]
|
|
43
|
+
when :ready then ["due", "due", {}]
|
|
44
|
+
when :lagging then ["waiting", "waiting_lagging", { count: rollover[:lagging].size, revision: rollover[:revision] }]
|
|
45
|
+
when :no_workers then ["waiting", "waiting_no_workers", { revision: rollover[:revision] }]
|
|
46
|
+
else ["waiting", "waiting_no_revision", {}]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
data/lib/pgbus.rb
CHANGED
|
@@ -298,6 +298,17 @@ module Pgbus
|
|
|
298
298
|
Streams::Key.queue_name_budget
|
|
299
299
|
end
|
|
300
300
|
|
|
301
|
+
# Open a batch, yield a Pgbus::Batch::Builder, and start the batch when
|
|
302
|
+
# the block returns — the top-level shortcut for Pgbus::Batch.start.
|
|
303
|
+
#
|
|
304
|
+
# Pgbus.batch(description: "Import") do |b|
|
|
305
|
+
# b.on_complete ImportDoneJob
|
|
306
|
+
# b.add(*rows.map { |row| ImportRowJob.new(row.id) })
|
|
307
|
+
# end
|
|
308
|
+
def batch(**, &)
|
|
309
|
+
Batch.start(**, &)
|
|
310
|
+
end
|
|
311
|
+
|
|
301
312
|
# Publish an event to the bus — the top-level shortcut for
|
|
302
313
|
# `Pgbus::EventBus::Publisher.publish`, symmetric with `Pgbus.stream`.
|
|
303
314
|
#
|
data/sig/pgbus/configuration.rbs
CHANGED
|
@@ -7,6 +7,8 @@ module Pgbus
|
|
|
7
7
|
class Configuration
|
|
8
8
|
def allowed_global_id_models: () -> untyped
|
|
9
9
|
def allowed_global_id_models=: (untyped) -> untyped
|
|
10
|
+
def app_revision: () -> untyped
|
|
11
|
+
def app_revision=: (untyped) -> untyped
|
|
10
12
|
def apply_log_format!: () -> void
|
|
11
13
|
def appsignal_enabled: () -> bool
|
|
12
14
|
def appsignal_enabled=: (untyped) -> untyped
|
|
@@ -46,6 +48,14 @@ module Pgbus
|
|
|
46
48
|
def default_priority=: (untyped) -> untyped
|
|
47
49
|
def default_queue: () -> String
|
|
48
50
|
def default_queue=: (untyped) -> untyped
|
|
51
|
+
def deploy_task_run_retention: () -> Numeric?
|
|
52
|
+
def deploy_task_run_retention=: (untyped value) -> untyped
|
|
53
|
+
def deploy_tasks: () -> untyped
|
|
54
|
+
def deploy_tasks=: (untyped) -> untyped
|
|
55
|
+
def deploy_tasks_enabled: () -> bool
|
|
56
|
+
def deploy_tasks_enabled=: (untyped) -> untyped
|
|
57
|
+
def deploy_tasks_files: () -> untyped
|
|
58
|
+
def deploy_tasks_files=: (untyped) -> untyped
|
|
49
59
|
def dispatch_interval: () -> Float
|
|
50
60
|
def dispatch_interval=: (untyped) -> untyped
|
|
51
61
|
def doctor_on_boot: () -> untyped
|
data/sig/pgbus.rbs
CHANGED
|
@@ -49,6 +49,13 @@ module Pgbus
|
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
# Partial: only the types Pgbus.batch names. Batch's own methods are not
|
|
53
|
+
# covered by spec/pgbus/rbs_spec.rb yet.
|
|
54
|
+
class Batch
|
|
55
|
+
class Builder
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
52
59
|
def self.configuration: () -> Configuration
|
|
53
60
|
def self.configure: () { (Configuration) -> void } -> Configuration
|
|
54
61
|
def self.finalize!: () -> Configuration
|
|
@@ -57,6 +64,8 @@ module Pgbus
|
|
|
57
64
|
def self.stream_key: (*untyped parts, ?digest_bits: Integer) -> String
|
|
58
65
|
def self.stream_key!: (String key) -> String
|
|
59
66
|
def self.stream_name_budget: () -> Integer
|
|
67
|
+
# Keywords go to Pgbus::Batch.new (description:, properties:, on_complete:, uniqueness_key:, …).
|
|
68
|
+
def self.batch: (**untyped options) { (Batch::Builder) -> void } -> Batch
|
|
60
69
|
# delay: seconds, as a Numeric or an ActiveSupport::Duration (1.hour).
|
|
61
70
|
def self.publish: (String routing_key, untyped payload, ?headers: Hash[String, untyped]?, ?delay: Numeric | _ToI) -> untyped
|
|
62
71
|
def self.publish_later: (String routing_key, untyped payload, delay: Numeric | _ToI, ?headers: Hash[String, untyped]?) -> untyped
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pgbus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.19.
|
|
4
|
+
version: 0.19.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mikael Henriksson
|
|
@@ -134,6 +134,7 @@ files:
|
|
|
134
134
|
- app/controllers/pgbus/batches_controller.rb
|
|
135
135
|
- app/controllers/pgbus/dashboard_controller.rb
|
|
136
136
|
- app/controllers/pgbus/dead_letter_controller.rb
|
|
137
|
+
- app/controllers/pgbus/deploy_tasks_controller.rb
|
|
137
138
|
- app/controllers/pgbus/events_controller.rb
|
|
138
139
|
- app/controllers/pgbus/frontends_controller.rb
|
|
139
140
|
- app/controllers/pgbus/insights_controller.rb
|
|
@@ -159,6 +160,7 @@ files:
|
|
|
159
160
|
- app/helpers/pgbus/application_helper.rb
|
|
160
161
|
- app/helpers/pgbus/button_helper.rb
|
|
161
162
|
- app/helpers/pgbus/dashboard_helper.rb
|
|
163
|
+
- app/helpers/pgbus/deploy_tasks_helper.rb
|
|
162
164
|
- app/helpers/pgbus/events_helper.rb
|
|
163
165
|
- app/helpers/pgbus/insights_helper.rb
|
|
164
166
|
- app/helpers/pgbus/processes_helper.rb
|
|
@@ -167,6 +169,8 @@ files:
|
|
|
167
169
|
- app/models/pgbus/batch_entry.rb
|
|
168
170
|
- app/models/pgbus/batch_execution.rb
|
|
169
171
|
- app/models/pgbus/blocked_execution.rb
|
|
172
|
+
- app/models/pgbus/deploy_task.rb
|
|
173
|
+
- app/models/pgbus/deploy_task_run.rb
|
|
170
174
|
- app/models/pgbus/job_stat.rb
|
|
171
175
|
- app/models/pgbus/outbox_entry.rb
|
|
172
176
|
- app/models/pgbus/process_entry.rb
|
|
@@ -194,6 +198,10 @@ files:
|
|
|
194
198
|
- app/views/pgbus/dead_letter/_row.html.erb
|
|
195
199
|
- app/views/pgbus/dead_letter/index.html.erb
|
|
196
200
|
- app/views/pgbus/dead_letter/show.html.erb
|
|
201
|
+
- app/views/pgbus/deploy_tasks/_rollover_banner.html.erb
|
|
202
|
+
- app/views/pgbus/deploy_tasks/_tasks_table.html.erb
|
|
203
|
+
- app/views/pgbus/deploy_tasks/index.html.erb
|
|
204
|
+
- app/views/pgbus/deploy_tasks/show.html.erb
|
|
197
205
|
- app/views/pgbus/events/_list.html.erb
|
|
198
206
|
- app/views/pgbus/events/_processed_table.html.erb
|
|
199
207
|
- app/views/pgbus/events/_replay.html.erb
|
|
@@ -246,6 +254,7 @@ files:
|
|
|
246
254
|
- lib/active_job/queue_adapters/pgbus_adapter.rb
|
|
247
255
|
- lib/generators/pgbus/add_batch_callback_jobs_generator.rb
|
|
248
256
|
- lib/generators/pgbus/add_batch_executions_generator.rb
|
|
257
|
+
- lib/generators/pgbus/add_deploy_tasks_generator.rb
|
|
249
258
|
- lib/generators/pgbus/add_failed_events_index_generator.rb
|
|
250
259
|
- lib/generators/pgbus/add_job_stats_generator.rb
|
|
251
260
|
- lib/generators/pgbus/add_job_stats_latency_generator.rb
|
|
@@ -264,6 +273,7 @@ files:
|
|
|
264
273
|
- lib/generators/pgbus/migration_path.rb
|
|
265
274
|
- lib/generators/pgbus/templates/add_batch_callback_jobs.rb.erb
|
|
266
275
|
- lib/generators/pgbus/templates/add_batch_executions.rb.erb
|
|
276
|
+
- lib/generators/pgbus/templates/add_deploy_tasks_tables.rb.erb
|
|
267
277
|
- lib/generators/pgbus/templates/add_failed_events_unique_index.rb.erb
|
|
268
278
|
- lib/generators/pgbus/templates/add_job_stats.rb.erb
|
|
269
279
|
- lib/generators/pgbus/templates/add_job_stats_latency.rb.erb
|
|
@@ -277,6 +287,7 @@ files:
|
|
|
277
287
|
- lib/generators/pgbus/templates/add_stream_queues.rb.erb
|
|
278
288
|
- lib/generators/pgbus/templates/add_stream_stats.rb.erb
|
|
279
289
|
- lib/generators/pgbus/templates/add_uniqueness_keys.rb.erb
|
|
290
|
+
- lib/generators/pgbus/templates/deploy_tasks.yml.erb
|
|
280
291
|
- lib/generators/pgbus/templates/initializer.rb.erb
|
|
281
292
|
- lib/generators/pgbus/templates/migrate_job_locks_to_uniqueness_keys.rb.erb
|
|
282
293
|
- lib/generators/pgbus/templates/migration.rb.erb
|
|
@@ -296,6 +307,7 @@ files:
|
|
|
296
307
|
- lib/pgbus/active_job/executor.rb
|
|
297
308
|
- lib/pgbus/autovacuum_tuning.rb
|
|
298
309
|
- lib/pgbus/batch.rb
|
|
310
|
+
- lib/pgbus/batch/builder.rb
|
|
299
311
|
- lib/pgbus/batch/sweep.rb
|
|
300
312
|
- lib/pgbus/bus_record.rb
|
|
301
313
|
- lib/pgbus/circuit_breaker.rb
|
|
@@ -315,6 +327,7 @@ files:
|
|
|
315
327
|
- lib/pgbus/concurrency/semaphore.rb
|
|
316
328
|
- lib/pgbus/configuration.rb
|
|
317
329
|
- lib/pgbus/configuration/capsule_dsl.rb
|
|
330
|
+
- lib/pgbus/configuration/deploy_settings.rb
|
|
318
331
|
- lib/pgbus/configuration/presence_settings.rb
|
|
319
332
|
- lib/pgbus/configuration/stream_authorization.rb
|
|
320
333
|
- lib/pgbus/current_attributes.rb
|
|
@@ -322,6 +335,10 @@ files:
|
|
|
322
335
|
- lib/pgbus/dead_letter_header.rb
|
|
323
336
|
- lib/pgbus/dedicated_connection.rb
|
|
324
337
|
- lib/pgbus/dedup_cache.rb
|
|
338
|
+
- lib/pgbus/deploy/revision.rb
|
|
339
|
+
- lib/pgbus/deploy/rollover.rb
|
|
340
|
+
- lib/pgbus/deploy/runner.rb
|
|
341
|
+
- lib/pgbus/deploy/task.rb
|
|
325
342
|
- lib/pgbus/doctor.rb
|
|
326
343
|
- lib/pgbus/engine.rb
|
|
327
344
|
- lib/pgbus/error_reporter.rb
|
|
@@ -357,6 +374,7 @@ files:
|
|
|
357
374
|
- lib/pgbus/mcp/runner.rb
|
|
358
375
|
- lib/pgbus/mcp/server.rb
|
|
359
376
|
- lib/pgbus/mcp/tools/concurrency_tool.rb
|
|
377
|
+
- lib/pgbus/mcp/tools/deploy_tasks_tool.rb
|
|
360
378
|
- lib/pgbus/mcp/tools/dlq_detail_tool.rb
|
|
361
379
|
- lib/pgbus/mcp/tools/dlq_tool.rb
|
|
362
380
|
- lib/pgbus/mcp/tools/health_tool.rb
|
|
@@ -447,12 +465,14 @@ files:
|
|
|
447
465
|
- lib/pgbus/web/data_source.rb
|
|
448
466
|
- lib/pgbus/web/data_source/dashboard_signals.rb
|
|
449
467
|
- lib/pgbus/web/data_source/dead_letter.rb
|
|
468
|
+
- lib/pgbus/web/data_source/deploy_task_list.rb
|
|
450
469
|
- lib/pgbus/web/data_source/event_list.rb
|
|
451
470
|
- lib/pgbus/web/data_source/job_list.rb
|
|
452
471
|
- lib/pgbus/web/data_source/list_counts.rb
|
|
453
472
|
- lib/pgbus/web/data_source/process_list.rb
|
|
454
473
|
- lib/pgbus/web/data_source/queue_summary.rb
|
|
455
474
|
- lib/pgbus/web/dead_letter_reason.rb
|
|
475
|
+
- lib/pgbus/web/deploy_task_state.rb
|
|
456
476
|
- lib/pgbus/web/event_state.rb
|
|
457
477
|
- lib/pgbus/web/health_app.rb
|
|
458
478
|
- lib/pgbus/web/health_server.rb
|