karafka-web 0.10.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +10 -0
  4. data/Gemfile +1 -0
  5. data/Gemfile.lock +12 -4
  6. data/certs/cert.pem +26 -0
  7. data/karafka-web.gemspec +2 -2
  8. data/lib/karafka/web/pro/ui/app.rb +40 -0
  9. data/lib/karafka/web/pro/ui/controllers/commanding_controller.rb +4 -4
  10. data/lib/karafka/web/pro/ui/controllers/recurring_tasks_controller.rb +131 -0
  11. data/lib/karafka/web/pro/ui/views/consumers/_consumer_controls.erb +13 -12
  12. data/lib/karafka/web/pro/ui/views/recurring_tasks/_actions.erb +58 -0
  13. data/lib/karafka/web/pro/ui/views/recurring_tasks/_batch_actions.erb +45 -0
  14. data/lib/karafka/web/pro/ui/views/recurring_tasks/_breadcrumbs.erb +22 -0
  15. data/lib/karafka/web/pro/ui/views/recurring_tasks/_log.erb +26 -0
  16. data/lib/karafka/web/pro/ui/views/recurring_tasks/_not_active.erb +12 -0
  17. data/lib/karafka/web/pro/ui/views/recurring_tasks/_tabs.erb +17 -0
  18. data/lib/karafka/web/pro/ui/views/recurring_tasks/_task.erb +46 -0
  19. data/lib/karafka/web/pro/ui/views/recurring_tasks/logs.erb +34 -0
  20. data/lib/karafka/web/pro/ui/views/recurring_tasks/schedule.erb +43 -0
  21. data/lib/karafka/web/pro/ui/views/shared/_navigation.erb +10 -0
  22. data/lib/karafka/web/pro/ui/views/topics/replication.erb +1 -1
  23. data/lib/karafka/web/ui/helpers/application_helper.rb +8 -1
  24. data/lib/karafka/web/ui/models/recurring_tasks/log.rb +26 -0
  25. data/lib/karafka/web/ui/models/recurring_tasks/schedule.rb +86 -0
  26. data/lib/karafka/web/ui/models/recurring_tasks/task.rb +30 -0
  27. data/lib/karafka/web/ui/public/javascripts/application.js +1 -1
  28. data/lib/karafka/web/ui/public/javascripts/application.min.js +7 -7
  29. data/lib/karafka/web/ui/public/javascripts/application.min.js.br +0 -0
  30. data/lib/karafka/web/ui/public/javascripts/application.min.js.gz +0 -0
  31. data/lib/karafka/web/ui/public/javascripts/components/live_poll.js +36 -0
  32. data/lib/karafka/web/ui/public/stylesheets/application.css +5 -1
  33. data/lib/karafka/web/ui/public/stylesheets/application.min.css +2 -2
  34. data/lib/karafka/web/ui/public/stylesheets/application.min.css.br +0 -0
  35. data/lib/karafka/web/ui/public/stylesheets/application.min.css.gz +0 -0
  36. data/lib/karafka/web/ui/public/stylesheets/libs/tailwind.css +17 -5
  37. data/lib/karafka/web/ui/views/dashboard/_ranges_selector.erb +1 -1
  38. data/lib/karafka/web/ui/views/shared/_navigation.erb +11 -0
  39. data/lib/karafka/web/ui/views/shared/icons/_check.erb +3 -0
  40. data/lib/karafka/web/ui/views/shared/icons/_play.erb +3 -0
  41. data/lib/karafka/web/ui/views/status/info/_components.erb +48 -11
  42. data/lib/karafka/web/ui/views/ux/_data_table.erb +34 -4
  43. data/lib/karafka/web/ui/views/ux/_status_rows.erb +12 -0
  44. data/lib/karafka/web/version.rb +1 -1
  45. data.tar.gz.sig +0 -0
  46. metadata +41 -26
  47. metadata.gz.sig +0 -0
  48. data/certs/cert_chain.pem +0 -26
