Skip to content

Conversation

@rafabene
Copy link
Contributor

@rafabene rafabene commented Feb 11, 2026

Summary

  • Add Health() error method to the Publisher interface for readiness probes
  • RabbitMQ: in-memory check via IsConnected() / Closed() (no network call)
  • Google Pub/Sub: lightweight ListTopics API call (page size 1, 3s timeout) using a persistent client
  • Fix 3 standard library CVEs
  • Share testcontainers across tests via TestMain (4 containers total instead of ~25)
  • Fix goroutine leak in subscriber Close() by cancelling router contexts
  • Fix GenerateSubscriptionName to include topic name, preventing PubSub subscription conflicts
  • Add configurable log level to NewTestLogger (WithLevel option), tests use WARN level
  • Add -p 1 to test-integration Makefile target for streaming output

Test plan

  • Unit tests for Health() with healthy/unhealthy publisher
  • Unit test for RabbitMQ type assertion failure path
  • Integration tests pass with shared containers (RabbitMQ + PubSub emulator)
  • Goroutine leak tests pass (0 leaked for RabbitMQ, tolerance of 4 for PubSub gRPC internals)
  • make test passing
  • make lint passing (0 issues)
  • govulncheck passing (0 vulnerabilities)

@openshift-ci openshift-ci bot requested review from 86254860 and Mischulee February 11, 2026 15:34
@openshift-ci
Copy link

openshift-ci bot commented Feb 11, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign tirthct for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a Publisher Health() API and broker-specific health checks. The Publisher interface gains Health(); the concrete publisher stores an optional healthCheck func and optional io.Closer healthCloser. New RabbitMQ health check inspects AMQP publisher Closed()/IsConnected(); Google Pub/Sub health check reuses a persistent pubsub.Client and performs a lightweight ListTopics (page size 1, 3s timeout). NewPublisher wires healthCheck and healthCloser; Close() closes healthCloser. Tests, README health documentation, and go.mod updates for pubsub/v2 were added.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Publisher
    participant HealthCheck as HealthCheckFunc
    participant Broker as RabbitMQ/GooglePubSub
    participant PubSubClient as Pub/Sub Client

    Client->>Publisher: Health()
    activate Publisher
    Publisher->>HealthCheck: invoke()
    activate HealthCheck

    alt RabbitMQ flow
        HealthCheck->>Broker: type assert to *amqp.Publisher
        Broker-->>HealthCheck: publisher ref
        HealthCheck->>Broker: Closed() / IsConnected()
        Broker-->>HealthCheck: state/result
    else Google Pub/Sub flow
        HealthCheck->>PubSubClient: ListTopics(ctx, PageSize=1, Timeout=3s)
        PubSubClient-->>HealthCheck: iterator
        HealthCheck->>PubSubClient: iterator.Next()
        PubSubClient-->>HealthCheck: iterator.Done or error
    end

    HealthCheck-->>Publisher: nil or error
    deactivate HealthCheck
    Publisher-->>Client: nil or error
    deactivate Publisher
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly references the main feature added (Health() method) and mentions two other objectives (optimize integration tests, fix goroutine leak), all of which are present in the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@broker/broker.go`:
- Around line 78-86: The publisher `pub` created by newGooglePubSubPublisher is
leaked when pubsub.NewClient fails; update the error path after calling
pubsub.NewClient (and before returning) to close/cleanup the previously created
publisher `pub` (or call its Close/Stop method) so resources are released, e.g.,
call the publisher's close method and handle/aggregate any close error before
returning the fmt.Errorf from the failing pubsub.NewClient call; reference
newGooglePubSubPublisher, pub, pubsub.NewClient, and healthClient to find the
exact spot to insert the cleanup.
🧹 Nitpick comments (1)
broker/publisher.go (1)

58-62: Consider adding a nil check for healthCheck to prevent potential panics.

If healthCheck is nil (e.g., in test scenarios or future broker types), calling p.healthCheck() will panic. A defensive nil check would improve robustness.

🛡️ Proposed defensive fix
 func (p *publisher) Health() error {
+	if p.healthCheck == nil {
+		return nil // No health check configured
+	}
 	return p.healthCheck()
 }

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@broker/publisher.go`:
- Around line 58-62: The Health() method on publisher currently calls
p.healthCheck() unguarded and will panic if healthCheck is nil; modify
publisher.Health() to first check if p == nil or p.healthCheck == nil and return
a clear error (e.g., errors.New or fmt.Errorf like "health check not
configured") instead of invoking the nil function, otherwise call and return
p.healthCheck(); reference the publisher type and the Health() and healthCheck
symbols when making the change.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@README.md`:
- Around line 117-119: The README note about Google Pub/Sub ends with a
truncated sentence; update the sentence referencing the Google Pub/Sub publisher
(via Watermill/Google Cloud SDK) to finish the thought—e.g., "The app should
call Close() to avoid leaking resources/goroutines"—so it clearly states what
Close() prevents (background goroutines or resources) and mention the Close()
method explicitly for clarity.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@broker/rabbitmq.go`:
- Around line 28-42: newRabbitMQHealthCheck may panic if pub is a nil
*amqp.Publisher because the type assertion succeeds but amqpPub can be nil;
after the type assertion in newRabbitMQHealthCheck (checking
pub.(*amqp.Publisher)), add an explicit nil check for amqpPub and return a
descriptive error if nil before calling amqpPub.Closed() or
amqpPub.IsConnected(); reference the types message.Publisher and *amqp.Publisher
and the methods Closed and IsConnected when implementing the guard.
🧹 Nitpick comments (1)
broker/health_test.go (1)

12-37: Consider adding a test case for nil healthCheck.

The Health() method includes a guard for p.healthCheck == nil returning "health check not configured", but there's no test covering this path. Adding this would improve coverage of the defensive nil check.

💡 Suggested test case
t.Run("nil healthCheck returns error", func(t *testing.T) {
	p := &publisher{
		logger:      mockLogger,
		healthCheck: nil,
	}
	err := p.Health()
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "health check not configured")
})

