feat: add Kafka publish for build/batch state-change events - #1381
feat: add Kafka publish for build/batch state-change events#1381ashwgit wants to merge 1 commit into
Conversation
|
🤖 Finished Review · ❌ Failure (validation failed after 2 iteration(s)) · Started 12:30 PM UTC · Completed 1:12 PM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $4.61 |
6d3a2c4 to
fb219fb
Compare
|
🤖 Finished Review · ❌ Failure (validation failed after 2 iteration(s)) · Started 1:57 PM UTC · Completed 2:39 PM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high |
fb219fb to
7dfa904
Compare
|
🤖 Finished Review · ✅ Success · Started 2:40 PM UTC · Completed 3:01 PM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $6.82 |
7dfa904 to
dce85fc
Compare
|
Risk Assessment: moderate (2/5) DetailsLarge blast radius and dual dependency file changes are the primary risk drivers, but clean recent git history (no churn, single-author files, no reverts on core modules) and adequate test coverage for the new Kafka producer keep the composite score at moderate. Previous runRisk Assessment: elevated (3/5) DetailsElevated risk: BLAST_RADIUS=large drives change-size to 5 and dual dependency-file changes also score 5, test coverage slipped to 0.20, and git history on messaging.py shows a pattern of hotfixes and reverts — together these push the score one point above the prior moderate assessment despite no protected paths or security-sensitive files being touched. Previous run (2)Risk Assessment: moderate (2/5) DetailsModerate risk: the PR adds a new Kafka messaging transport alongside existing AMQP with a new dependency and two new modules, but risk is tempered by solid test coverage (0.33 ratio), stable git history on modified files, no protected or security-sensitive paths touched, and a non-first-time author. |
ReviewFindingsMedium
Low
Next steps:
Previous runReviewReason: stale-head The review agent reviewed commit Previous run (2)ReviewReason: stale-head The review agent reviewed commit |
|
/fs-review |
|
🤖 Finished Review · ❌ Failure (validation failed after 2 iteration(s)) · Started 3:02 PM UTC · Completed 3:44 PM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high |
dce85fc to
45e62d0
Compare
|
🤖 Finished Review · ✅ Success · Started 7:39 AM UTC · Completed 8:01 AM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $6.43 |
Introduces Kafka messaging features, allowing IIB to broadcast build and batch state-change events to Kafka topics. - Added kafka-python support in IIB - Kafka messaging is optional and if brokers are not configured, IIB will skip trying sending messages to Kafka
45e62d0 to
51173ac
Compare
|
/fs-review |
|
🤖 Finished Review · ✅ Success · Started 8:02 AM UTC · Completed 8:23 AM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $6.23 |
There was a problem hiding this comment.
Note: The following review comments could not be posted on the diff (GitHub returned 422) and are included here instead:
iib/web/config.py(file-level): Line 58 · [low] architectural-coherence
DevelopmentConfig pre-populates sample AMQP values for developer discoverability but has no equivalent Kafka sample values.
Suggested fix: Add commented-out sample Kafka config values to DevelopmentConfig.
| if batch_data: | ||
| content, properties = batch_data | ||
| send_kafka_message(producer, batch_topic, content, properties) | ||
| except: # noqa: E722 |
There was a problem hiding this comment.
[medium] error-handling
Bare except: in _send_kafka_messages catches BaseException including SystemExit and KeyboardInterrupt, which can prevent clean process shutdown. The PR's own kafka_producer.py correctly uses except Exception:, creating an internal inconsistency.
Suggested fix: Replace except: # noqa: E722 with except Exception:.
| if ca_file: | ||
| producer_kwargs['ssl_cafile'] = ca_file | ||
|
|
||
| _kafka_producer = KafkaProducer(**producer_kwargs) |
There was a problem hiding this comment.
[medium] resource-lifecycle
The module-level _kafka_producer singleton is never explicitly flushed or closed. With linger_ms=5, buffered messages can be lost on process shutdown. No Flask teardown hook or signal handler calls producer.flush() / producer.close().
Suggested fix: Register a Flask teardown_appcontext or atexit handler that calls _kafka_producer.flush() and _kafka_producer.close().
There was a problem hiding this comment.
That's the tradeoff we have to accept for sending message async and not blocking the main thread for sending messages.
| BatchRequestResponseList, | ||
| ) | ||
|
|
||
| _kafka_producer: Optional[KafkaProducer] = None |
There was a problem hiding this comment.
[low] architectural-coherence
The Kafka path introduces a process-wide module-level singleton while the existing AMQP path creates a fresh connection per call. Tests work around this by directly resetting kafka_producer._kafka_producer = None. The singleton pattern is idiomatic for KafkaProducer but diverges from the project's existing connection model.
Suggested fix: Document the rationale for the singleton lifetime in a module-level docstring, or scope the producer to the Flask application context.
There was a problem hiding this comment.
Creating Kafka connection for each message will be a heavy weight operation and considering the scale of request IIB receives, having a single Producer reduces the load at a good factor. So I will stick with this one.
| global _kafka_producer | ||
|
|
||
| # First check without lock for performance | ||
| if _kafka_producer is not None: |
There was a problem hiding this comment.
[low] edge-case
Double-checked locking caches the producer indefinitely. No reconnection, cache-invalidation, or credential-rotation mechanism exists. The application must be fully restarted for new credentials or to recover from certain failure modes.
Suggested fix: Add a mechanism to invalidate the cached producer (e.g., TTL-based refresh, a reset function, or a signal handler).
There was a problem hiding this comment.
It will become complex to add such facility in a single MR. It might be better to create a separate MR in case if the current implementation causes issue.
| 'security_protocol': 'SASL_SSL', | ||
| 'sasl_mechanism': 'SCRAM-SHA-512', | ||
| 'sasl_plain_username': username, | ||
| 'sasl_plain_password': password, |
There was a problem hiding this comment.
[low] secrets-handling
Kafka password placed in producer_kwargs dict could be exposed if logger.exception() captures local variables in certain logging or APM configurations.
Suggested fix: Clear password from producer_kwargs in a finally block, or pass credentials as direct keyword arguments.
There was a problem hiding this comment.
I don't think we are having any such custom logging configuration.
|
|
||
| def _build_request_state_change_data( | ||
| request: Request, | ||
| ) -> tuple: |
There was a problem hiding this comment.
[low] api-shape-patterns
_build_request_state_change_data and _build_batch_state_change_data return bare tuple instead of explicit Tuple[...] generics used elsewhere in the codebase.
Suggested fix: Use Tuple[BaseClassRequestResponse, Dict[str, Any]] and Optional[Tuple[...]].
| IIB_REQUEST_RELATED_BUNDLES_DIR: Optional[str] = None | ||
| IIB_REQUEST_RECURSIVE_RELATED_BUNDLES_DIR: Optional[str] = None | ||
| IIB_USER_TO_QUEUE: Union[Dict[str, str], Dict[str, Dict[str, str]]] = _get_empty_dict_str_str() | ||
| # Kafka messaging configuration |
There was a problem hiding this comment.
[low] naming-convention
Existing messaging config uses IIB_MESSAGING_* prefix; this PR introduces a parallel IIB_KAFKA_* namespace. A separate namespace is reasonable given the different transport backends, but diverges from the single-prefix pattern.
Suggested fix: Consider IIB_MESSAGING_KAFKA_* to keep messaging config under one prefix, or document the naming rationale.
There was a problem hiding this comment.
As most of the configs are for Kafka, it suits better to have kafka for these configs.
| mock_sm.assert_not_called() | ||
|
|
||
|
|
||
| @mock.patch('iib.web.messaging._send_kafka_messages') |
There was a problem hiding this comment.
[low] test-inadequate
test_send_messages_for_new_batch_of_requests_no_requests mocks _send_kafka_messages but does not assert it is NOT called when the request list is empty.
Suggested fix: Add mock_skm.assert_not_called().
| messages when a build request state changes and when a batch state changes. Please note that if a | ||
| message can't be sent due to an infrastructure issue, the build request will continue as it is not | ||
| considered a fatal error. | ||
| IIB has support to send messages to an AMQP 1.0 broker (will be depricated in future) and to Apache Kafka topics. |
There was a problem hiding this comment.
[low] scope-creep
States AMQP 'will be deprecated' but the PR provides no deprecation warning, migration guide, or timeline.
Suggested fix: Remove the deprecation claim from the README or open a follow-up issue tracking AMQP deprecation.
There was a problem hiding this comment.
No warning reqired, as the web service logs is only available to operator foundry team.
| messages when a build request state changes and when a batch state changes. Please note that if a | ||
| message can't be sent due to an infrastructure issue, the build request will continue as it is not | ||
| considered a fatal error. | ||
| IIB has support to send messages to an AMQP 1.0 broker (will be depricated in future) and to Apache Kafka topics. |
There was a problem hiding this comment.
[low] documentation-quality
Contains 'depricated' (typo for 'deprecated') and 'Please notethat' (missing space between 'note' and 'that').
Suggested fix: Correct to 'deprecated' and 'Please note that'.
There was a problem hiding this comment.
Thanks, will correct it.
Related Jira Ticket : CLOUDDST-32828
Overview
This PR introduces Kafka messaging features, allowing IIB to broadcast build and batch state-change events to Kafka topics. Implemented code make things modular so that the legacy AMQP/UMB feature could be depricated easily. This MR will :
Architectural & Security Highlights
Configuration :
@release-engineering/exd-guild-hello-operator PTAL