Skip to content

Add Kafka messaging backend - #125

Merged
asabadra merged 7 commits into
fedora-modularity:masterfrom
asabadra:umb-to-kafka
Nov 3, 2026
Merged

asabadra merged 7 commits into
fedora-modularity:masterfrom
asabadra:umb-to-kafka

Conversation

@asabadra

Copy link
Copy Markdown
Collaborator

Summary

Adds kafka as a third messaging backend alongside fedora-messaging and rhmsg. MTS can now consume MBS module state change events from and publish tagging events to Kafka. It plugs into the existing messaging_backend dispatch, so existing deployments are unaffected — they stay on their current backend by default.

Changes

  • Publisher (messaging.py) — _kafka_publish() registered under the kafka backend. Topics are built as {kafka_topic_prefix}.{topic} so callers keep passing short names like build.tagged. Sends block on broker ack so delivery errors surface to the caller instead of being swallowed by the async producer. dry_run is honored. A shared kafka_client_config() builds connection kwargs for both producer and consumer, including only the options that are actually set.
  • Consumer (consumer.py) — KafkaMessage mirrors the existing UMBMessage interface (id/topic/body), with the id derived from topic-partition-offset since Kafka records carry none. kafka_backend() disables auto-commit and commits only after processing, giving at-least-once delivery. Undecodable bodies are logged and committed so a poison message can't wedge the consumer.
  • Config — kafka_* options for bootstrap servers, consumer topic/group, offset reset, topic prefix, send timeout, and security. Defaults to SASL_SSL + SCRAM-SHA-512 on port 9096. SASL credentials come from MTS_KAFKA_USERNAME / MTS_KAFKA_PASSWORD so the secret stays out of the config file.
  • Packaging — kafka-python==2.0.2 in requirements.in and both lockfiles; python3-kafka in the container deps.
  • Docs — README section on the three backends, plus the two new env vars.

Tests

5 unit tests covering the consume path, offset commit/close, invalid bodies, KafkaMessage, and publish (config pass-through and dry-run). All fake the kafka module, so no broker is needed.

asabadra-lab and others added 4 commits September 2, 2026 10:13
Add a 'kafka' messaging backend alongside the existing rhmsg (UMB) and
fedora-messaging backends, per the UMB-to-Kafka migration guide. The
Messaging Bridge keeps the UMB and Kafka topics in sync, so the producer
and consumer can be switched to Kafka independently while other services
remain on UMB. The UMB (rhmsg) client is retained for now and can be
removed once the migration is confirmed.

- messaging.py: add _kafka_publish and a shared kafka_client_config
  helper; register the 'kafka' backend.
- consumer.py: add KafkaMessage wrapper and kafka_backend using
  kafka-python with manual offset commits (at-least-once); wire into run().
- conf/config.py: add kafka_* config (bootstrap servers, topic/group,
  offset reset, topic prefix, send timeout, and SASL/SSL auth options).
- requirements*: add kafka-python==2.0.2.
- docker/install-dependencies.sh: install python3-kafka.
- tests: cover the Kafka producer, consumer, and message wrapper.
- README: document the three messaging backends and Kafka config.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Read the Kafka SASL username/password from MTS_KAFKA_USERNAME and
MTS_KAFKA_PASSWORD so the secret does not have to live in the config
file, and clarify that SCRAM-SHA-512 over SASL_SSL connects on port 9096.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@asabadra

Copy link
Copy Markdown
Collaborator Author

@azhuzhu @lcarva @ralphbean do you have merge perms? can you review please?

The VirtualTopic.* namespace is a UMB addressing convention and has no
meaning on Kafka. Align the Kafka topic declarations with the names
registered in it-platform/kafka!911 (producer) and !768 (consumer):

  kafka_topic_prefix     eng.mts
  kafka_consumer_topic   eng.mbs.module.state.change

The rhmsg settings keep VirtualTopic.* since that backend still targets
UMB. Stage uses a stage.* prefix on both, set in the deployment overlay
rather than here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@asabadra
asabadra requested a review from tkopecek October 26, 2026 13:30
The consume loop only caught JSONDecodeError. Any other exception escaped
the loop, closed the consumer and ended the process with the offset
uncommitted, so the restart was re-delivered the same record and failed
again -- a crash loop that makes no further progress.

This is reachable with a well-formed JSON body: the NSVC is built with
'{name}:{stream}:{version}:{context}'.format(**mbs_msg) outside of the
try block in consume(), so a message missing one of those fields raises
KeyError. A connection error while fetching the rules file escapes the
same way, turning a transient fault into a stuck consumer.

Log the failure and commit the offset instead, which is what consume()
already does for a failed tagging attempt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both jobs failed at the "Set up Python 3.9" step, before tox ever ran:

  The version '3.9' with architecture 'x64' was not found for Ubuntu 26.04.

ubuntu-latest began migrating to Ubuntu 26.04 on 2026-10-19, and the
actions/python-versions manifest has no 3.9 build for 26.04, though it
does for 3.10 and newer. Pinning the runner restores a combination where
3.9 is available.

Python 3.9 has been EOL since 2025-10, so moving the test matrix off it
is the durable fix; this only unblocks CI in the meantime.

Also bump actions/setup-python v4 to v6. That is unrelated hygiene, not
part of the fix above: v4 targets the deprecated node16 runtime, but
deprecated runtimes are force-upgraded with a warning rather than
failed, so it was never what broke these jobs.

This is pre-existing breakage on master rather than anything to do with
the Kafka backend, but CI could not report on this branch until it was
fixed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@asabadra
asabadra merged commit fc618f8 into fedora-modularity:master Nov 3, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants