pgbus 0.17.1 → 0.17.3
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 +42 -0
- data/README.md +83 -13
- data/Rakefile +26 -0
- data/app/assets/javascripts/pgbus/stream_source_element.js +34 -2
- data/app/assets/javascripts/pgbus/stream_source_element.min.js +6 -0
- data/app/assets/javascripts/pgbus/stream_source_element.min.js.map +1 -0
- data/app/controllers/concerns/pgbus/job_listing.rb +37 -0
- data/app/controllers/concerns/pgbus/process_listing.rb +17 -0
- data/app/controllers/pgbus/application_controller.rb +5 -2
- data/app/controllers/pgbus/batches_controller.rb +4 -1
- data/app/controllers/pgbus/dashboard_controller.rb +20 -6
- data/app/controllers/pgbus/dead_letter_controller.rb +27 -3
- data/app/controllers/pgbus/events_controller.rb +52 -3
- data/app/controllers/pgbus/frontends_controller.rb +25 -11
- data/app/controllers/pgbus/insights_controller.rb +19 -1
- data/app/controllers/pgbus/jobs_controller.rb +45 -26
- data/app/controllers/pgbus/locks_controller.rb +7 -2
- data/app/controllers/pgbus/outbox_controller.rb +4 -1
- data/app/controllers/pgbus/processes_controller.rb +3 -1
- data/app/controllers/pgbus/queues_controller.rb +16 -4
- data/app/controllers/pgbus/recurring_tasks_controller.rb +5 -7
- data/app/frontend/pgbus/application.min.js +2 -0
- data/app/frontend/pgbus/application.min.js.map +1 -0
- data/app/frontend/pgbus/modules/charts.js +137 -77
- data/app/frontend/pgbus/modules/charts.min.js +2 -0
- data/app/frontend/pgbus/modules/charts.min.js.map +1 -0
- data/app/frontend/pgbus/style.css +1 -1
- data/app/frontend/pgbus/tailwind.css +18 -0
- data/app/frontend/pgbus/vendor/turbo.min.js +54 -0
- data/app/frontend/pgbus/vendor/turbo.min.js.map +1 -0
- data/app/helpers/pgbus/application_helper.rb +155 -113
- data/app/helpers/pgbus/button_helper.rb +88 -0
- data/app/helpers/pgbus/dashboard_helper.rb +157 -0
- data/app/helpers/pgbus/events_helper.rb +40 -0
- data/app/helpers/pgbus/insights_helper.rb +39 -0
- data/app/helpers/pgbus/processes_helper.rb +79 -0
- data/app/views/layouts/pgbus/application.html.erb +0 -1
- data/app/views/pgbus/batches/_batches_table.html.erb +16 -13
- data/app/views/pgbus/batches/show.html.erb +3 -4
- data/app/views/pgbus/dashboard/_processes_table.html.erb +11 -11
- data/app/views/pgbus/dashboard/_queue_health.html.erb +42 -51
- data/app/views/pgbus/dashboard/_queues_table.html.erb +18 -16
- data/app/views/pgbus/dashboard/_recent_failures.html.erb +16 -12
- data/app/views/pgbus/dashboard/_stats_cards.html.erb +70 -36
- data/app/views/pgbus/dashboard/show.html.erb +1 -1
- data/app/views/pgbus/dead_letter/_error.html.erb +13 -0
- data/app/views/pgbus/dead_letter/_messages_table.html.erb +37 -96
- data/app/views/pgbus/dead_letter/_row.html.erb +75 -0
- data/app/views/pgbus/dead_letter/index.html.erb +6 -9
- data/app/views/pgbus/dead_letter/show.html.erb +37 -21
- data/app/views/pgbus/events/_list.html.erb +55 -0
- data/app/views/pgbus/events/_processed_table.html.erb +45 -0
- data/app/views/pgbus/events/_replay.html.erb +10 -0
- data/app/views/pgbus/events/_row.html.erb +162 -0
- data/app/views/pgbus/events/_tabs.html.erb +13 -0
- data/app/views/pgbus/events/index.html.erb +27 -48
- data/app/views/pgbus/events/show.html.erb +25 -7
- data/app/views/pgbus/insights/_chart_card.html.erb +21 -0
- data/app/views/pgbus/insights/_latency_table.html.erb +20 -0
- data/app/views/pgbus/insights/_status_table.html.erb +19 -0
- data/app/views/pgbus/insights/_throughput_table.html.erb +18 -0
- data/app/views/pgbus/insights/show.html.erb +83 -100
- data/app/views/pgbus/jobs/_list.html.erb +64 -0
- data/app/views/pgbus/jobs/_row.html.erb +107 -0
- data/app/views/pgbus/jobs/_tabs.html.erb +14 -0
- data/app/views/pgbus/jobs/index.html.erb +10 -10
- data/app/views/pgbus/jobs/show.html.erb +18 -20
- data/app/views/pgbus/locks/_concurrency.html.erb +25 -23
- data/app/views/pgbus/locks/_uniqueness.html.erb +20 -22
- data/app/views/pgbus/outbox/index.html.erb +30 -27
- data/app/views/pgbus/processes/_processes_table.html.erb +6 -25
- data/app/views/pgbus/processes/_row.html.erb +48 -0
- data/app/views/pgbus/processes/_status.html.erb +4 -0
- data/app/views/pgbus/queues/_queues_list.html.erb +28 -32
- data/app/views/pgbus/queues/show.html.erb +69 -118
- data/app/views/pgbus/recurring_tasks/_tasks_table.html.erb +75 -76
- data/app/views/pgbus/recurring_tasks/index.html.erb +1 -1
- data/app/views/pgbus/recurring_tasks/show.html.erb +45 -51
- data/app/views/pgbus/shared/_empty_row.html.erb +2 -0
- data/app/views/pgbus/shared/_pager.html.erb +34 -0
- data/config/i18n-tasks.yml +11 -2
- data/config/locales/da.yml +405 -113
- data/config/locales/de.yml +405 -113
- data/config/locales/en.yml +405 -113
- data/config/locales/es.yml +404 -112
- data/config/locales/fi.yml +404 -112
- data/config/locales/fr.yml +406 -114
- data/config/locales/it.yml +405 -113
- data/config/locales/ja.yml +405 -113
- data/config/locales/nb.yml +405 -113
- data/config/locales/nl.yml +405 -113
- data/config/locales/pt.yml +406 -114
- data/config/locales/sv.yml +404 -112
- data/config/routes.rb +1 -1
- data/lib/generators/pgbus/add_presence_generator.rb +2 -1
- data/lib/generators/pgbus/add_presence_seats_generator.rb +45 -0
- data/lib/generators/pgbus/templates/add_presence.rb.erb +32 -7
- data/lib/generators/pgbus/templates/add_presence_seats.rb.erb +38 -0
- data/lib/generators/pgbus/templates/initializer.rb.erb +4 -0
- data/lib/pgbus/active_job/executor.rb +16 -6
- data/lib/pgbus/cli/dlq.rb +32 -5
- data/lib/pgbus/client.rb +4 -2
- data/lib/pgbus/configuration/presence_settings.rb +103 -0
- data/lib/pgbus/configuration.rb +51 -2
- data/lib/pgbus/dead_letter_header.rb +129 -0
- data/lib/pgbus/doctor.rb +8 -4
- data/lib/pgbus/engine.rb +13 -7
- data/lib/pgbus/event_bus/handler.rb +18 -11
- data/lib/pgbus/event_bus/registry.rb +6 -0
- data/lib/pgbus/failed_event_recorder.rb +34 -0
- data/lib/pgbus/generators/migration_detector.rb +9 -1
- data/lib/pgbus/instrumentation.rb +2 -1
- data/lib/pgbus/mcp/base_tool.rb +25 -0
- data/lib/pgbus/mcp/tools/concurrency_tool.rb +23 -4
- data/lib/pgbus/mcp/tools/dlq_detail_tool.rb +4 -2
- data/lib/pgbus/mcp/tools/dlq_tool.rb +10 -4
- data/lib/pgbus/mcp/tools/locks_tool.rb +23 -5
- data/lib/pgbus/mcp/tools/recurring_tool.rb +33 -4
- data/lib/pgbus/outbox/poller.rb +1 -1
- data/lib/pgbus/process/consumer.rb +53 -3
- data/lib/pgbus/process/dispatcher.rb +1 -1
- data/lib/pgbus/process/supervisor.rb +32 -11
- data/lib/pgbus/process/worker.rb +45 -8
- data/lib/pgbus/recurring/scheduler.rb +2 -1
- data/lib/pgbus/streams/presence.rb +317 -81
- data/lib/pgbus/version.rb +1 -1
- data/lib/pgbus/web/data_source/dashboard_signals.rb +170 -0
- data/lib/pgbus/web/data_source/dead_letter.rb +142 -0
- data/lib/pgbus/web/data_source/event_list.rb +161 -0
- data/lib/pgbus/web/data_source/job_list.rb +323 -0
- data/lib/pgbus/web/data_source/list_counts.rb +80 -0
- data/lib/pgbus/web/data_source/process_list.rb +69 -0
- data/lib/pgbus/web/data_source/queue_summary.rb +122 -0
- data/lib/pgbus/web/data_source.rb +132 -254
- data/lib/pgbus/web/dead_letter_reason.rb +81 -0
- data/lib/pgbus/web/event_state.rb +71 -0
- data/lib/pgbus/web/health_app.rb +7 -3
- data/lib/pgbus/web/health_verdict.rb +78 -0
- data/lib/pgbus/web/insights_charts.rb +84 -0
- data/lib/pgbus/web/job_state.rb +111 -0
- data/lib/pgbus/web/process_activity.rb +97 -0
- data/lib/pgbus/web/process_state.rb +187 -0
- data/lib/pgbus/web/queue_summary.rb +104 -0
- data/lib/pgbus/web/stream_app.rb +18 -6
- data/lib/pgbus/web/streamer/connection.rb +7 -1
- data/lib/pgbus/web/streamer/falcon_connection.rb +7 -1
- data/lib/pgbus/web/streamer/heartbeat.rb +9 -3
- data/lib/pgbus/web/streamer/instance.rb +2 -1
- data/lib/pgbus/web/streamer/presence_tracker.rb +155 -0
- data/lib/pgbus/web/streamer/stream_event_dispatcher.rb +8 -37
- data/lib/pgbus/web/time_format.rb +128 -0
- metadata +55 -4
- data/app/views/pgbus/events/_pending_table.html.erb +0 -169
- data/app/views/pgbus/jobs/_enqueued_table.html.erb +0 -118
- data/app/views/pgbus/jobs/_failed_table.html.erb +0 -76
|
@@ -1,77 +1,90 @@
|
|
|
1
1
|
<div class="mb-3">
|
|
2
|
-
<%=
|
|
2
|
+
<%= pgbus_link_to "← #{t("pgbus.queues.show.back")}", pgbus.queues_path %>
|
|
3
3
|
</div>
|
|
4
|
-
<div class="flex items-center justify-between mb-6">
|
|
4
|
+
<div class="flex flex-wrap items-center justify-between gap-4 mb-6">
|
|
5
5
|
<div>
|
|
6
6
|
<h1 class="text-2xl font-bold text-gray-900 dark:text-white">
|
|
7
7
|
<%= @queue&.dig(:name) || params[:name] %>
|
|
8
|
-
|
|
9
|
-
<span class="inline-flex items-center rounded-full bg-yellow-100 px-2.5 py-0.5 text-xs font-medium text-yellow-800"><%= t("pgbus.queues.queues_list.paused") %></span>
|
|
10
|
-
<% end %>
|
|
8
|
+
<%= pgbus_paused_badge(@paused) %>
|
|
11
9
|
</h1>
|
|
12
|
-
<% if @queue %>
|
|
13
|
-
<p class="text-sm text-gray-500 mt-1">
|
|
14
|
-
<%= t("pgbus.queues.show.depth") %> <span class="font-mono"><%= @queue[:queue_length] %></span> |
|
|
15
|
-
<%= t("pgbus.queues.show.visible") %> <span class="font-mono"><%= @queue[:queue_visible_length] %></span> |
|
|
16
|
-
<%= t("pgbus.queues.show.parked") %> <span class="font-mono"><%= @queue[:parked_length] %></span> |
|
|
17
|
-
<%= t("pgbus.queues.show.oldest") %> <span class="font-mono"><%= @queue[:oldest_msg_age_sec] || "—" %></span> |
|
|
18
|
-
<%= t("pgbus.queues.show.oldest_claimable") %> <span class="font-mono"><%= @queue[:oldest_claimable_age_sec] || "—" %></span> |
|
|
19
|
-
<%= t("pgbus.queues.show.total") %> <span class="font-mono"><%= pgbus_number(@queue[:total_messages]) %></span>
|
|
20
|
-
</p>
|
|
21
|
-
<% end %>
|
|
22
10
|
</div>
|
|
23
11
|
<div class="flex space-x-2">
|
|
24
12
|
<% if @paused %>
|
|
25
|
-
<%=
|
|
26
|
-
method: :post,
|
|
27
|
-
class: "rounded-md bg-green-600 px-3 py-2 text-sm font-medium text-white hover:bg-green-500" %>
|
|
13
|
+
<%= pgbus_button_to t("pgbus.queues.show.resume"), pgbus.resume_queue_path(name: params[:name]),
|
|
14
|
+
method: :post, variant: :success %>
|
|
28
15
|
<% else %>
|
|
29
|
-
<%=
|
|
30
|
-
method: :post,
|
|
31
|
-
class: "rounded-md bg-yellow-500 px-3 py-2 text-sm font-medium text-white hover:bg-yellow-400",
|
|
16
|
+
<%= pgbus_button_to t("pgbus.queues.show.pause"), pgbus.pause_queue_path(name: params[:name]),
|
|
17
|
+
method: :post, variant: :warning,
|
|
32
18
|
data: { turbo_confirm: t("pgbus.queues.show.pause_confirm") } %>
|
|
33
19
|
<% end %>
|
|
34
|
-
<%=
|
|
35
|
-
method: :post,
|
|
36
|
-
class: "rounded-md bg-red-600 px-3 py-2 text-sm font-medium text-white hover:bg-red-500",
|
|
20
|
+
<%= pgbus_button_to t("pgbus.queues.show.purge_queue"), pgbus.purge_queue_path(name: params[:name]),
|
|
21
|
+
method: :post, variant: :danger,
|
|
37
22
|
data: { turbo_confirm: t("pgbus.queues.show.purge_confirm") } %>
|
|
38
|
-
<%=
|
|
39
|
-
method: :delete,
|
|
40
|
-
class: "rounded-md bg-red-800 px-3 py-2 text-sm font-medium text-white hover:bg-red-700",
|
|
23
|
+
<%= pgbus_button_to t("pgbus.queues.show.delete_queue"), pgbus.queue_path(name: params[:name]),
|
|
24
|
+
method: :delete, variant: :destructive,
|
|
41
25
|
data: { turbo_confirm: t("pgbus.queues.show.delete_confirm") } %>
|
|
42
26
|
</div>
|
|
43
27
|
</div>
|
|
44
28
|
|
|
29
|
+
<%# The queue in words (Pgbus::Web::QueueSummary), then its numbers. %>
|
|
30
|
+
<section aria-label="<%= t("pgbus.queues.show.summary_label") %>" data-testid="queue-summary" class="mb-6 space-y-2">
|
|
31
|
+
<% @summary.each do |line| %>
|
|
32
|
+
<p data-summary-line="<%= line.key %>" class="rounded-md px-3 py-2 text-sm ring-1 <%= pgbus_queue_summary_classes(line.tone) %>"><%= pgbus_queue_summary_line(line) %></p>
|
|
33
|
+
<% end %>
|
|
34
|
+
<% if @drainers[:siblings].any? %>
|
|
35
|
+
<p class="text-sm text-gray-700 dark:text-gray-200">
|
|
36
|
+
<%= t("pgbus.queues.show.other_levels") %>
|
|
37
|
+
<% @drainers[:siblings].each do |sibling| %>
|
|
38
|
+
<%= pgbus_link_to sibling, pgbus.queue_path(name: sibling), size: :sm, class: "font-mono" %>
|
|
39
|
+
<% end %>
|
|
40
|
+
</p>
|
|
41
|
+
<% end %>
|
|
42
|
+
</section>
|
|
43
|
+
|
|
44
|
+
<dl data-testid="queue-metrics" class="mb-6 grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-6">
|
|
45
|
+
<% [[:depth, pgbus_number(@queue[:queue_length])],
|
|
46
|
+
[:claimable, pgbus_number(@queue[:queue_visible_length])],
|
|
47
|
+
[:parked, pgbus_number(@queue[:parked_length])],
|
|
48
|
+
[:oldest_claimable, pgbus_duration(@queue[:oldest_claimable_age_sec])],
|
|
49
|
+
[:oldest, pgbus_duration(@queue[:oldest_msg_age_sec])],
|
|
50
|
+
[:total, pgbus_number(@queue[:total_messages])]].each do |key, value| %>
|
|
51
|
+
<div class="rounded-lg bg-white dark:bg-gray-800 px-4 py-3 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
52
|
+
<dt class="text-xs font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.queues.show.metrics.#{key}") %></dt>
|
|
53
|
+
<dd class="mt-1 text-lg font-semibold font-mono text-gray-900 dark:text-white"><%= value %></dd>
|
|
54
|
+
</div>
|
|
55
|
+
<% end %>
|
|
56
|
+
</dl>
|
|
57
|
+
|
|
45
58
|
<!-- Table Health -->
|
|
46
59
|
<% if @health && @health[:tables].any? %>
|
|
47
60
|
<div class="mb-6 overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
48
61
|
<div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700">
|
|
49
62
|
<h2 class="text-sm font-semibold text-gray-900 dark:text-white"><%= t("pgbus.queues.show.table_health.title") %></h2>
|
|
50
63
|
<% if @health[:oldest_transaction_age_sec] %>
|
|
51
|
-
<p class="text-xs text-gray-500 mt-1">
|
|
64
|
+
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">
|
|
52
65
|
<%= t("pgbus.queues.show.table_health.oldest_txn") %>
|
|
53
|
-
<span class="font-mono <%= @health[:oldest_transaction_age_sec] > 60 ? 'text-red-600 dark:text-red-400' : @health[:oldest_transaction_age_sec] > 30 ? 'text-amber-
|
|
66
|
+
<span class="font-mono <%= @health[:oldest_transaction_age_sec] > 60 ? 'text-red-600 dark:text-red-400' : @health[:oldest_transaction_age_sec] > 30 ? 'text-amber-700 dark:text-amber-400' : 'text-green-700 dark:text-green-400' %>"><%= pgbus_duration(@health[:oldest_transaction_age_sec]) %></span>
|
|
54
67
|
</p>
|
|
55
68
|
<% end %>
|
|
56
69
|
</div>
|
|
57
70
|
<table class="pgbus-table min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
|
58
71
|
<thead class="bg-gray-50 dark:bg-gray-900">
|
|
59
72
|
<tr>
|
|
60
|
-
<th class="px-4 py-2 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.table_health.headers.table") %></th>
|
|
61
|
-
<th class="px-4 py-2 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.table_health.headers.live") %></th>
|
|
62
|
-
<th class="px-4 py-2 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.table_health.headers.dead") %></th>
|
|
63
|
-
<th class="px-4 py-2 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.table_health.headers.bloat") %></th>
|
|
64
|
-
<th class="px-4 py-2 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.table_health.headers.last_vacuum") %></th>
|
|
73
|
+
<th class="px-4 py-2 text-left text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.queues.show.table_health.headers.table") %></th>
|
|
74
|
+
<th class="px-4 py-2 text-right text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.queues.show.table_health.headers.live") %></th>
|
|
75
|
+
<th class="px-4 py-2 text-right text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.queues.show.table_health.headers.dead") %></th>
|
|
76
|
+
<th class="px-4 py-2 text-right text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.queues.show.table_health.headers.bloat") %></th>
|
|
77
|
+
<th class="px-4 py-2 text-right text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.queues.show.table_health.headers.last_vacuum") %></th>
|
|
65
78
|
</tr>
|
|
66
79
|
</thead>
|
|
67
80
|
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
|
68
81
|
<% @health[:tables].each do |t| %>
|
|
69
|
-
<tr
|
|
70
|
-
<td class="px-4 py-2 text-sm font-mono text-gray-900 dark:text-white"><%= t[:table] %></td>
|
|
71
|
-
<td class="px-4 py-2 text-sm text-right text-gray-700 dark:text-gray-300"><%= pgbus_number(t[:live_tuples]) %></td>
|
|
72
|
-
<td class="px-4 py-2 text-sm text-right <%= t[:dead_tuples] > 1000 ? 'text-amber-
|
|
73
|
-
<td class="px-4 py-2 text-sm text-right <%= t[:bloat_ratio] > 0.2 ? 'text-red-600 dark:text-red-400 font-semibold' : t[:bloat_ratio] > 0.1 ? 'text-amber-
|
|
74
|
-
<td class="px-4 py-2 text-sm text-right text-gray-500 dark:text-gray-400"><%= t[:last_vacuum_ago_sec] ? pgbus_duration(t[:last_vacuum_ago_sec]) : "—" %></td>
|
|
82
|
+
<tr>
|
|
83
|
+
<td data-label="<%= t("pgbus.queues.show.table_health.headers.table") %>" class="px-4 py-2 text-sm font-mono text-gray-900 dark:text-white"><%= t[:table] %></td>
|
|
84
|
+
<td data-label="<%= t("pgbus.queues.show.table_health.headers.live") %>" class="px-4 py-2 text-sm text-right text-gray-700 dark:text-gray-300"><%= pgbus_number(t[:live_tuples]) %></td>
|
|
85
|
+
<td data-label="<%= t("pgbus.queues.show.table_health.headers.dead") %>" class="px-4 py-2 text-sm text-right <%= t[:dead_tuples] > 1000 ? 'text-amber-700 dark:text-amber-400 font-semibold' : 'text-gray-700 dark:text-gray-300' %>"><%= pgbus_number(t[:dead_tuples]) %></td>
|
|
86
|
+
<td data-label="<%= t("pgbus.queues.show.table_health.headers.bloat") %>" class="px-4 py-2 text-sm text-right <%= t[:bloat_ratio] > 0.2 ? 'text-red-600 dark:text-red-400 font-semibold' : t[:bloat_ratio] > 0.1 ? 'text-amber-700 dark:text-amber-400' : 'text-gray-500 dark:text-gray-400' %>"><%= (t[:bloat_ratio] * 100).round(1) %>%</td>
|
|
87
|
+
<td data-label="<%= t("pgbus.queues.show.table_health.headers.last_vacuum") %>" class="px-4 py-2 text-sm text-right text-gray-500 dark:text-gray-400"><%= t[:last_vacuum_ago_sec] ? pgbus_duration(t[:last_vacuum_ago_sec]) : "—" %></td>
|
|
75
88
|
</tr>
|
|
76
89
|
<% end %>
|
|
77
90
|
</tbody>
|
|
@@ -79,81 +92,19 @@
|
|
|
79
92
|
</div>
|
|
80
93
|
<% end %>
|
|
81
94
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
<
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<td colspan="5" class="p-0">
|
|
99
|
-
<details class="group">
|
|
100
|
-
<summary class="flex cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700/50 dark:bg-gray-900 list-none">
|
|
101
|
-
<span class="w-16 shrink-0 px-4 py-3 text-sm font-mono text-gray-900 dark:text-white"><%= m[:msg_id] %></span>
|
|
102
|
-
<span class="flex-1 px-4 py-3 text-sm font-medium text-gray-900 dark:text-white"><%= payload["job_class"] || "—" %></span>
|
|
103
|
-
<span class="w-28 shrink-0 px-4 py-3 text-sm text-gray-500"><%= pgbus_time_ago(m[:enqueued_at]) %></span>
|
|
104
|
-
<span class="w-16 shrink-0 px-4 py-3 text-sm text-gray-500"><%= m[:read_ct] %></span>
|
|
105
|
-
<span class="w-28 shrink-0 px-4 py-3 text-sm text-gray-500"><%= pgbus_time_ago(m[:vt]) %></span>
|
|
106
|
-
</summary>
|
|
107
|
-
<div class="px-4 pb-4 bg-gray-50 dark:bg-gray-900 border-t border-gray-100">
|
|
108
|
-
<div class="flex items-center mt-3 mb-3">
|
|
109
|
-
<span class="text-xs font-mono text-gray-400"><%= t("pgbus.queues.show.job_id") %> <%= payload["job_id"] %></span>
|
|
110
|
-
</div>
|
|
111
|
-
<div class="grid grid-cols-2 gap-4 mb-3">
|
|
112
|
-
<div>
|
|
113
|
-
<span class="text-xs font-medium text-gray-500"><%= t("pgbus.queues.show.arguments") %></span>
|
|
114
|
-
<pre class="text-xs text-gray-700 bg-white dark:bg-gray-800 rounded p-2 mt-1 overflow-x-auto max-h-40"><%= JSON.pretty_generate(payload["arguments"] || []) rescue "—" %></pre>
|
|
115
|
-
</div>
|
|
116
|
-
<div>
|
|
117
|
-
<span class="text-xs font-medium text-gray-500"><%= t("pgbus.queues.show.metadata") %></span>
|
|
118
|
-
<div class="text-xs text-gray-600 bg-white dark:bg-gray-800 rounded p-2 mt-1 space-y-1">
|
|
119
|
-
<% if payload["queue_name"] %><p><strong><%= t("pgbus.queues.show.metadata_labels.queue") %></strong> <%= payload["queue_name"] %></p><% end %>
|
|
120
|
-
<% if payload["priority"] %><p><strong><%= t("pgbus.queues.show.metadata_labels.priority") %></strong> <%= payload["priority"] %></p><% end %>
|
|
121
|
-
<% if payload["locale"] %><p><strong><%= t("pgbus.queues.show.metadata_labels.locale") %></strong> <%= payload["locale"] %></p><% end %>
|
|
122
|
-
<% if payload["timezone"] %><p><strong><%= t("pgbus.queues.show.metadata_labels.timezone") %></strong> <%= payload["timezone"] %></p><% end %>
|
|
123
|
-
<% if payload["scheduled_at"] %><p><strong><%= t("pgbus.queues.show.metadata_labels.scheduled") %></strong> <%= payload["scheduled_at"] %></p><% end %>
|
|
124
|
-
<% if m[:vt] %><p><strong><%= t("pgbus.queues.show.metadata_labels.visible_at") %></strong> <%= m[:vt] %></p><% end %>
|
|
125
|
-
<% if m[:last_read_at] %><p><strong><%= t("pgbus.queues.show.metadata_labels.last_read") %></strong> <%= m[:last_read_at] %></p><% end %>
|
|
126
|
-
</div>
|
|
127
|
-
</div>
|
|
128
|
-
</div>
|
|
129
|
-
<details class="mt-2">
|
|
130
|
-
<summary class="text-xs font-medium text-gray-500 cursor-pointer hover:text-gray-700"><%= t("pgbus.queues.show.full_json_payload") %></summary>
|
|
131
|
-
<pre class="text-xs text-gray-600 bg-white dark:bg-gray-800 rounded p-2 mt-1 overflow-x-auto max-h-96"><%= JSON.pretty_generate(payload) rescue m[:message] %></pre>
|
|
132
|
-
</details>
|
|
133
|
-
<% if m[:headers] %>
|
|
134
|
-
<details class="mt-2">
|
|
135
|
-
<summary class="text-xs font-medium text-gray-500 cursor-pointer hover:text-gray-700"><%= t("pgbus.queues.show.headers_section") %></summary>
|
|
136
|
-
<pre class="text-xs text-gray-600 bg-white dark:bg-gray-800 rounded p-2 mt-1 overflow-x-auto"><%= JSON.pretty_generate(JSON.parse(m[:headers])) rescue m[:headers] %></pre>
|
|
137
|
-
</details>
|
|
138
|
-
<% end %>
|
|
139
|
-
<div class="flex space-x-2 mt-3 pt-3 border-t border-gray-200 dark:border-gray-700">
|
|
140
|
-
<%= button_to t("pgbus.queues.show.retry"), pgbus.retry_message_queue_path(name: params[:name], msg_id: m[:msg_id]),
|
|
141
|
-
method: :post,
|
|
142
|
-
class: "rounded-md bg-indigo-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-indigo-500",
|
|
143
|
-
data: { turbo_confirm: t("pgbus.queues.show.retry_confirm") } %>
|
|
144
|
-
<%= button_to t("pgbus.queues.show.discard"), pgbus.discard_message_queue_path(name: params[:name], msg_id: m[:msg_id]),
|
|
145
|
-
method: :post,
|
|
146
|
-
class: "rounded-md bg-red-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-red-500",
|
|
147
|
-
data: { turbo_confirm: t("pgbus.queues.show.discard_confirm") } %>
|
|
148
|
-
</div>
|
|
149
|
-
</div>
|
|
150
|
-
</details>
|
|
151
|
-
</td>
|
|
152
|
-
</tr>
|
|
153
|
-
<% end %>
|
|
154
|
-
<% if @messages.empty? %>
|
|
155
|
-
<tr><td colspan="5" class="px-4 py-8 text-center text-sm text-gray-400"><%= t("pgbus.queues.show.empty") %></td></tr>
|
|
156
|
-
<% end %>
|
|
157
|
-
</tbody>
|
|
158
|
-
</table>
|
|
159
|
-
</div>
|
|
95
|
+
<% if @dlq %>
|
|
96
|
+
<%# DLQ tables are not part of the unified list; their messages live on the Dead Letter page. %>
|
|
97
|
+
<div data-testid="dlq-pointer" class="rounded-lg bg-white dark:bg-gray-800 px-4 py-4 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
98
|
+
<p class="text-sm text-gray-700 dark:text-gray-200">
|
|
99
|
+
<%= t("pgbus.queues.show.dlq_pointer", logical: @drainers[:logical], count: @queue[:queue_length].to_i) %>
|
|
100
|
+
<%= pgbus_link_to t("pgbus.queues.show.dlq_link"), pgbus.dead_letter_index_path(dlq: params[:name]), size: :sm %>
|
|
101
|
+
</p>
|
|
102
|
+
</div>
|
|
103
|
+
<% else %>
|
|
104
|
+
<%# Scoped to this physical table. Known warts of job_rows on a _pN table:
|
|
105
|
+
blocked rows match the logical name, so a queue's blocked jobs show on
|
|
106
|
+
every level's page (they are parked before a level is chosen), and a
|
|
107
|
+
failed event whose message sits in a sibling level reads as an orphan. %>
|
|
108
|
+
<%= render "pgbus/jobs/tabs", state: @state, counts: @counts, list_path: @list_path %>
|
|
109
|
+
<%= render "pgbus/jobs/list" %>
|
|
110
|
+
<% end %>
|
|
@@ -1,80 +1,79 @@
|
|
|
1
|
-
<turbo-frame id="recurring-tasks" data-auto-refresh data-
|
|
1
|
+
<turbo-frame id="recurring-tasks" data-auto-refresh data-turbo-action="advance"
|
|
2
|
+
data-src="<%= pgbus.recurring_tasks_path(request.query_parameters.merge(frame: "recurring_tasks")) %>">
|
|
2
3
|
<div class="rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
3
|
-
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<
|
|
4
|
+
<table class="pgbus-table min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
|
5
|
+
<thead class="bg-gray-50 dark:bg-gray-900">
|
|
6
|
+
<tr>
|
|
7
|
+
<th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.tasks_table.headers.task") %></th>
|
|
8
|
+
<th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.tasks_table.headers.schedule") %></th>
|
|
9
|
+
<th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.tasks_table.headers.queue") %></th>
|
|
10
|
+
<th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.tasks_table.headers.last_run") %></th>
|
|
11
|
+
<th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.tasks_table.headers.next_run") %></th>
|
|
12
|
+
<th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.tasks_table.headers.status") %></th>
|
|
13
|
+
<th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.tasks_table.headers.actions") %></th>
|
|
14
|
+
</tr>
|
|
15
|
+
</thead>
|
|
16
|
+
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
|
17
|
+
<% @recurring_tasks.each do |task| %>
|
|
18
|
+
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700/50">
|
|
19
|
+
<td data-label="<%= t("pgbus.recurring_tasks.tasks_table.headers.task") %>" class="px-4 py-3">
|
|
20
|
+
<div>
|
|
21
|
+
<%= pgbus_link_to task[:key], pgbus.recurring_task_path(task[:id]), data: { turbo_frame: "_top" } %>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="text-xs text-gray-500 dark:text-gray-400"><%= task[:class_name] || task[:command]&.truncate(40) %></div>
|
|
24
|
+
<% if task[:description] %>
|
|
25
|
+
<div class="text-xs text-gray-500 dark:text-gray-400 mt-0.5"><%= task[:description] %></div>
|
|
26
|
+
<% end %>
|
|
27
|
+
</td>
|
|
28
|
+
<td data-label="<%= t("pgbus.recurring_tasks.tasks_table.headers.schedule") %>" class="px-4 py-3">
|
|
29
|
+
<div class="text-sm text-gray-900 dark:text-white"><%= task[:schedule] %></div>
|
|
30
|
+
<% if task[:human_schedule] && task[:human_schedule] != task[:schedule] %>
|
|
31
|
+
<div class="text-xs text-gray-500 dark:text-gray-400"><%= task[:human_schedule] %></div>
|
|
32
|
+
<% end %>
|
|
33
|
+
</td>
|
|
34
|
+
<td data-label="<%= t("pgbus.recurring_tasks.tasks_table.headers.queue") %>" class="px-4 py-3 text-sm text-gray-600 dark:text-gray-300">
|
|
35
|
+
<%= task[:queue_name] || t("pgbus.recurring_tasks.tasks_table.default_queue") %>
|
|
36
|
+
</td>
|
|
37
|
+
<td data-label="<%= t("pgbus.recurring_tasks.tasks_table.headers.last_run") %>" class="px-4 py-3 text-sm text-gray-600 dark:text-gray-300">
|
|
38
|
+
<%= task[:last_run_at] ? pgbus_time(task[:last_run_at]) : t("pgbus.recurring_tasks.tasks_table.never") %>
|
|
39
|
+
</td>
|
|
40
|
+
<td data-label="<%= t("pgbus.recurring_tasks.tasks_table.headers.next_run") %>" class="px-4 py-3 text-sm text-gray-600 dark:text-gray-300">
|
|
41
|
+
<% if task[:enabled] && task[:next_run_at] %>
|
|
42
|
+
<%= pgbus_time(task[:next_run_at]) %>
|
|
43
|
+
<% else %>
|
|
44
|
+
<span class="text-gray-500 dark:text-gray-400">—</span>
|
|
45
|
+
<% end %>
|
|
46
|
+
</td>
|
|
47
|
+
<td data-label="<%= t("pgbus.recurring_tasks.tasks_table.headers.status") %>" class="px-4 py-3">
|
|
48
|
+
<% if task[:enabled] %>
|
|
49
|
+
<%= pgbus_recurring_health_badge(task) %>
|
|
50
|
+
<% else %>
|
|
51
|
+
<span class="inline-flex items-center rounded-full bg-gray-100 dark:bg-gray-700 px-2.5 py-0.5 text-xs font-medium text-gray-600 dark:text-gray-300">
|
|
52
|
+
<%= t("pgbus.recurring_tasks.tasks_table.disabled") %>
|
|
53
|
+
</span>
|
|
54
|
+
<% end %>
|
|
55
|
+
</td>
|
|
56
|
+
<td data-label="<%= t("pgbus.recurring_tasks.tasks_table.headers.actions") %>" class="px-4 py-3 text-right space-x-1">
|
|
57
|
+
<%= pgbus_button_to task[:enabled] ? t("pgbus.recurring_tasks.tasks_table.disable") : t("pgbus.recurring_tasks.tasks_table.enable"),
|
|
58
|
+
pgbus.toggle_recurring_task_path(task[:id]),
|
|
59
|
+
variant: task[:enabled] ? :warning : :success, size: :sm %>
|
|
60
|
+
<% if task[:enabled] %>
|
|
61
|
+
<%= pgbus_button_to t("pgbus.recurring_tasks.tasks_table.run_now"),
|
|
62
|
+
pgbus.enqueue_recurring_task_path(task[:id]), variant: :primary, size: :sm %>
|
|
63
|
+
<% end %>
|
|
64
|
+
</td>
|
|
19
65
|
</tr>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<div class="text-xs text-gray-400 mt-0.5"><%= task[:description] %></div>
|
|
33
|
-
<% end %>
|
|
34
|
-
</td>
|
|
35
|
-
<td data-label="Schedule" class="px-4 py-3">
|
|
36
|
-
<div class="text-sm text-gray-900 dark:text-white"><%= task[:schedule] %></div>
|
|
37
|
-
<% if task[:human_schedule] && task[:human_schedule] != task[:schedule] %>
|
|
38
|
-
<div class="text-xs text-gray-400"><%= task[:human_schedule] %></div>
|
|
39
|
-
<% end %>
|
|
40
|
-
</td>
|
|
41
|
-
<td data-label="Queue" class="px-4 py-3 text-sm text-gray-600">
|
|
42
|
-
<%= task[:queue_name] || t("pgbus.recurring_tasks.tasks_table.default_queue") %>
|
|
43
|
-
</td>
|
|
44
|
-
<td data-label="Last Run" class="px-4 py-3 text-sm text-gray-600">
|
|
45
|
-
<%= task[:last_run_at] ? pgbus_time_ago(task[:last_run_at]) : t("pgbus.recurring_tasks.tasks_table.never") %>
|
|
46
|
-
</td>
|
|
47
|
-
<td data-label="Next Run" class="px-4 py-3 text-sm text-gray-600">
|
|
48
|
-
<% if task[:enabled] && task[:next_run_at] %>
|
|
49
|
-
<%= pgbus_time_ago_future(task[:next_run_at]) %>
|
|
50
|
-
<% else %>
|
|
51
|
-
<span class="text-gray-400">—</span>
|
|
52
|
-
<% end %>
|
|
53
|
-
</td>
|
|
54
|
-
<td data-label="Status" class="px-4 py-3">
|
|
55
|
-
<% if task[:enabled] %>
|
|
56
|
-
<%= pgbus_recurring_health_badge(task) %>
|
|
57
|
-
<% else %>
|
|
58
|
-
<span class="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-600">
|
|
59
|
-
<%= t("pgbus.recurring_tasks.tasks_table.disabled") %>
|
|
60
|
-
</span>
|
|
61
|
-
<% end %>
|
|
62
|
-
</td>
|
|
63
|
-
<td data-label="Actions" class="px-4 py-3 text-right space-x-1">
|
|
64
|
-
<%= button_to task[:enabled] ? t("pgbus.recurring_tasks.tasks_table.disable") : t("pgbus.recurring_tasks.tasks_table.enable"),
|
|
65
|
-
pgbus.toggle_recurring_task_path(task[:id]),
|
|
66
|
-
class: "inline-flex items-center rounded px-2 py-1 text-xs font-medium " \
|
|
67
|
-
"#{task[:enabled] ? 'bg-yellow-100 text-yellow-700 hover:bg-yellow-200' : 'bg-green-100 text-green-700 hover:bg-green-200'}" %>
|
|
68
|
-
<% if task[:enabled] %>
|
|
69
|
-
<%= button_to t("pgbus.recurring_tasks.tasks_table.run_now"),
|
|
70
|
-
pgbus.enqueue_recurring_task_path(task[:id]),
|
|
71
|
-
class: "inline-flex items-center rounded bg-blue-100 px-2 py-1 text-xs font-medium text-blue-700 hover:bg-blue-200" %>
|
|
72
|
-
<% end %>
|
|
73
|
-
</td>
|
|
74
|
-
</tr>
|
|
75
|
-
<% end %>
|
|
76
|
-
</tbody>
|
|
77
|
-
</table>
|
|
78
|
-
<% end %>
|
|
66
|
+
<% end %>
|
|
67
|
+
<% if @recurring_tasks.empty? %>
|
|
68
|
+
<%= render "pgbus/shared/empty_row", colspan: 7,
|
|
69
|
+
message: safe_join([content_tag(:p, t("pgbus.recurring_tasks.tasks_table.empty_title"), class: "text-lg font-medium"),
|
|
70
|
+
content_tag(:p, t("pgbus.recurring_tasks.tasks_table.empty_hint"), class: "mt-1")]) %>
|
|
71
|
+
<% end %>
|
|
72
|
+
</tbody>
|
|
73
|
+
</table>
|
|
74
|
+
<%= render "pgbus/shared/pager", page: @page, per_page: @per_page, shown: @recurring_tasks.size,
|
|
75
|
+
total_count: @recurring_tasks_count.total,
|
|
76
|
+
has_more: @recurring_tasks_count.capped? && @recurring_tasks.size == @per_page,
|
|
77
|
+
page_path: ->(n) { pgbus.recurring_tasks_path(page: n) } %>
|
|
79
78
|
</div>
|
|
80
79
|
</turbo-frame>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div class="flex items-center justify-between mb-6">
|
|
2
2
|
<h1 class="text-2xl font-bold text-gray-900 dark:text-white"><%= t("pgbus.recurring_tasks.index.title") %></h1>
|
|
3
|
-
<span class="text-sm text-gray-500"><%= t("pgbus.recurring_tasks.index.task_count", count: @
|
|
3
|
+
<span class="text-sm text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.index.task_count", count: @recurring_tasks_count.total) %></span>
|
|
4
4
|
</div>
|
|
5
5
|
|
|
6
6
|
<%= render "pgbus/recurring_tasks/tasks_table" %>
|
|
@@ -2,87 +2,84 @@
|
|
|
2
2
|
<div class="flex items-center justify-between">
|
|
3
3
|
<div>
|
|
4
4
|
<h1 class="text-2xl font-bold text-gray-900 dark:text-white"><%= @task[:key] %></h1>
|
|
5
|
-
<p class="mt-1 text-sm text-gray-500"><%= @task[:class_name] || @task[:command] %></p>
|
|
5
|
+
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400"><%= @task[:class_name] || @task[:command] %></p>
|
|
6
6
|
</div>
|
|
7
7
|
<div class="flex space-x-2">
|
|
8
|
-
<%=
|
|
8
|
+
<%= pgbus_button_to @task[:enabled] ? t("pgbus.recurring_tasks.show.disable") : t("pgbus.recurring_tasks.show.enable"),
|
|
9
9
|
pgbus.toggle_recurring_task_path(@task[:id]),
|
|
10
|
-
|
|
11
|
-
"#{@task[:enabled] ? 'bg-yellow-100 text-yellow-700 hover:bg-yellow-200' : 'bg-green-100 text-green-700 hover:bg-green-200'}" %>
|
|
10
|
+
variant: @task[:enabled] ? :warning : :success %>
|
|
12
11
|
<% if @task[:enabled] %>
|
|
13
|
-
<%=
|
|
14
|
-
pgbus.enqueue_recurring_task_path(@task[:id]),
|
|
15
|
-
class: "inline-flex items-center rounded-md bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700" %>
|
|
12
|
+
<%= pgbus_button_to t("pgbus.recurring_tasks.show.run_now"),
|
|
13
|
+
pgbus.enqueue_recurring_task_path(@task[:id]), variant: :primary %>
|
|
16
14
|
<% end %>
|
|
17
|
-
<%=
|
|
18
|
-
class: "inline-flex items-center rounded-md bg-gray-100 px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-200" %>
|
|
15
|
+
<%= pgbus_link_to t("pgbus.recurring_tasks.show.back"), pgbus.recurring_tasks_path, variant: :secondary %>
|
|
19
16
|
</div>
|
|
20
17
|
</div>
|
|
21
18
|
</div>
|
|
22
19
|
|
|
23
20
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
|
|
24
21
|
<div class="rounded-lg bg-white dark:bg-gray-800 p-5 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
25
|
-
<p class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.schedule") %></p>
|
|
22
|
+
<p class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.show.schedule") %></p>
|
|
26
23
|
<p class="mt-1 text-lg font-semibold text-gray-900 dark:text-white"><%= @task[:schedule] %></p>
|
|
27
24
|
<% if @task[:human_schedule] && @task[:human_schedule] != @task[:schedule] %>
|
|
28
|
-
<p class="text-xs text-gray-400"><%= @task[:human_schedule] %></p>
|
|
25
|
+
<p class="text-xs text-gray-500 dark:text-gray-400"><%= @task[:human_schedule] %></p>
|
|
29
26
|
<% end %>
|
|
30
27
|
</div>
|
|
31
28
|
|
|
32
29
|
<div class="rounded-lg bg-white dark:bg-gray-800 p-5 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
33
|
-
<p class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.next_run") %></p>
|
|
30
|
+
<p class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.show.next_run") %></p>
|
|
34
31
|
<% if @task[:enabled] && @task[:next_run_at] %>
|
|
35
|
-
<p class="mt-1 text-lg font-semibold text-gray-900 dark:text-white"><%=
|
|
36
|
-
<p class="text-xs text-gray-400"><%= @task[:next_run_at]
|
|
32
|
+
<p class="mt-1 text-lg font-semibold text-gray-900 dark:text-white"><%= pgbus_time(@task[:next_run_at], clock: true) %></p>
|
|
33
|
+
<p class="text-xs text-gray-500 dark:text-gray-400"><%= pgbus_absolute_time(@task[:next_run_at]) %></p>
|
|
37
34
|
<% else %>
|
|
38
|
-
<p class="mt-1 text-lg font-semibold text-gray-400">—</p>
|
|
35
|
+
<p class="mt-1 text-lg font-semibold text-gray-500 dark:text-gray-400">—</p>
|
|
39
36
|
<% end %>
|
|
40
37
|
</div>
|
|
41
38
|
|
|
42
39
|
<div class="rounded-lg bg-white dark:bg-gray-800 p-5 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
43
|
-
<p class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.status") %></p>
|
|
44
|
-
<p class="mt-1"><%= @task[:enabled] ? pgbus_recurring_health_badge(@task) : content_tag(:span, t("pgbus.recurring_tasks.show.disabled"), class: "inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-600") %></p>
|
|
40
|
+
<p class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.show.status") %></p>
|
|
41
|
+
<p class="mt-1"><%= @task[:enabled] ? pgbus_recurring_health_badge(@task) : content_tag(:span, t("pgbus.recurring_tasks.show.disabled"), class: "inline-flex items-center rounded-full bg-gray-100 dark:bg-gray-700 px-2.5 py-0.5 text-xs font-medium text-gray-600 dark:text-gray-300") %></p>
|
|
45
42
|
</div>
|
|
46
43
|
</div>
|
|
47
44
|
|
|
48
45
|
<div class="rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700 mb-8">
|
|
49
|
-
<div class="px-4 py-3 border-b border-gray-200">
|
|
46
|
+
<div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700">
|
|
50
47
|
<h2 class="text-lg font-medium text-gray-900 dark:text-white"><%= t("pgbus.recurring_tasks.show.configuration") %></h2>
|
|
51
48
|
</div>
|
|
52
49
|
<div class="p-4">
|
|
53
50
|
<dl class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
54
51
|
<div>
|
|
55
|
-
<dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.job_class") %></dt>
|
|
52
|
+
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.show.labels.job_class") %></dt>
|
|
56
53
|
<dd class="mt-1 text-sm text-gray-900 dark:text-white"><%= @task[:class_name] || "—" %></dd>
|
|
57
54
|
</div>
|
|
58
55
|
<% if @task[:command] %>
|
|
59
56
|
<div>
|
|
60
|
-
<dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.command") %></dt>
|
|
57
|
+
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.show.labels.command") %></dt>
|
|
61
58
|
<dd class="mt-1 text-sm text-gray-900 dark:text-white font-mono text-xs"><%= @task[:command] %></dd>
|
|
62
59
|
</div>
|
|
63
60
|
<% end %>
|
|
64
61
|
<div>
|
|
65
|
-
<dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.queue") %></dt>
|
|
62
|
+
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.show.labels.queue") %></dt>
|
|
66
63
|
<dd class="mt-1 text-sm text-gray-900 dark:text-white"><%= @task[:queue_name] || t("pgbus.recurring_tasks.show.default_queue") %></dd>
|
|
67
64
|
</div>
|
|
68
65
|
<div>
|
|
69
|
-
<dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.priority") %></dt>
|
|
66
|
+
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.show.labels.priority") %></dt>
|
|
70
67
|
<dd class="mt-1 text-sm text-gray-900 dark:text-white"><%= @task[:priority] %></dd>
|
|
71
68
|
</div>
|
|
72
69
|
<% if @task[:arguments]&.any? %>
|
|
73
70
|
<div class="sm:col-span-2">
|
|
74
|
-
<dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.arguments") %></dt>
|
|
71
|
+
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.show.labels.arguments") %></dt>
|
|
75
72
|
<dd class="mt-1 text-sm text-gray-900 dark:text-white font-mono text-xs"><%= @task[:arguments].inspect %></dd>
|
|
76
73
|
</div>
|
|
77
74
|
<% end %>
|
|
78
75
|
<% if @task[:description] %>
|
|
79
76
|
<div class="sm:col-span-2">
|
|
80
|
-
<dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.description") %></dt>
|
|
77
|
+
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.show.labels.description") %></dt>
|
|
81
78
|
<dd class="mt-1 text-sm text-gray-900 dark:text-white"><%= @task[:description] %></dd>
|
|
82
79
|
</div>
|
|
83
80
|
<% end %>
|
|
84
81
|
<div>
|
|
85
|
-
<dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.source") %></dt>
|
|
82
|
+
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.show.labels.source") %></dt>
|
|
86
83
|
<dd class="mt-1 text-sm text-gray-900 dark:text-white"><%= @task[:static] ? t("pgbus.recurring_tasks.show.source_config") : t("pgbus.recurring_tasks.show.source_dynamic") %></dd>
|
|
87
84
|
</div>
|
|
88
85
|
</dl>
|
|
@@ -90,33 +87,30 @@
|
|
|
90
87
|
</div>
|
|
91
88
|
|
|
92
89
|
<div class="rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
93
|
-
<div class="px-4 py-3 border-b border-gray-200">
|
|
90
|
+
<div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700">
|
|
94
91
|
<h2 class="text-lg font-medium text-gray-900 dark:text-white"><%= t("pgbus.recurring_tasks.show.recent_executions") %></h2>
|
|
95
92
|
</div>
|
|
96
|
-
|
|
97
|
-
<
|
|
98
|
-
<
|
|
99
|
-
<
|
|
100
|
-
|
|
101
|
-
|
|
93
|
+
<table class="pgbus-table min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
|
94
|
+
<thead class="bg-gray-50 dark:bg-gray-900">
|
|
95
|
+
<tr>
|
|
96
|
+
<th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.show.execution_headers.scheduled_for") %></th>
|
|
97
|
+
<th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500 dark:text-gray-400"><%= t("pgbus.recurring_tasks.show.execution_headers.enqueued_at") %></th>
|
|
98
|
+
</tr>
|
|
99
|
+
</thead>
|
|
100
|
+
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
|
101
|
+
<% Array(@task[:executions]).each do |exec| %>
|
|
102
|
+
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700/50">
|
|
103
|
+
<td data-label="<%= t("pgbus.recurring_tasks.show.execution_headers.scheduled_for") %>" class="px-4 py-3 text-sm text-gray-900 dark:text-white">
|
|
104
|
+
<%= pgbus_timestamp(exec[:run_at]) %>
|
|
105
|
+
</td>
|
|
106
|
+
<td data-label="<%= t("pgbus.recurring_tasks.show.execution_headers.enqueued_at") %>" class="px-4 py-3 text-sm text-gray-600 dark:text-gray-300">
|
|
107
|
+
<%= pgbus_time(exec[:created_at]) %>
|
|
108
|
+
</td>
|
|
102
109
|
</tr>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
</td>
|
|
110
|
-
<td class="px-4 py-3 text-sm text-gray-600">
|
|
111
|
-
<%= exec[:created_at] ? pgbus_time_ago(exec[:created_at]) : "—" %>
|
|
112
|
-
</td>
|
|
113
|
-
</tr>
|
|
114
|
-
<% end %>
|
|
115
|
-
</tbody>
|
|
116
|
-
</table>
|
|
117
|
-
<% else %>
|
|
118
|
-
<div class="p-8 text-center text-gray-500">
|
|
119
|
-
<p><%= t("pgbus.recurring_tasks.show.no_executions") %></p>
|
|
120
|
-
</div>
|
|
121
|
-
<% end %>
|
|
110
|
+
<% end %>
|
|
111
|
+
<% if Array(@task[:executions]).empty? %>
|
|
112
|
+
<%= render "pgbus/shared/empty_row", colspan: 2, message: t("pgbus.recurring_tasks.show.no_executions") %>
|
|
113
|
+
<% end %>
|
|
114
|
+
</tbody>
|
|
115
|
+
</table>
|
|
122
116
|
</div>
|