@@ -0,0 +1,34 @@
1
+ <% view_title 'Logs' %>
2
+
3
+ <%== partial 'recurring_tasks/tabs' %>
4
+
5
+ <div class="col-span-12">
6
+ <% if @logs.empty? && params.current_page <= 1 %>
7
+ <%== alert_info('There are no available logs.') %>
8
+ <% elsif @logs.empty? %>
9
+ <%== partial 'shared/no_paginated_data' %>
10
+ <% else %>
11
+ <div class="data-table-wrapper">
12
+ <table class="data-table">
13
+ <thead>
14
+ <tr>
15
+ <th>Task ID</th>
16
+ <th>Result</th>
17
+ <th>Time Taken</th>
18
+ <th>Dispatched At</th>
19
+ <th>Schedule Version</th>
20
+ </tr>
21
+ </thead>
22
+ <tbody>
23
+ <%==
24
+ render_each(
25
+ @logs,
26
+ 'recurring_tasks/_log',
27
+ local: :log
28
+ )
29
+ %>
30
+ </tbody>
31
+ </table>
32
+ </div>
33
+ <% end %>
34
+ </div>
@@ -0,0 +1,43 @@
1
+ <% if @schedule %>
2
+ <% view_title "Schedule #{@schedule.schedule_version}" %>
3
+ <% else %>
4
+ <% view_title 'Schedule' %>
5
+ <% end %>
6
+
7
+ <% if @schedule %>
8
+ <%== partial 'recurring_tasks/tabs' %>
9
+
10
+ <% unless @tasks.empty? %>
11
+ <%== partial 'recurring_tasks/batch_actions' %>
12
+ <% end %>
13
+ <% end %>
14
+
15
+ <div class="col-span-12">
16
+ <% if @schedule && !@tasks.empty? %>
17
+ <div class="data-table-wrapper">
18
+ <table class="data-table">
19
+ <thead>
20
+ <tr>
21
+ <th><%== sort_link('Task ID', :id) %></th>
22
+ <th><%== sort_link('Status', :enabled) %></th>
23
+ <th><%== sort_link(:cron) %></th>
24
+ <th><%== sort_link(:previous_time) %></th>
25
+ <th><%== sort_link(:next_time) %></th>
26
+ <th></th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <%==
31
+ render_each(
32
+ @tasks,
33
+ 'recurring_tasks/_task',
34
+ local: :task
35
+ )
36
+ %>
37
+ </tbody>
38
+ </table>
39
+ </div>
40
+ <% else %>
41
+ <%== partial 'recurring_tasks/not_active' %>
42
+ <% end %>
43
+ </div>
@@ -62,6 +62,16 @@
62
62
  </a>
63
63
  </li>
64
64
 
65
+ <li>
66
+ <a
67
+ class="sidebar-nav-item <%= nav_class(start_with: '/recurring_tasks') %>"
68
+ href="<%= root_path('recurring_tasks') %>"
69
+ >
70
+ <%== icon(:arrow_path_rounded) %>
71
+ Cron
72
+ </a>
73
+ </li>
74
+
65
75
  <li>
66
76
  <a
67
77
  class="sidebar-nav-item <%= nav_class(start_with: '/errors') %>"
@@ -9,7 +9,7 @@
9
9
  <th><%== sort_link(:partition_id) %></th>
10
10
  <th><%== sort_link(:leader) %></th>
11
11
  <th><%== sort_link(:replica_count) %></th>
12
- <th><%== sort_link('In sync brokers', :in_sync_replica_brokers) %></th>
12
+ <th><%== sort_link('In Sync Brokers', :in_sync_replica_brokers) %></th>
13
13
  </tr>
14
14
  </thead>
15
15
  <tbody>
@@ -309,7 +309,14 @@ module Karafka
309
309
  def sort_link(name, attribute = nil, rev: false)
