karafka-web 0.10.0 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +17 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +12 -4
- data/certs/cert.pem +26 -0
- data/karafka-web.gemspec +2 -2
- data/lib/karafka/web/pro/ui/app.rb +75 -0
- data/lib/karafka/web/pro/ui/controllers/commanding_controller.rb +4 -4
- data/lib/karafka/web/pro/ui/controllers/recurring_tasks_controller.rb +131 -0
- data/lib/karafka/web/pro/ui/controllers/scheduled_messages/base_controller.rb +29 -0
- data/lib/karafka/web/pro/ui/controllers/scheduled_messages/explorer_controller.rb +65 -0
- data/lib/karafka/web/pro/ui/controllers/scheduled_messages/schedules_controller.rb +84 -0
- data/lib/karafka/web/pro/ui/views/consumers/_consumer_controls.erb +13 -12
- data/lib/karafka/web/pro/ui/views/explorer/_partition_option.erb +10 -2
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_actions.erb +58 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_batch_actions.erb +45 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_breadcrumbs.erb +22 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_log.erb +26 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_not_active.erb +12 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_tabs.erb +17 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_task.erb +46 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/logs.erb +34 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/schedule.erb +43 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_breadcrumbs.erb +30 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_message.erb +84 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_messages.erb +28 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/partition.erb +72 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/topic.erb +33 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/_breadcrumbs.erb +21 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/_no_groups.erb +11 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/index.erb +38 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/show.erb +48 -0
- data/lib/karafka/web/pro/ui/views/search/_breadcrumbs.erb +1 -0
- data/lib/karafka/web/pro/ui/views/shared/_navigation.erb +20 -0
- data/lib/karafka/web/pro/ui/views/topics/replication.erb +1 -1
- data/lib/karafka/web/tracking/consumers/listeners/errors.rb +3 -1
- data/lib/karafka/web/ui/base.rb +1 -1
- data/lib/karafka/web/ui/controllers/base_controller.rb +18 -3
- data/lib/karafka/web/ui/helpers/application_helper.rb +29 -8
- data/lib/karafka/web/ui/helpers/paths_helper.rb +18 -0
- data/lib/karafka/web/ui/models/recurring_tasks/log.rb +15 -0
- data/lib/karafka/web/ui/models/recurring_tasks/schedule.rb +75 -0
- data/lib/karafka/web/ui/models/recurring_tasks/task.rb +19 -0
- data/lib/karafka/web/ui/public/javascripts/application.js +1 -1
- data/lib/karafka/web/ui/public/javascripts/application.min.js +7 -7
- data/lib/karafka/web/ui/public/javascripts/application.min.js.br +0 -0
- data/lib/karafka/web/ui/public/javascripts/application.min.js.gz +0 -0
- data/lib/karafka/web/ui/public/javascripts/components/live_poll.js +51 -0
- data/lib/karafka/web/ui/public/stylesheets/application.css +5 -1
- data/lib/karafka/web/ui/public/stylesheets/application.min.css +2 -2
- data/lib/karafka/web/ui/public/stylesheets/application.min.css.br +0 -0
- data/lib/karafka/web/ui/public/stylesheets/application.min.css.gz +0 -0
- data/lib/karafka/web/ui/public/stylesheets/libs/tailwind.css +18 -6
- data/lib/karafka/web/ui/views/dashboard/_ranges_selector.erb +1 -1
- data/lib/karafka/web/ui/views/shared/_breadcrumbs.erb +1 -1
- data/lib/karafka/web/ui/views/shared/_navigation.erb +21 -0
- data/lib/karafka/web/ui/views/shared/icons/_calendar.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_check.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_play.erb +3 -0
- data/lib/karafka/web/ui/views/status/info/_components.erb +48 -11
- data/lib/karafka/web/ui/views/ux/_data_table.erb +34 -4
- data/lib/karafka/web/ui/views/ux/_status_rows.erb +12 -0
- data/lib/karafka/web/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +56 -27
- metadata.gz.sig +0 -0
- data/certs/cert_chain.pem +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d471de1bcc756c234f8db2345c269b878863759fb5deb195ac8579e57365efde
|
4
|
+
data.tar.gz: 12d1348a0b83353dabeeea7a5ae164be7ff834d84088cfadb7b32c7343470f66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f3eab846d445aa01714c8cea282874f9228f69af2475408d19a34b3ce43793b235f32c4484b640fad3b36ae29c90a2a8112dfd0b46685159528672355945f4c
|
7
|
+
data.tar.gz: f44a24702afe474270232a1cd5d785737fbd3e6d3b3e574b3eeb1cba5680147000092ec564ad5da7c663d6de124c7b59d9c3bd6c4e51ec80fc249eb90627fb5c
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.3.
|
1
|
+
3.3.5
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
# Karafka Web Changelog
|
2
2
|
|
3
|
+
## 0.10.2 (2024-09-03)
|
4
|
+
- **[Feature]** Support Future Messages management (Pro).
|
5
|
+
- [Enhancement] Do not live-reload when form active.
|
6
|
+
- [Fix] Undefined method `deep_merge` for an instance of Hash.
|
7
|
+
- [Fix] Prevent live-polling on elements wrapped in a button.
|
8
|
+
- [Fix] Fix errors extractor failure on first message-less tick / eofed
|
9
|
+
|
10
|
+
## 0.10.1 (2024-08-23)
|
11
|
+
- **[Feature]** Support Recurring Tasks management (Pro).
|
12
|
+
- [Enhancement] Optimize command buttons so they occupy less space.
|
13
|
+
- [Enhancement] Improve tables headers capitalization.
|
14
|
+
- [Enhancement] Prevent live-polling when user hovers over actionable links to mitigate race conditions.
|
15
|
+
- [Fix] Fix partial lack of tables hover in daily mode.
|
16
|
+
- [Fix] Fix lack of tables hover in dark mode.
|
17
|
+
- [Fix] Normalize various tables types styling.
|
18
|
+
- [Fix] Fix ranges selectors position on wide screens.
|
19
|
+
|
3
20
|
## 0.10.0 (2024-08-19)
|
4
21
|
- **[Breaking]** Rename and reorganize visibility filter to policies engine since it is not only about visibility.
|
5
22
|
- **[Feature]** Replace Bootstrap with with tailwind + DaisyUI.
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
karafka-web (0.10.
|
4
|
+
karafka-web (0.10.2)
|
5
5
|
erubi (~> 1.4)
|
6
|
-
karafka (>= 2.4.
|
6
|
+
karafka (>= 2.4.10, < 2.5.0)
|
7
7
|
karafka-core (>= 2.4.0, < 2.5.0)
|
8
8
|
roda (~> 3.68, >= 3.69)
|
9
9
|
tilt (~> 2.0)
|
@@ -30,19 +30,25 @@ GEM
|
|
30
30
|
docile (1.4.0)
|
31
31
|
drb (2.2.1)
|
32
32
|
erubi (1.13.0)
|
33
|
+
et-orbi (1.2.11)
|
34
|
+
tzinfo
|
33
35
|
factory_bot (6.4.6)
|
34
36
|
activesupport (>= 5.0.0)
|
35
37
|
ffi (1.17.0)
|
38
|
+
fugit (1.11.1)
|
39
|
+
et-orbi (~> 1, >= 1.2.11)
|
40
|
+
raabro (~> 1.4)
|
36
41
|
i18n (1.14.5)
|
37
42
|
concurrent-ruby (~> 1.0)
|
38
|
-
karafka (2.4.
|
43
|
+
karafka (2.4.10)
|
39
44
|
base64 (~> 0.2)
|
40
45
|
karafka-core (>= 2.4.3, < 2.5.0)
|
46
|
+
karafka-rdkafka (>= 0.17.2)
|
41
47
|
waterdrop (>= 2.7.3, < 3.0.0)
|
42
48
|
zeitwerk (~> 2.3)
|
43
49
|
karafka-core (2.4.4)
|
44
50
|
karafka-rdkafka (>= 0.15.0, < 0.18.0)
|
45
|
-
karafka-rdkafka (0.17.
|
51
|
+
karafka-rdkafka (0.17.3)
|
46
52
|
ffi (~> 1.15)
|
47
53
|
mini_portile2 (~> 2.6)
|
48
54
|
rake (> 12)
|
@@ -50,6 +56,7 @@ GEM
|
|
50
56
|
minitest (5.24.0)
|
51
57
|
mutex_m (0.2.0)
|
52
58
|
ostruct (0.6.0)
|
59
|
+
raabro (1.4.0)
|
53
60
|
rack (3.1.4)
|
54
61
|
rack-test (2.1.0)
|
55
62
|
rack (>= 1.3)
|
@@ -95,6 +102,7 @@ PLATFORMS
|
|
95
102
|
DEPENDENCIES
|
96
103
|
byebug
|
97
104
|
factory_bot
|
105
|
+
fugit
|
98
106
|
karafka-web!
|
99
107
|
ostruct
|
100
108
|
rack-test
|
data/certs/cert.pem
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MRAwDgYDVQQDDAdjb250
|
3
|
+
YWN0MRcwFQYKCZImiZPyLGQBGRYHa2FyYWZrYTESMBAGCgmSJomT8ixkARkWAmlv
|
4
|
+
MB4XDTI0MDgyMzEwMTkyMFoXDTQ5MDgxNzEwMTkyMFowPzEQMA4GA1UEAwwHY29u
|
5
|
+
dGFjdDEXMBUGCgmSJomT8ixkARkWB2thcmFma2ExEjAQBgoJkiaJk/IsZAEZFgJp
|
6
|
+
bzCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAKjLhLjQqUlNayxkXnO+
|
7
|
+
PsmCDs/KFIzhrsYMfLZRZNaWmzV3ujljMOdDjd4snM2X06C41iVdQPWjpe3j8vVe
|
8
|
+
ZXEWR/twSbOP6Eeg8WVH2wCOo0x5i7yhVn4UBLH4JpfEMCbemVcWQ9ry9OMg4WpH
|
9
|
+
Uu4dRwxFV7hzCz3p0QfNLRI4miAxnGWcnlD98IJRjBAksTuR1Llj0vbOrDGsL9ZT
|
10
|
+
JeXP2gdRLd8SqzAFJEWrbeTBCBU7gfSh3oMg5SVDLjaqf7Kz5wC/8bDZydzanOxB
|
11
|
+
T6CDXPsCnllmvTNx2ei2T5rGYJOzJeNTmJLLK6hJWUlAvaQSvCwZRvFJ0tVGLEoS
|
12
|
+
flqSr6uGyyl1eMUsNmsH4BqPEYcAV6P2PKTv2vUR8AP0raDvZ3xL1TKvfRb8xRpo
|
13
|
+
vPopCGlY5XBWEc6QERHfVLTIVsjnls2/Ujj4h8/TSfqqYnaHKefIMLbuD/tquMjD
|
14
|
+
iWQsW2qStBV0T+U7FijKxVfrfqZP7GxQmDAc9o1iiyAa3QIDAQABo3cwdTAJBgNV
|
15
|
+
HRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU3O4dTXmvE7YpAkszGzR9DdL9
|
16
|
+
sbEwHQYDVR0RBBYwFIESY29udGFjdEBrYXJhZmthLmlvMB0GA1UdEgQWMBSBEmNv
|
17
|
+
bnRhY3RAa2FyYWZrYS5pbzANBgkqhkiG9w0BAQsFAAOCAYEAVKTfoLXn7mqdSxIR
|
18
|
+
eqxcR6Huudg1jes81s1+X0uiRTR3hxxKZ3Y82cPsee9zYWyBrN8TA4KA0WILTru7
|
19
|
+
Ygxvzha0SRPsSiaKLmgOJ+61ebI4+bOORzIJLpD6GxCxu1r7MI4+0r1u1xe0EWi8
|
20
|
+
agkVo1k4Vi8cKMLm6Gl9b3wG9zQBw6fcgKwmpjKiNnOLP+OytzUANrIUJjoq6oal
|
21
|
+
TC+f/Uc0TLaRqUaW/bejxzDWWHoM3SU6aoLPuerglzp9zZVzihXwx3jPLUVKDFpF
|
22
|
+
Rl2lcBDxlpYGueGo0/oNzGJAAy6js8jhtHC9+19PD53vk7wHtFTZ/0ugDQYnwQ+x
|
23
|
+
oml2fAAuVWpTBCgOVFe6XCQpMKopzoxQ1PjKztW2KYxgJdIBX87SnL3aWuBQmhRd
|
24
|
+
i9zWxov0mr44TWegTVeypcWGd/0nxu1+QHVNHJrpqlPBRvwQsUm7fwmRInGpcaB8
|
25
|
+
ap8wNYvryYzrzvzUxIVFBVM5PacgkFqRmolCa8I7tdKQN+R1
|
26
|
+
-----END CERTIFICATE-----
|
data/karafka-web.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.licenses = %w[LGPL-3.0-only Commercial]
|
18
18
|
|
19
19
|
spec.add_dependency 'erubi', '~> 1.4'
|
20
|
-
spec.add_dependency 'karafka', '>= 2.4.
|
20
|
+
spec.add_dependency 'karafka', '>= 2.4.10', '< 2.5.0'
|
21
21
|
spec.add_dependency 'karafka-core', '>= 2.4.0', '< 2.5.0'
|
22
22
|
spec.add_dependency 'roda', '~> 3.68', '>= 3.69'
|
23
23
|
spec.add_dependency 'tilt', '~> 2.0'
|
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.signing_key = File.expand_path('~/.ssh/gem-private_key.pem')
|
31
31
|
end
|
32
32
|
|
33
|
-
spec.cert_chain = %w[certs/
|
33
|
+
spec.cert_chain = %w[certs/cert.pem]
|
34
34
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
|
35
35
|
spec.executables = %w[karafka-web]
|
36
36
|
spec.require_paths = %w[lib]
|
@@ -232,6 +232,81 @@ module Karafka
|
|
232
232
|
end
|
233
233
|
end
|
234
234
|
|
235
|
+
r.on 'recurring_tasks' do
|
236
|
+
controller = Controllers::RecurringTasksController.new(params)
|
237
|
+
|
238
|
+
r.get 'schedule' do
|
239
|
+
controller.schedule
|
240
|
+
end
|
241
|
+
|
242
|
+
r.get 'logs' do
|
243
|
+
controller.logs
|
244
|
+
end
|
245
|
+
|
246
|
+
r.post 'trigger_all' do
|
247
|
+
controller.trigger_all
|
248
|
+
end
|
249
|
+
|
250
|
+
r.post 'enable_all' do
|
251
|
+
controller.enable_all
|
252
|
+
end
|
253
|
+
|
254
|
+
r.post 'disable_all' do
|
255
|
+
controller.disable_all
|
256
|
+
end
|
257
|
+
|
258
|
+
r.post String, 'trigger' do |task_id|
|
259
|
+
controller.trigger(task_id)
|
260
|
+
end
|
261
|
+
|
262
|
+
r.post String, 'enable' do |task_id|
|
263
|
+
controller.enable(task_id)
|
264
|
+
end
|
265
|
+
|
266
|
+
r.post String, 'disable' do |task_id|
|
267
|
+
controller.disable(task_id)
|
268
|
+
end
|
269
|
+
|
270
|
+
r.get do
|
271
|
+
r.redirect root_path('recurring_tasks/schedule')
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
r.on 'scheduled_messages' do
|
276
|
+
r.on 'schedules' do
|
277
|
+
controller = Controllers::ScheduledMessages::SchedulesController.new(params)
|
278
|
+
|
279
|
+
r.get String do |topic_id|
|
280
|
+
controller.show(topic_id)
|
281
|
+
end
|
282
|
+
|
283
|
+
r.get do
|
284
|
+
controller.index
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
r.on 'explorer' do
|
289
|
+
controller = Controllers::ScheduledMessages::ExplorerController.new(params)
|
290
|
+
|
291
|
+
r.get String do |topic_id|
|
292
|
+
controller.topic(topic_id)
|
293
|
+
end
|
294
|
+
|
295
|
+
r.get String, Integer do |topic_id, partition_id|
|
296
|
+
controller.partition(topic_id, partition_id)
|
297
|
+
end
|
298
|
+
|
299
|
+
# Jumps to offset matching the expected time
|
300
|
+
r.get String, Integer, Time do |topic_id, partition_id, time|
|
301
|
+
controller.closest(topic_id, partition_id, time)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
r.get do
|
306
|
+
r.redirect root_path('scheduled_messages/schedules')
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
235
310
|
r.on 'health' do
|
236
311
|
controller = Controllers::HealthController.new(params)
|
237
312
|
|
@@ -27,7 +27,7 @@ module Karafka
|
|
27
27
|
|
28
28
|
redirect(
|
29
29
|
:back,
|
30
|
-
success:
|
30
|
+
success: dispatched_to_one(:probe, process_id)
|
31
31
|
)
|
32
32
|
end
|
33
33
|
|
@@ -39,7 +39,7 @@ module Karafka
|
|
39
39
|
|
40
40
|
redirect(
|
41
41
|
:back,
|
42
|
-
success:
|
42
|
+
success: dispatched_to_one(:quiet, process_id)
|
43
43
|
)
|
44
44
|
end
|
45
45
|
|
@@ -51,7 +51,7 @@ module Karafka
|
|
51
51
|
|
52
52
|
redirect(
|
53
53
|
:back,
|
54
|
-
success:
|
54
|
+
success: dispatched_to_one(:stop, process_id)
|
55
55
|
)
|
56
56
|
end
|
57
57
|
|
@@ -96,7 +96,7 @@ module Karafka
|
|
96
96
|
# @param command [Symbol]
|
97
97
|
# @param process_id [String]
|
98
98
|
# @return [String] flash message that command has been dispatched to a given process
|
99
|
-
def
|
99
|
+
def dispatched_to_one(command, process_id)
|
100
100
|
command_name = command.to_s.capitalize
|
101
101
|
|
102
102
|
"The #{command_name} command has been dispatched to the #{process_id} process."
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Web
|
16
|
+
module Pro
|
17
|
+
module Ui
|
18
|
+
module Controllers
|
19
|
+
# Controller for viewing and managing recurring tasks
|
20
|
+
class RecurringTasksController < Web::Ui::Controllers::ClusterController
|
21
|
+
self.sortable_attributes = %w[
|
22
|
+
id
|
23
|
+
enabled
|
24
|
+
cron
|
25
|
+
previous_time
|
26
|
+
next_time
|
27
|
+
].freeze
|
28
|
+
|
29
|
+
# Displays the current schedule
|
30
|
+
def schedule
|
31
|
+
@schedule = Models::RecurringTasks::Schedule.current
|
32
|
+
|
33
|
+
@tasks = refine(@schedule.tasks) if @schedule
|
34
|
+
|
35
|
+
render
|
36
|
+
end
|
37
|
+
|
38
|
+
# Displays the execution logs
|
39
|
+
def logs
|
40
|
+
@watermark_offsets = Models::WatermarkOffsets.find(logs_topic, 0)
|
41
|
+
previous_offset, @logs, next_offset, = current_page_data
|
42
|
+
|
43
|
+
paginate(
|
44
|
+
previous_offset,
|
45
|
+
@params.current_offset,
|
46
|
+
next_offset,
|
47
|
+
@logs.map(&:offset)
|
48
|
+
)
|
49
|
+
|
50
|
+
# We remap this so we can represent the payloads as logs that we expect
|
51
|
+
@logs.map! { |log| Models::RecurringTasks::Log.new(log.payload) }
|
52
|
+
|
53
|
+
render
|
54
|
+
end
|
55
|
+
|
56
|
+
# Actions definitions that trigger appropriate recurring tasks action + display a nice
|
57
|
+
# flash message.
|
58
|
+
%i[
|
59
|
+
trigger
|
60
|
+
enable
|
61
|
+
disable
|
62
|
+
].each do |action|
|
63
|
+
define_method :"#{action}_all" do
|
64
|
+
command(action, '*')
|
65
|
+
|
66
|
+
redirect(
|
67
|
+
:back,
|
68
|
+
success: dispatched_to_all(action)
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
define_method action do |task_id|
|
73
|
+
command(action, task_id)
|
74
|
+
|
75
|
+
redirect(
|
76
|
+
:back,
|
77
|
+
success: dispatched_to_one(action, task_id)
|
78
|
+
)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
# @return [Array] Array with requested messages as well as pagination details and other
|
85
|
+
# obtained metadata
|
86
|
+
def current_page_data
|
87
|
+
Models::Message.offset_page(
|
88
|
+
logs_topic,
|
89
|
+
0,
|
90
|
+
@params.current_offset,
|
91
|
+
@watermark_offsets
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
95
|
+
# @return [String] recurring tasks logs topic
|
96
|
+
def logs_topic
|
97
|
+
::Karafka::App.config.recurring_tasks.topics.logs
|
98
|
+
end
|
99
|
+
|
100
|
+
# Runs the recurring tasks command
|
101
|
+
#
|
102
|
+
# @param command [String] command we want to invoke
|
103
|
+
# @param task_id [String] task id or '*' to target expected task
|
104
|
+
def command(command, task_id)
|
105
|
+
Karafka::Pro::RecurringTasks.public_send(command, task_id)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Generates a nice flash message about the dispatch
|
109
|
+
# @param command [Symbol]
|
110
|
+
# @param task_id [String]
|
111
|
+
# @return [String] flash message that command has been dispatched to a given task
|
112
|
+
def dispatched_to_one(command, task_id)
|
113
|
+
command_name = command.to_s.capitalize
|
114
|
+
|
115
|
+
"The #{command_name} command has been dispatched to the #{task_id} task."
|
116
|
+
end
|
117
|
+
|
118
|
+
# Generates a nice flash message about dispatch of multi-task command
|
119
|
+
# @param command [Symbol]
|
120
|
+
# @return [String] flash message that command has been dispatched
|
121
|
+
def dispatched_to_all(command)
|
122
|
+
command_name = command.to_s.capitalize
|
123
|
+
|
124
|
+
"The #{command_name} command has been dispatched to all tasks."
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Web
|
16
|
+
module Pro
|
17
|
+
module Ui
|
18
|
+
module Controllers
|
19
|
+
# Namespace for all controllers related to scheduled messages
|
20
|
+
module ScheduledMessages
|
21
|
+
# Base Pro controller for scheduled messages
|
22
|
+
class BaseController < Controllers::BaseController
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Web
|
16
|
+
module Pro
|
17
|
+
module Ui
|
18
|
+
module Controllers
|
19
|
+
module ScheduledMessages
|
20
|
+
# Allows for exploration of dispatch messages in a less generic form that via the
|
21
|
+
# explorer as different details are present
|
22
|
+
class ExplorerController < BaseController
|
23
|
+
# Displays aggregated messages from (potentially) all partitions of a topic
|
24
|
+
#
|
25
|
+
# @param topic_id [String]
|
26
|
+
def topic(topic_id)
|
27
|
+
response = Controllers::ExplorerController
|
28
|
+
.new(@params)
|
29
|
+
.topic(topic_id)
|
30
|
+
|
31
|
+
render(attributes: response.attributes)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Shows messages available in a given partition
|
35
|
+
#
|
36
|
+
# @param topic_id [String]
|
37
|
+
# @param partition_id [Integer]
|
38
|
+
def partition(topic_id, partition_id)
|
39
|
+
response = Controllers::ExplorerController
|
40
|
+
.new(@params)
|
41
|
+
.partition(topic_id, partition_id)
|
42
|
+
|
43
|
+
render(attributes: response.attributes)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Finds the closest offset matching the requested time and redirects to this location
|
47
|
+
# Note, that it redirects to closest but always younger.
|
48
|
+
#
|
49
|
+
# @param topic_id [String]
|
50
|
+
# @param partition_id [Integer]
|
51
|
+
# @param time [Time] time of the message
|
52
|
+
def closest(topic_id, partition_id, time)
|
53
|
+
response = Controllers::ExplorerController
|
54
|
+
.new(@params)
|
55
|
+
.closest(topic_id, partition_id, time)
|
56
|
+
|
57
|
+
redirect("scheduled_messages/#{response.path}")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Web
|
16
|
+
module Pro
|
17
|
+
module Ui
|
18
|
+
module Controllers
|
19
|
+
# Namespace for all controllers related to scheduled messages
|
20
|
+
module ScheduledMessages
|
21
|
+
# Controller to display list of schedules (groups) and details about each
|
22
|
+
class SchedulesController < BaseController
|
23
|
+
# Displays list of groups
|
24
|
+
def index
|
25
|
+
topics = Models::Topic.all
|
26
|
+
|
27
|
+
# Names of scheduled messages topics defined in the routing
|
28
|
+
# They may not exist (yet) so we filter them based on the existing topics in the
|
29
|
+
# cluster
|
30
|
+
candidates = Karafka::App
|
31
|
+
.routes
|
32
|
+
.map(&:topics)
|
33
|
+
.map(&:to_a)
|
34
|
+
.flatten
|
35
|
+
.select(&:scheduled_messages?)
|
36
|
+
.reject { |topic| topic.name.end_with?(states_postfix) }
|
37
|
+
.map(&:name)
|
38
|
+
.sort
|
39
|
+
|
40
|
+
@topics = topics.select { |topic| candidates.include?(topic.topic_name) }
|
41
|
+
|
42
|
+
render
|
43
|
+
end
|
44
|
+
|
45
|
+
# Displays all partitions statistics (if any) with number of messages to dispatch
|
46
|
+
# @param schedule_name [String] name of the schedules messages topic
|
47
|
+
def show(schedule_name)
|
48
|
+
@schedule_name = schedule_name
|
49
|
+
@stats_topic_name = "#{schedule_name}#{states_postfix}"
|
50
|
+
@stats_info = Karafka::Admin.topic_info(@stats_topic_name)
|
51
|
+
|
52
|
+
@states = {}
|
53
|
+
@stats_info[:partition_count].times { |i| @states[i] = false }
|
54
|
+
|
55
|
+
Karafka::Pro::Iterator.new({ @stats_topic_name => -1 }).each do |message|
|
56
|
+
@states[message.partition] = message.payload
|
57
|
+
end
|
58
|
+
|
59
|
+
# Sort by partition id
|
60
|
+
@states = @states.sort_by { |key, _| key.to_s }.to_h
|
61
|
+
# Sort daily from closest date
|
62
|
+
@states.each_value do |details|
|
63
|
+
# Skip false predefined values from sorting
|
64
|
+
next unless details
|
65
|
+
|
66
|
+
details[:daily] = details[:daily].sort_by { |key, _| key.to_s }.to_h
|
67
|
+
end
|
68
|
+
|
69
|
+
render
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
# @return [String] states topic postfix
|
75
|
+
def states_postfix
|
76
|
+
@states_postfix ||= Karafka::App.config.scheduled_messages.states_postfix
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -43,17 +43,16 @@
|
|
43
43
|
<%= process.lag_hybrid %>
|
44
44
|
</td>
|
45
45
|
|
46
|
-
<td class="commands">
|
46
|
+
<td class="commands-inline-3">
|
47
47
|
<%
|
48
48
|
probe_path = root_path('commanding', process.id, 'probe')
|
49
49
|
disabled_class = process.status != 'stopped' ? '' : 'btn-disabled'
|
50
50
|
%>
|
51
|
-
<form action="<%= probe_path %>" method="post" class="">
|
51
|
+
<form action="<%= probe_path %>" method="post" class="inline" title="Probe">
|
52
52
|
<%== csrf_tag(probe_path) %>
|
53
53
|
|
54
|
-
<button type="submit" class="btn btn-info btn-sm
|
54
|
+
<button type="submit" class="btn btn-info btn-sm <%= disabled_class %>">
|
55
55
|
<%== icon(:gear) %>
|
56
|
-
Probe
|
57
56
|
</button>
|
58
57
|
</form>
|
59
58
|
|
@@ -61,16 +60,17 @@
|
|
61
60
|
quiet_path = root_path('commanding', process.id, 'quiet')
|
62
61
|
disabled_class = process.status == 'running' ? '' : 'btn-disabled'
|
63
62
|
|
64
|
-
|
63
|
+
if process.execution_mode == 'standalone'
|
64
|
+
title = 'Quiet'
|
65
|
+
else
|
65
66
|
disabled_class = 'btn-disabled'
|
66
67
|
title = 'Supported only in standalone consumer processes'
|
67
68
|
end
|
68
69
|
%>
|
69
|
-
<form action="<%= quiet_path %>" method="post" class="" title="<%= title %>">
|
70
|
+
<form action="<%= quiet_path %>" method="post" class="inline" title="<%= title %>">
|
70
71
|
<%== csrf_tag(quiet_path) %>
|
71
|
-
<button type="submit" class="btn btn-warning btn-sm
|
72
|
+
<button type="submit" class="btn btn-warning btn-sm <%= disabled_class %>">
|
72
73
|
<%== icon(:pause) %>
|
73
|
-
Quiet
|
74
74
|
</button>
|
75
75
|
</form>
|
76
76
|
|
@@ -78,16 +78,17 @@
|
|
78
78
|
stop_path = root_path('commanding', process.id, 'stop')
|
79
79
|
disabled_class = process.status != 'stopping' && process.status != 'stopped' ? '' : 'btn-disabled'
|
80
80
|
|
81
|
-
|
81
|
+
if process.execution_mode == 'standalone'
|
82
|
+
title = 'Stop'
|
83
|
+
else
|
82
84
|
disabled_class = 'btn-disabled'
|
83
85
|
title = 'Supported only in standalone consumer processes'
|
84
86
|
end
|
85
87
|
%>
|
86
|
-
<form action="<%= stop_path %>" method="post" class="" title="<%= title %>">
|
88
|
+
<form action="<%= stop_path %>" method="post" class="inline" title="<%= title %>">
|
87
89
|
<%== csrf_tag(stop_path) %>
|
88
|
-
<button type="submit" class="btn btn-error btn-sm
|
90
|
+
<button type="submit" class="btn btn-error btn-sm <%= disabled_class %>">
|
89
91
|
<%== icon(:stop) %>
|
90
|
-
Stop
|
91
92
|
</button>
|
92
93
|
</form>
|
93
94
|
</td>
|
@@ -1,7 +1,15 @@
|
|
1
|
+
<%
|
2
|
+
path = if @selector_path_method
|
3
|
+
public_send(@selector_path_method, @topic_id, partition)
|
4
|
+
else
|
5
|
+
explorer_path(@topic_id, partition)
|
6
|
+
end
|
7
|
+
%>
|
8
|
+
|
1
9
|
<% if @partition_id == partition %>
|
2
|
-
<option value="<%=
|
10
|
+
<option value="<%= path %>" selected=selected>
|
3
11
|
<% else %>
|
4
|
-
<option value="<%=
|
12
|
+
<option value="<%= path %>">
|
5
13
|
<% end %>
|
6
14
|
<%= partition || 'All' %>
|
7
15
|
</option>
|