karafka-web 0.8.2 → 0.9.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/ci.yml +5 -16
- data/CHANGELOG.md +39 -0
- data/Gemfile.lock +21 -23
- data/LICENSE +3 -3
- data/bin/rspecs +1 -1
- data/config/locales/pro_errors.yml +11 -0
- data/config/locales/slogans.yml +62 -0
- data/karafka-web.gemspec +4 -2
- data/lib/karafka/web/app.rb +1 -1
- data/lib/karafka/web/config.rb +17 -0
- data/lib/karafka/web/contracts/config.rb +6 -0
- data/lib/karafka/web/management/actions/create_topics.rb +21 -0
- data/lib/karafka/web/management/actions/delete_topics.rb +1 -0
- data/lib/karafka/web/management/actions/enable.rb +11 -5
- data/lib/karafka/web/management/migrations/0_base.rb +1 -1
- data/lib/karafka/web/pro/commanding/commands/base.rb +33 -0
- data/lib/karafka/web/pro/commanding/commands/probe.rb +41 -0
- data/lib/karafka/web/pro/commanding/commands/quiet.rb +31 -0
- data/lib/karafka/web/pro/commanding/commands/stop.rb +31 -0
- data/lib/karafka/web/pro/commanding/config.rb +57 -0
- data/lib/karafka/web/pro/commanding/contracts/config.rb +60 -0
- data/lib/karafka/web/pro/commanding/dispatcher.rb +93 -0
- data/lib/karafka/web/pro/commanding/listener.rb +97 -0
- data/lib/karafka/web/pro/commanding/manager.rb +98 -0
- data/lib/karafka/web/pro/commanding/matcher.rb +50 -0
- data/lib/karafka/web/pro/commanding.rb +40 -0
- data/lib/karafka/web/pro/loader.rb +40 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/app.rb +103 -22
- data/lib/karafka/web/{ui/pro/controllers/cluster.rb → pro/ui/controllers/base_controller.rb} +4 -5
- data/lib/karafka/web/pro/ui/controllers/cluster_controller.rb +54 -0
- data/lib/karafka/web/pro/ui/controllers/commanding_controller.rb +118 -0
- data/lib/karafka/web/pro/ui/controllers/commands_controller.rb +96 -0
- data/lib/karafka/web/{ui/pro/controllers/consumers.rb → pro/ui/controllers/consumers_controller.rb} +31 -4
- data/lib/karafka/web/{ui/pro/controllers/dashboard.rb → pro/ui/controllers/dashboard_controller.rb} +5 -3
- data/lib/karafka/web/pro/ui/controllers/dlq_controller.rb +60 -0
- data/lib/karafka/web/{ui/pro/controllers/errors.rb → pro/ui/controllers/errors_controller.rb} +5 -7
- data/lib/karafka/web/{ui/pro/controllers/explorer.rb → pro/ui/controllers/explorer_controller.rb} +24 -19
- data/lib/karafka/web/{ui/pro/controllers/health.rb → pro/ui/controllers/health_controller.rb} +16 -3
- data/lib/karafka/web/{ui/pro/controllers/jobs.rb → pro/ui/controllers/jobs_controller.rb} +4 -4
- data/lib/karafka/web/{ui/pro/controllers/messages.rb → pro/ui/controllers/messages_controller.rb} +8 -6
- data/lib/karafka/web/{ui/pro/controllers/routing.rb → pro/ui/controllers/routing_controller.rb} +6 -22
- data/lib/karafka/web/{ui/pro/controllers/status.rb → pro/ui/controllers/status_controller.rb} +3 -3
- data/lib/karafka/web/pro/ui/controllers/topics_controller.rb +99 -0
- data/lib/karafka/web/pro/ui/lib/patterns_detector.rb +50 -0
- data/lib/karafka/web/pro/ui/views/cluster/_breadcrumbs.erb +29 -0
- data/lib/karafka/web/pro/ui/views/cluster/_broker.erb +13 -0
- data/lib/karafka/web/pro/ui/views/cluster/_config.erb +13 -0
- data/lib/karafka/web/pro/ui/views/cluster/_tabs.erb +27 -0
- data/lib/karafka/web/pro/ui/views/cluster/brokers.erb +27 -0
- data/lib/karafka/web/pro/ui/views/cluster/index.erb +27 -0
- data/lib/karafka/web/pro/ui/views/cluster/show.erb +27 -0
- data/lib/karafka/web/pro/ui/views/commands/_backtrace.erb +20 -0
- data/lib/karafka/web/pro/ui/views/commands/_breadcrumbs.erb +21 -0
- data/lib/karafka/web/pro/ui/views/commands/_command.erb +60 -0
- data/lib/karafka/web/pro/ui/views/commands/_command_details.erb +11 -0
- data/lib/karafka/web/pro/ui/views/commands/_details.erb +26 -0
- data/lib/karafka/web/pro/ui/views/commands/_empty.erb +3 -0
- data/lib/karafka/web/pro/ui/views/commands/_incompatible_schema.erb +14 -0
- data/lib/karafka/web/pro/ui/views/commands/_metadata.erb +50 -0
- data/lib/karafka/web/pro/ui/views/commands/_table.erb +23 -0
- data/lib/karafka/web/pro/ui/views/commands/index.erb +17 -0
- data/lib/karafka/web/pro/ui/views/commands/show.erb +38 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/_breadcrumbs.erb +20 -4
- data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/_consumer.erb +2 -21
- data/lib/karafka/web/pro/ui/views/consumers/_consumer_controls.erb +78 -0
- data/lib/karafka/web/pro/ui/views/consumers/_consumer_performance.erb +59 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/_counters.erb +7 -5
- data/lib/karafka/web/pro/ui/views/consumers/_tabs.erb +35 -0
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_commands.erb +32 -0
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_no_jobs.erb +7 -0
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_no_subscriptions.erb +7 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_subscription_group.erb +13 -8
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_title.erb +5 -0
- data/lib/karafka/web/pro/ui/views/consumers/controls.erb +67 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/details.erb +6 -1
- data/lib/karafka/web/pro/ui/views/consumers/index.erb +39 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/pending_jobs.erb +15 -7
- data/lib/karafka/web/pro/ui/views/consumers/performance.erb +52 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/running_jobs.erb +15 -7
- data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/subscriptions.erb +6 -1
- data/lib/karafka/web/{ui/pro → pro/ui}/views/dashboard/index.erb +10 -10
- data/lib/karafka/web/pro/ui/views/dlq/_no_topics.erb +7 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/views/dlq/index.erb +1 -1
- data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/_error.erb +2 -6
- data/lib/karafka/web/pro/ui/views/errors/_table.erb +23 -0
- data/lib/karafka/web/pro/ui/views/explorer/_failed_deserialization.erb +4 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_message.erb +7 -1
- data/lib/karafka/web/pro/ui/views/explorer/_no_topics.erb +5 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/index.erb +1 -6
- data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/message/_metadata.erb +33 -9
- data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/message/_payload.erb +4 -4
- data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/message/_payload_actions.erb +1 -1
- data/lib/karafka/web/pro/ui/views/explorer/messages/_headers.erb +33 -0
- data/lib/karafka/web/pro/ui/views/explorer/messages/_key.erb +20 -0
- data/lib/karafka/web/pro/ui/views/explorer/partition/_cleaned.erb +5 -0
- data/lib/karafka/web/pro/ui/views/explorer/partition/_empty.erb +5 -0
- data/lib/karafka/web/pro/ui/views/explorer/partition/_messages.erb +21 -0
- data/lib/karafka/web/pro/ui/views/explorer/topic/_empty.erb +5 -0
- data/lib/karafka/web/pro/ui/views/explorer/topic/_limited.erb +10 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_breadcrumbs.erb +8 -0
- data/lib/karafka/web/pro/ui/views/health/_no_data.erb +7 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_partition.erb +1 -1
- data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_partition_lags.erb +6 -3
- data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_tabs.erb +11 -1
- data/lib/karafka/web/{ui/pro → pro/ui}/views/health/changes.erb +13 -8
- data/lib/karafka/web/pro/ui/views/health/cluster_lags.erb +54 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/views/health/lags.erb +14 -8
- data/lib/karafka/web/{ui/pro → pro/ui}/views/health/offsets.erb +15 -12
- data/lib/karafka/web/{ui/pro → pro/ui}/views/health/overview.erb +21 -7
- data/lib/karafka/web/{ui/pro → pro/ui}/views/jobs/_job.erb +1 -1
- data/lib/karafka/web/pro/ui/views/jobs/_no_jobs.erb +7 -0
- data/lib/karafka/web/{ui/pro → pro/ui}/views/jobs/pending.erb +12 -8
- data/lib/karafka/web/{ui/pro → pro/ui}/views/jobs/running.erb +12 -8
- data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/_consumer_group.erb +2 -2
- data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/index.erb +1 -1
- data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/show.erb +1 -1
- data/lib/karafka/web/{ui/pro → pro/ui}/views/shared/_navigation.erb +14 -0
- data/lib/karafka/web/pro/ui/views/topics/_breadcrumbs.erb +37 -0
- data/lib/karafka/web/pro/ui/views/topics/_partition.erb +16 -0
- data/lib/karafka/web/pro/ui/views/topics/_tabs.erb +37 -0
- data/lib/karafka/web/pro/ui/views/topics/_topic.erb +12 -0
- data/lib/karafka/web/pro/ui/views/topics/config.erb +29 -0
- data/lib/karafka/web/pro/ui/views/topics/distribution/_badges.erb +7 -0
- data/lib/karafka/web/pro/ui/views/topics/distribution/_chart.erb +2 -0
- data/lib/karafka/web/pro/ui/views/topics/distribution/_empty_partitions.erb +1 -0
- data/lib/karafka/web/pro/ui/views/topics/distribution/_limited.erb +10 -0
- data/lib/karafka/web/pro/ui/views/topics/distribution/_partition.erb +10 -0
- data/lib/karafka/web/pro/ui/views/topics/distribution.erb +47 -0
- data/lib/karafka/web/pro/ui/views/topics/index.erb +16 -0
- data/lib/karafka/web/pro/ui/views/topics/replication.erb +28 -0
- data/lib/karafka/web/processing/consumers/aggregators/base.rb +1 -1
- data/lib/karafka/web/processing/consumers/aggregators/metrics.rb +1 -1
- data/lib/karafka/web/processing/consumers/aggregators/state.rb +4 -4
- data/lib/karafka/web/tracking/consumers/contracts/report.rb +1 -1
- data/lib/karafka/web/tracking/consumers/listeners/booting.rb +3 -1
- data/lib/karafka/web/tracking/consumers/listeners/errors.rb +2 -2
- data/lib/karafka/web/tracking/consumers/reporter.rb +3 -3
- data/lib/karafka/web/tracking/consumers/sampler.rb +2 -2
- data/lib/karafka/web/tracking/contracts/error.rb +1 -1
- data/lib/karafka/web/tracking/producers/listeners/booting.rb +3 -1
- data/lib/karafka/web/tracking/producers/listeners/errors.rb +2 -2
- data/lib/karafka/web/tracking/producers/reporter.rb +1 -1
- data/lib/karafka/web/tracking/producers/sampler.rb +1 -1
- data/lib/karafka/web/tracking/sampler.rb +3 -3
- data/lib/karafka/web/ui/app.rb +13 -9
- data/lib/karafka/web/ui/base.rb +1 -0
- data/lib/karafka/web/ui/controllers/{base.rb → base_controller.rb} +15 -2
- data/lib/karafka/web/ui/controllers/{become_pro.rb → become_pro_controller.rb} +1 -1
- data/lib/karafka/web/ui/controllers/{cluster.rb → cluster_controller.rb} +4 -4
- data/lib/karafka/web/ui/controllers/{consumers.rb → consumers_controller.rb} +3 -3
- data/lib/karafka/web/ui/controllers/{dashboard.rb → dashboard_controller.rb} +1 -1
- data/lib/karafka/web/ui/controllers/{errors.rb → errors_controller.rb} +2 -2
- data/lib/karafka/web/ui/controllers/{jobs.rb → jobs_controller.rb} +5 -5
- data/lib/karafka/web/ui/controllers/{routing.rb → routing_controller.rb} +2 -2
- data/lib/karafka/web/ui/controllers/{status.rb → status_controller.rb} +1 -1
- data/lib/karafka/web/ui/helpers/alerts_helper.rb +23 -0
- data/lib/karafka/web/ui/helpers/application_helper.rb +53 -1
- data/lib/karafka/web/ui/lib/paginations/offset_based.rb +3 -4
- data/lib/karafka/web/ui/lib/safe_runner.rb +59 -0
- data/lib/karafka/web/ui/models/broker.rb +66 -0
- data/lib/karafka/web/ui/models/health.rb +28 -2
- data/lib/karafka/web/ui/models/message.rb +9 -3
- data/lib/karafka/web/ui/models/process.rb +10 -5
- data/lib/karafka/web/ui/models/processes.rb +2 -2
- data/lib/karafka/web/ui/models/topic.rb +78 -0
- data/lib/karafka/web/ui/public/javascripts/application.js +18 -1
- data/lib/karafka/web/ui/public/javascripts/charts/data_formatting_utility.js +71 -0
- data/lib/karafka/web/ui/public/javascripts/charts/dataset_state_manager.js +49 -0
- data/lib/karafka/web/ui/public/javascripts/charts/types/bar.js +123 -0
- data/lib/karafka/web/ui/public/javascripts/charts/types/line.js +143 -0
- data/lib/karafka/web/ui/public/javascripts/charts.js +10 -325
- data/lib/karafka/web/ui/public/javascripts/live_poll.js +5 -5
- data/lib/karafka/web/ui/public/javascripts/tabs_manager.js +57 -0
- data/lib/karafka/web/ui/public/stylesheets/application.css +7 -6
- data/lib/karafka/web/ui/views/cluster/_breadcrumbs.erb +3 -3
- data/lib/karafka/web/ui/views/cluster/_no_partitions.erb +1 -3
- data/lib/karafka/web/ui/views/cluster/_tabs.erb +3 -3
- data/lib/karafka/web/ui/views/cluster/brokers.erb +19 -19
- data/lib/karafka/web/ui/views/cluster/replication.erb +37 -0
- data/lib/karafka/web/ui/views/consumers/_assignments_badges.erb +24 -0
- data/lib/karafka/web/ui/views/consumers/_consumer.erb +2 -15
- data/lib/karafka/web/ui/views/consumers/_counters.erb +1 -1
- data/lib/karafka/web/ui/views/consumers/_summary.erb +5 -5
- data/lib/karafka/web/ui/views/consumers/index.erb +22 -20
- data/lib/karafka/web/ui/views/dashboard/index.erb +9 -9
- data/lib/karafka/web/ui/views/errors/_cleaned.erb +1 -3
- data/lib/karafka/web/ui/views/errors/_error.erb +2 -6
- data/lib/karafka/web/ui/views/errors/_no_errors.erb +1 -3
- data/lib/karafka/web/ui/views/errors/index.erb +22 -20
- data/lib/karafka/web/ui/views/jobs/_job.erb +4 -1
- data/lib/karafka/web/ui/views/jobs/_no_jobs.erb +1 -3
- data/lib/karafka/web/ui/views/jobs/pending.erb +4 -3
- data/lib/karafka/web/ui/views/jobs/running.erb +4 -3
- data/lib/karafka/web/ui/views/routing/_consumer_group.erb +2 -2
- data/lib/karafka/web/ui/views/routing/index.erb +1 -1
- data/lib/karafka/web/ui/views/routing/show.erb +1 -1
- data/lib/karafka/web/ui/views/shared/_become_pro.erb +3 -3
- data/lib/karafka/web/ui/views/shared/_header.erb +16 -10
- data/lib/karafka/web/ui/views/shared/_navigation.erb +17 -3
- data/lib/karafka/web/ui/views/shared/_not_a_message.erb +5 -0
- data/lib/karafka/web/ui/views/shared/alerts/_info.erb +3 -0
- data/lib/karafka/web/ui/views/shared/charts/_bar.erb +7 -0
- data/lib/karafka/web/ui/views/shared/{_chart.erb → charts/_line.erb} +1 -1
- data/lib/karafka/web/ui/views/shared/exceptions/not_found.erb +1 -1
- data/lib/karafka/web/ui/views/status/show.erb +1 -1
- data/lib/karafka/web/version.rb +1 -1
- data/lib/karafka/web.rb +17 -1
- data.tar.gz.sig +0 -0
- metadata +189 -120
- metadata.gz.sig +0 -0
- data/lib/karafka/web/ui/pro/controllers/dlq.rb +0 -43
- data/lib/karafka/web/ui/pro/views/consumers/consumer/_no_jobs.erb +0 -9
- data/lib/karafka/web/ui/pro/views/consumers/consumer/_no_subscriptions.erb +0 -9
- data/lib/karafka/web/ui/pro/views/consumers/index.erb +0 -36
- data/lib/karafka/web/ui/pro/views/dlq/_no_topics.erb +0 -9
- data/lib/karafka/web/ui/pro/views/errors/_table.erb +0 -21
- data/lib/karafka/web/ui/pro/views/explorer/_failed_deserialization.erb +0 -4
- data/lib/karafka/web/ui/pro/views/explorer/_no_topics.erb +0 -7
- data/lib/karafka/web/ui/pro/views/explorer/messages/_headers.erb +0 -15
- data/lib/karafka/web/ui/pro/views/explorer/messages/_key.erb +0 -12
- data/lib/karafka/web/ui/pro/views/explorer/partition/_cleaned.erb +0 -3
- data/lib/karafka/web/ui/pro/views/explorer/partition/_empty.erb +0 -3
- data/lib/karafka/web/ui/pro/views/explorer/partition/_messages.erb +0 -19
- data/lib/karafka/web/ui/pro/views/explorer/topic/_empty.erb +0 -3
- data/lib/karafka/web/ui/pro/views/explorer/topic/_limited.erb +0 -4
- data/lib/karafka/web/ui/pro/views/health/_no_data.erb +0 -9
- data/lib/karafka/web/ui/pro/views/jobs/_no_jobs.erb +0 -9
- data/lib/karafka/web/ui/public/javascripts/tabs.js +0 -59
- data/lib/karafka/web/ui/views/cluster/topics.erb +0 -35
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_consumer_group.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_job.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_metrics.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_partition.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_stopped.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_tabs.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/dlq/_breadcrumbs.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/dlq/_topic.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/_breadcrumbs.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/_partition_option.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/_title_with_select.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/index.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/partition.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/show.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_breadcrumbs.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_filtered.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_partition_option.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_topic.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/message/_message_actions.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/messages/_detail.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/partition/_details.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/partition.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/show.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/topic/_details.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/topic.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_consumer_group_header.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_partition_offset.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_partition_times.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/_detail.erb +0 -0
- /data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/_topic.erb +0 -0
- /data/lib/karafka/web/ui/public/javascripts/{bootstrap.min.js → libs/bootstrap.min.js} +0 -0
- /data/lib/karafka/web/ui/public/javascripts/{chart.min.js → libs/chart.min.js} +0 -0
- /data/lib/karafka/web/ui/public/javascripts/{datepicker.js → libs/datepicker.js} +0 -0
- /data/lib/karafka/web/ui/public/javascripts/{highlight.min.js → libs/highlight.min.js} +0 -0
- /data/lib/karafka/web/ui/public/javascripts/{timeago.min.js → libs/timeago.min.js} +0 -0
- /data/lib/karafka/web/ui/public/stylesheets/{bootstrap.min.css → libs/bootstrap.min.css} +0 -0
- /data/lib/karafka/web/ui/public/stylesheets/{datepicker.min.css → libs/datepicker.min.css} +0 -0
- /data/lib/karafka/web/ui/public/stylesheets/{highlight.min.css → libs/highlight.min.css} +0 -0
@@ -0,0 +1,57 @@
|
|
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 Commanding
|
18
|
+
# Extra configuration for pro commanding
|
19
|
+
class Config
|
20
|
+
extend ::Karafka::Core::Configurable
|
21
|
+
|
22
|
+
# Management of processes is enabled by default
|
23
|
+
setting :active, default: true
|
24
|
+
|
25
|
+
# What consumer group to use for the commanding subscription.
|
26
|
+
# In general this CG is irrelevant. Required but irrelevant unless you're using ACLs
|
27
|
+
# as in that case you will have to grant it permissions. This CG never stores any
|
28
|
+
# offsets as the underlying assignment is via assign API and not subscribe one.
|
29
|
+
setting :consumer_group, default: 'karafka_web'
|
30
|
+
|
31
|
+
# How long should we wait on command arrival before yielding. Having it too short will
|
32
|
+
# cause unnecessary CPU cycles. Too long will make shutdown slower.
|
33
|
+
setting :max_wait_time, default: 2_000
|
34
|
+
|
35
|
+
# How long should we wait when an error occurs. Since this subscription is via the assign
|
36
|
+
# API, we can just back-off and not care since we can always re-create the consumer on
|
37
|
+
# issues. We always want to prevent a case where we would create new in a loop and
|
38
|
+
# fail without backoff as this could overload the process.
|
39
|
+
#
|
40
|
+
# This should not happen often so waiting that long should not pose significant risks
|
41
|
+
# and should not cause issues with the user-experience, since this is only commanding
|
42
|
+
# connection
|
43
|
+
setting :pause_timeout, default: 10_000
|
44
|
+
|
45
|
+
# The underlying iterator requires specific settings, do not change this unless you know
|
46
|
+
# what you area doing
|
47
|
+
setting :kafka, default: {
|
48
|
+
'enable.partition.eof': false,
|
49
|
+
'auto.offset.reset': 'latest'
|
50
|
+
}
|
51
|
+
|
52
|
+
configure
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,60 @@
|
|
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 Commanding
|
18
|
+
# Commanding related contracts
|
19
|
+
module Contracts
|
20
|
+
# Makes sure, all the expected commanding config is defined as it should be
|
21
|
+
class Config < ::Karafka::Contracts::Base
|
22
|
+
configure do |config|
|
23
|
+
config.error_messages = YAML.safe_load(
|
24
|
+
File.read(
|
25
|
+
File.join(Karafka::Web.gem_root, 'config', 'locales', 'pro_errors.yml')
|
26
|
+
)
|
27
|
+
).fetch('en').fetch('validations').fetch('config')
|
28
|
+
end
|
29
|
+
|
30
|
+
nested(:commanding) do
|
31
|
+
required(:active) { |val| [true, false].include?(val) }
|
32
|
+
required(:pause_timeout) { |val| val.is_a?(Integer) && val.positive? }
|
33
|
+
required(:max_wait_time) { |val| val.is_a?(Integer) && val.positive? }
|
34
|
+
required(:kafka) { |val| val.is_a?(Hash) }
|
35
|
+
|
36
|
+
required(:consumer_group) do |val|
|
37
|
+
val.is_a?(String) && Karafka::Web::Contracts::Config::TOPIC_REGEXP.match?(val)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Ensure all commanding kafka keys are symbols
|
42
|
+
virtual do |data, errors|
|
43
|
+
next unless errors.empty?
|
44
|
+
|
45
|
+
detected_errors = []
|
46
|
+
|
47
|
+
data.fetch(:commanding).fetch(:kafka).each_key do |key|
|
48
|
+
next if key.is_a?(Symbol)
|
49
|
+
|
50
|
+
detected_errors << [[:commanding, :kafka, key], :key_must_be_a_symbol]
|
51
|
+
end
|
52
|
+
|
53
|
+
detected_errors
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,93 @@
|
|
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 Commanding
|
18
|
+
# Dispatcher for sending commanding related messages. Those can be:
|
19
|
+
# - command (do something)
|
20
|
+
# - result (you wanted me to get you some info, here it is)
|
21
|
+
#
|
22
|
+
# Dispatcher requires Web UI to have a producer
|
23
|
+
class Dispatcher
|
24
|
+
# What schema do we have in current Karafka version for commands dispatches
|
25
|
+
SCHEMA_VERSION = '1.0.0'
|
26
|
+
|
27
|
+
class << self
|
28
|
+
# Dispatches the command request
|
29
|
+
#
|
30
|
+
# @param name [String, Symbol] name of the command we want to deal with in the process
|
31
|
+
# @param process_id [String] id of the process. We use name instead of id only
|
32
|
+
# because in the web ui we work with the full name and it is easier. Since
|
33
|
+
def command(name, process_id)
|
34
|
+
producer.produce_async(
|
35
|
+
topic: commands_topic,
|
36
|
+
key: process_id,
|
37
|
+
partition: 0,
|
38
|
+
payload: {
|
39
|
+
schema_version: SCHEMA_VERSION,
|
40
|
+
type: 'command',
|
41
|
+
command: {
|
42
|
+
name: name
|
43
|
+
},
|
44
|
+
dispatched_at: Time.now.to_f,
|
45
|
+
process: {
|
46
|
+
id: process_id
|
47
|
+
}
|
48
|
+
}.to_json
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Dispatches the result request
|
53
|
+
#
|
54
|
+
# @param result [Object] anything that can be the result of the command execution
|
55
|
+
# @param process_id [String] related process id
|
56
|
+
# @param command_name [String, Symbol] command that triggered this result
|
57
|
+
def result(result, process_id, command_name)
|
58
|
+
producer.produce_async(
|
59
|
+
topic: commands_topic,
|
60
|
+
key: process_id,
|
61
|
+
partition: 0,
|
62
|
+
payload: {
|
63
|
+
schema_version: SCHEMA_VERSION,
|
64
|
+
type: 'result',
|
65
|
+
command: {
|
66
|
+
name: command_name
|
67
|
+
},
|
68
|
+
result: result,
|
69
|
+
dispatched_at: Time.now.to_f,
|
70
|
+
process: {
|
71
|
+
id: process_id
|
72
|
+
}
|
73
|
+
}.to_json
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# @return [::WaterDrop::Producer] web ui producer
|
80
|
+
def producer
|
81
|
+
Karafka::Web.producer
|
82
|
+
end
|
83
|
+
|
84
|
+
# @return [String] consumers commands topic
|
85
|
+
def commands_topic
|
86
|
+
::Karafka::Web.config.topics.consumers.commands
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,97 @@
|
|
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
|
+
# Namespace for things related to consumers commanding (management)
|
18
|
+
#
|
19
|
+
# This feature allows for basic of consumers. They can be stopped, moved to quiet or probed
|
20
|
+
# via the Web UI
|
21
|
+
module Commanding
|
22
|
+
# Wrapper around the Pro Iterator that yields messages with commands when needed for
|
23
|
+
# further processing.
|
24
|
+
#
|
25
|
+
# This iterator supports error handling, basically on errors it will be reported and
|
26
|
+
# ignored as long as they are not critical. Critical errors will cause back-off and
|
27
|
+
# reconnection.
|
28
|
+
class Listener
|
29
|
+
# Runs iterator and keeps it running until not needed.
|
30
|
+
#
|
31
|
+
# @yield [Karafka::Messages::Message] command message
|
32
|
+
def each
|
33
|
+
c_config = ::Karafka::Web.config.commanding
|
34
|
+
t_config = Karafka::Web.config.topics
|
35
|
+
|
36
|
+
iterator = Karafka::Pro::Iterator.new(
|
37
|
+
{ t_config.consumers.commands => true },
|
38
|
+
settings: c_config.kafka.merge('group.id' => c_config.consumer_group),
|
39
|
+
yield_nil: true,
|
40
|
+
max_wait_time: c_config.max_wait_time
|
41
|
+
)
|
42
|
+
|
43
|
+
iterator.each do |message|
|
44
|
+
iterator.stop if @stop
|
45
|
+
next if @stop
|
46
|
+
next unless message
|
47
|
+
|
48
|
+
yield(message)
|
49
|
+
rescue StandardError => e
|
50
|
+
report_error(e)
|
51
|
+
|
52
|
+
sleep(c_config.pause_timeout / 1_000)
|
53
|
+
|
54
|
+
next
|
55
|
+
end
|
56
|
+
rescue StandardError => e
|
57
|
+
report_error(e)
|
58
|
+
|
59
|
+
return if done?
|
60
|
+
|
61
|
+
sleep(c_config.pause_timeout / 1_000)
|
62
|
+
|
63
|
+
retry
|
64
|
+
end
|
65
|
+
|
66
|
+
# Triggers stop of the listener. Does **not** stop the listener but requests it to stop.
|
67
|
+
def stop
|
68
|
+
@stop = true
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# @return [Boolean] true if we should stop
|
74
|
+
def done?
|
75
|
+
@stop
|
76
|
+
end
|
77
|
+
|
78
|
+
# Reports any error that occurred in the manager
|
79
|
+
#
|
80
|
+
# Since we have an iterator based Kafka connection here, we do not have standard Karafka
|
81
|
+
# error handling and retries. This means, that we have to handle errors ourselves and
|
82
|
+
# report them to the instrumentation pipeline.
|
83
|
+
#
|
84
|
+
# @param error [StandardError] any error that occurred in the manager
|
85
|
+
def report_error(error)
|
86
|
+
::Karafka.monitor.instrument(
|
87
|
+
'error.occurred',
|
88
|
+
error: error,
|
89
|
+
caller: self,
|
90
|
+
type: 'web.controlling.controller.error'
|
91
|
+
)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,98 @@
|
|
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 Commanding
|
18
|
+
# Manager responsible for receiving commands and taking appropriate actions
|
19
|
+
# It uses the assign API instead of subscribe and it does NOT publish or change anything
|
20
|
+
# Since its subscription is not user-related and does not run any work in the workers, it
|
21
|
+
# is not visible in the statistics.
|
22
|
+
#
|
23
|
+
# There are few critical things here worth keeping in mind:
|
24
|
+
# - We do **not** use dynamic routing here and we do not inject active consumption
|
25
|
+
# - We use a direct assign API to get an "invisible" (from the end user) perspective
|
26
|
+
# connection to the commands topic for management. This is done that way so the end
|
27
|
+
# user does not see this connection within the UI as it should not be a manageable one
|
28
|
+
# anyhow. Also, on top of that, because we handle it under the hood, this is also not
|
29
|
+
# prone to saturation and other issues that can arise when working under stress. Thanks
|
30
|
+
# to that, probing can be handled almost immediately on command arrival.
|
31
|
+
# - Messages causing errors will be ignored and won't block.
|
32
|
+
# - Any errors are reported back to the Karafka monitor pipeline.
|
33
|
+
class Manager
|
34
|
+
include ::Karafka::Helpers::Async
|
35
|
+
include Singleton
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
@listener = Listener.new
|
39
|
+
@matcher = Matcher.new
|
40
|
+
end
|
41
|
+
|
42
|
+
# When app starts to run, we start to listen for commands
|
43
|
+
#
|
44
|
+
# @param _event [Karafka::Core::Monitoring::Event]
|
45
|
+
def on_app_running(_event)
|
46
|
+
async_call('karafka.web.pro.commanding.manager')
|
47
|
+
end
|
48
|
+
|
49
|
+
# When app stops, we stop the manager
|
50
|
+
#
|
51
|
+
# @param _event [Karafka::Core::Monitoring::Event]
|
52
|
+
def on_app_stopping(_event)
|
53
|
+
@listener.stop
|
54
|
+
end
|
55
|
+
|
56
|
+
# This ensures that in case of super fast shutdown, we wait on this in case it would be
|
57
|
+
# slower not to end up with a semi-closed iterator.
|
58
|
+
#
|
59
|
+
# @param _event [Karafka::Core::Monitoring::Event]
|
60
|
+
def on_app_stopped(_event)
|
61
|
+
@thread&.join
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
# Main iterator code.
|
67
|
+
# This iterator listens to the commands topic and when it detects messages targeting
|
68
|
+
# current process, performs the requested command.
|
69
|
+
def call
|
70
|
+
@listener.each do |message|
|
71
|
+
next unless @matcher.matches?(message)
|
72
|
+
|
73
|
+
control(message.payload[:command][:name])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Runs the expected command
|
78
|
+
#
|
79
|
+
# @param command [String] command expected to run
|
80
|
+
def control(command)
|
81
|
+
case command
|
82
|
+
when 'probe'
|
83
|
+
Commands::Probe.new.call
|
84
|
+
when 'stop'
|
85
|
+
Commands::Stop.new.call
|
86
|
+
when 'quiet'
|
87
|
+
Commands::Quiet.new.call
|
88
|
+
else
|
89
|
+
# We raise it and will be rescued, reported and ignored. We raise it as this should
|
90
|
+
# not happen unless there are version conflicts
|
91
|
+
raise ::Karafka::Errors::UnsupportedCaseError, command
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,50 @@
|
|
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 Commanding
|
18
|
+
# Matcher that makes a decision whether a given command message should be applied/executed
|
19
|
+
# within the context of the current consumer process.
|
20
|
+
#
|
21
|
+
# Since we use the `assign`, each process listens to this topic and receives messages
|
22
|
+
# with commands targeting all the processes, this is why it needs to be filtered.
|
23
|
+
class Matcher
|
24
|
+
# @param message [Karafka::Messages::Message] message with command
|
25
|
+
# @return [Boolean] is this message dedicated to current process and is actionable
|
26
|
+
def matches?(message)
|
27
|
+
matches = true
|
28
|
+
|
29
|
+
# We want to work only with commands that target all processes or our current
|
30
|
+
matches = false unless message.key == '*' || message.key == process_id
|
31
|
+
# We operate only on commands. Result messages should be ignored
|
32
|
+
matches = false unless message.payload[:type] == 'command'
|
33
|
+
# Ignore messages that have different schema. This can happen in the middle of
|
34
|
+
# upgrades of the framework. We ignore this not to risk compatibility issues
|
35
|
+
matches = false unless message.payload[:schema_version] == Dispatcher::SCHEMA_VERSION
|
36
|
+
|
37
|
+
matches
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# @return [String] current process id
|
43
|
+
def process_id
|
44
|
+
@process_id ||= ::Karafka::Web.config.tracking.consumers.sampler.process_id
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,40 @@
|
|
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
|
+
# Namespace for things related to consumers commanding (management)
|
18
|
+
#
|
19
|
+
# This feature allows for basic of consumers. They can be stopped, moved to quiet or probed
|
20
|
+
# via the Web UI
|
21
|
+
module Commanding
|
22
|
+
class << self
|
23
|
+
# Subscribes with the commanding manager when commanding is enabled
|
24
|
+
#
|
25
|
+
# @param config [Karafka::Core::Configurable::Node] web config
|
26
|
+
def post_setup(config)
|
27
|
+
# We do not use manager if commanding is not suppose to work at all
|
28
|
+
return unless config.commanding.active
|
29
|
+
|
30
|
+
Commanding::Contracts::Config.new.validate!(config.to_h)
|
31
|
+
|
32
|
+
::Karafka.monitor.subscribe(
|
33
|
+
Commanding::Manager.instance
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,40 @@
|
|
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
|
+
# Loader requires and loads all the pro components only when they are needed
|
18
|
+
class Loader
|
19
|
+
class << self
|
20
|
+
# Loads all the Web UI pro components and configures them wherever it is expected
|
21
|
+
# @param config [Karafka::Core::Configurable::Node] web config that we can alter with pro
|
22
|
+
# components
|
23
|
+
def pre_setup_all(config)
|
24
|
+
# Expand the config with commanding configuration
|
25
|
+
config.instance_eval do
|
26
|
+
setting(:commanding, default: Commanding::Config.config)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Runs post setup features configuration operations
|
31
|
+
#
|
32
|
+
# @param config [Karafka::Core::Configurable::Node]
|
33
|
+
def post_setup_all(config)
|
34
|
+
Commanding.post_setup(config)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|