310
310
  unless attribute
311
311
  attribute = name
312
- name = SORT_NAMES[attribute] || attribute.to_s.tr('_', ' ').tr('?', '').capitalize
312
+
313
+ if SORT_NAMES[attribute]
314
+ name = SORT_NAMES[attribute]
315
+ else
316
+ name = attribute.to_s.tr('_', ' ').tr('?', '')
317
+ # Always capitalize the name
318
+ name = name.split(' ').map(&:capitalize).join(' ')
319
+ end
313
320
  end
314
321
 
315
322
  arrow_both = '&#x21D5;'
@@ -0,0 +1,26 @@
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 Ui
17
+ module Models
18
+ module RecurringTasks
19
+ # Single log entry for recurring tasks execution
20
+ class Log < Lib::HashProxy
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,86 @@
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 Ui
17
+ module Models
18
+ # Namespace for models representing recurring tasks related components taken from Kafka
19
+ module RecurringTasks
20
+ # Karafka schedule representation
21
+ class Schedule < Web::Ui::Lib::HashProxy
22
+ # Rdkafka errors we expect and handle gracefully
23
+ EXPECTED_RDKAFKA_ERRORS = %i[
24
+ unknown_topic
25
+ unknown_partition
26
+ unknown_topic_or_part
27
+ ].freeze
28
+
29
+ private_constant :EXPECTED_RDKAFKA_ERRORS
30
+
31
+ class << self
32
+ # @return [Schedule, false] current schedule or false if it was not possible to
33
+ # get it because requested topic/partition does not exist or nothing was present
34
+ def current
35
+ messages = Karafka::Admin.read_topic(
36
+ config.topics.schedules,
37
+ 0,
38
+ # We work here with the assumption that users won't click so fast to load
39
+ # more than 20 commands prior to a state flush. If that happens, this will
40
+ # return false. This is a known and expected limitation.
41
+ 20
42
+ )
43
+
44
+ # Out of those messages we pick the most recent persisted schedule
45
+ candidate = messages
46
+ .reverse
47
+ .find { |message| message.key == 'state:schedule' }
48
+
49
+ # If there is a schedule message we use its data to build schedule, if not false
50
+ return false unless candidate
51
+
52
+ # If the deserializer is not our dedicated recurring tasks deserializer, it means
53
+ # that routing for recurring tasks was not loaded, so recurring tasks are not
54
+ # active
55
+ #
56
+ # User might have used recurring tasks previously and disabled them, but still may
57
+ # navigate to them and then we should not show anything because without the
58
+ # correct deserializer it will crash anyhow
59
+ return false unless candidate.metadata.deserializers.payload == config.deserializer
60
+
61
+ new(candidate.payload)
62
+ rescue Rdkafka::RdkafkaError => e
63
+ # If any of "topic missing" is raised, we return false but other errors we re-raise
64
+ raise(e) unless EXPECTED_RDKAFKA_ERRORS.any? { |code| e.code == code }
65
+
66
+ false
67
+ end
68
+
69
+ private
70
+
71
+ # @return [Karafka::Core::Configurable::Node]
72
+ def config
73
+ Karafka::App.config.recurring_tasks
74
+ end
75
+ end
76
+
77
+ # @return [Array<Task>] tasks of the current schedule
78
+ def tasks
79
+ @tasks ||= super.values.map { |task_hash| Task.new(task_hash) }
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,30 @@
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 Ui
17
+ module Models
18
+ module RecurringTasks
19
+ # Represents a single recurring task
20
+ class Task < Lib::HashProxy
21
+ # @return [Boolean] true if this task is enabled, otherwise false
22
+ def enabled?
23
+ enabled
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -119,4 +119,4 @@ function addListeners() {
119
119
 
120
120
  document.addEventListener('turbo:load', addListeners);
121
121
 
122
- Turbo.setProgressBarDelay(250)
122
+ Turbo.setProgressBarDelay(100)