@rafabene
Copy link
Contributor Author

After merging, tag v1.0.2 must be created.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@README.md`:
- Around line 120-134: Add a note to the Health Check section explaining that
the Google Pub/Sub Health() implementation uses the ListTopics API and therefore
requires the IAM permission pubsub.topics.list on the project; clarify that this
is separate from publish permissions (e.g., pubsub.topics.publish) so a
principal that can publish but lacks pubsub.topics.list will cause
Publisher.Health() to fail and may misconfigure readiness probes.
🧹 Nitpick comments (1)
broker/health_test.go (1)

39-59: Clarify the non-AMQP publisher comment.

✏️ Suggested tweak
-		// Pass a nil publisher wrapped in the message.Publisher interface
-		// to trigger the type assertion failure
+		// Pass a non-AMQP publisher to trigger the type assertion failure

- Add Health() error to Publisher interface for readiness probes
- RabbitMQ: in-memory check via IsConnected()/Closed() (no network call)
- Google Pub/Sub: lightweight ListTopics API call (page size 1, 3s timeout)
- Fix publisher resource leak when health check client creation fails
- Guard Health() against nil healthCheck to prevent panic
- Guard RabbitMQ health check against nil *amqp.Publisher to prevent panic
- Fix truncated sentence in README for Google Pub/Sub Close() note
- Document pubsub.topics.list IAM permission requirement for Health()
- GO-2026-4341: memory exhaustion in net/url query parameter parsing
- GO-2026-4340: TLS handshake messages processed at incorrect encryption level
- GO-2026-4337: unexpected TLS session resumption
- Share testcontainers across tests via TestMain (4 containers total
  instead of ~25), significantly reducing test execution time
- Fix goroutine leak in subscriber Close() by cancelling router
  contexts before waiting for goroutines to finish
- Fix GenerateSubscriptionName to include topic name, preventing
  PubSub subscription conflicts across different topics
- Use unique topic/subscription names per test to avoid interference
  when sharing containers
- Add configurable log level to NewTestLogger (WithLevel option),
  set tests to WARN level to suppress Watermill INFO-level chatter
- Add -p 1 to Makefile test-integration target for streaming output
@rafabene rafabene changed the title HYPERFLEET-641: Add Health() method to Publisher interface HYPERFLEET-641: Add Health() method, optimize integration tests, fix goroutine leak Feb 11, 2026
@rafabene
Copy link
Contributor Author

@coderabbitai resume

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.

1 participant