Skip to content

feat: add some grpc utils #403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

feat: add some grpc utils #403

wants to merge 2 commits into from

Conversation

gfyrag
Copy link
Contributor

@gfyrag gfyrag commented Apr 22, 2025

No description provided.

@gfyrag gfyrag requested a review from a team as a code owner April 22, 2025 10:00
Copy link

coderabbitai bot commented Apr 22, 2025

Walkthrough

This set of changes introduces new abstractions and refactors existing code to unify and simplify server lifecycle management for both HTTP and gRPC servers. A new serverport package is added, providing context-based server metadata propagation, listener management, and lifecycle signaling. The HTTP and gRPC server packages are refactored to delegate listener and address management to serverport, replacing custom implementations with shared, context-aware logic. Functional options patterns are adopted for flexible configuration. Additionally, the ClickHouse test server setup is enhanced with retry logic and version configurability, and new instrumentation helpers are added for gRPC test services. Minor improvements are made to error handling in deferred test utilities.

Changes

File(s) Change Summary
grpcserver/serverport.go New package for gRPC server lifecycle management using serverport and Uber Fx. Adds context helpers, functional options for configuration, and a lifecycle hook to start/stop gRPC servers with clean shutdown and context propagation.
httpserver/serverport.go Refactored HTTP server management to delegate listener/address and context handling to serverport. Replaces custom server state with ServerOptions and option modifiers. Updates lifecycle hook and server startup logic to use serverport.Server.
serverport/serverport.go New package providing Server and ServerInfo abstractions for context-based server lifecycle, address propagation, and listener management. Includes functional options for listener/address, context helpers for storing/retrieving server info, and methods for signaling readiness.
testing/deferred/deferred.go Enhanced Deferred type: Reset now clears stored error; Wait returns error immediately if present after completion, ensuring proper error propagation in asynchronous test scenarios.
testing/platform/clickhousetesting/clickhouse.go Improved database cleanup with retry logic for dropping databases. Refactored CreateServer to accept functional options for server configuration, including customizable ClickHouse version. Imports added for error code checking and timing.
testing/testservice/instrumentation_grpcserver.go New file adding gRPC server instrumentation for test services. Provides functions to inject gRPC server info into contexts and retrieve gRPC server addresses from test service instances, relying on the new grpcserver package.

Sequence Diagram(s)

sequenceDiagram
    participant FxApp
    participant ServerPort
    participant gRPCServer
    participant Context

    FxApp->>ServerPort: NewServer(discr, opts...)
    FxApp->>ServerPort: Listen(ctx)
    ServerPort->>Context: ContextWithServerInfo(ctx, discr)
    FxApp->>gRPCServer: New(grpcOpts...)
    FxApp->>gRPCServer: Apply setup options
    FxApp->>gRPCServer: Serve(ServerPort.Listener)
    Note over gRPCServer: Server runs asynchronously
    FxApp->>gRPCServer: Stop() on shutdown
Loading
sequenceDiagram
    participant FxApp
    participant ServerPort
    participant HTTPServer
    participant Context

    FxApp->>ServerPort: NewServer("http", opts...)
    FxApp->>ServerPort: Listen(ctx)
    ServerPort->>Context: ContextWithServerInfo(ctx, "http")
    FxApp->>HTTPServer: New(handler, httpOpts...)
    FxApp->>HTTPServer: Serve(ServerPort.Listener)
    Note over HTTPServer: Server runs asynchronously
    FxApp->>HTTPServer: Shutdown() on stop
Loading

Suggested reviewers

  • laouji

Poem

In the warren of code, new tunnels appear,
With context and listeners, all crystal clear.
HTTP and gRPC, now hop paw in paw,
Serverport guides them—no tooth, only law!
Testing gets clever, with retries and flair,
A rabbit’s delight: clean shutdowns everywhere.
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Base automatically changed from feat/clickhousetesting-configurable-version to main April 22, 2025 11:34
Copy link

codecov bot commented Apr 22, 2025

Codecov Report

Attention: Patch coverage is 0% with 187 lines in your changes missing coverage. Please review.

Project coverage is 34.29%. Comparing base (9dde2a1) to head (0689c5e).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
grpcserver/serverport.go 0.00% 66 Missing ⚠️
serverport/serverport.go 0.00% 60 Missing ⚠️
testing/platform/clickhousetesting/clickhouse.go 0.00% 25 Missing ⚠️
httpserver/serverport.go 0.00% 24 Missing ⚠️
testing/testservice/instrumentation_grpcserver.go 0.00% 8 Missing ⚠️
testing/deferred/deferred.go 0.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #403      +/-   ##
==========================================
- Coverage   35.11%   34.29%   -0.83%     
==========================================
  Files         124      127       +3     
  Lines        5263     5389     +126     
==========================================
  Hits         1848     1848              
- Misses       3306     3432     +126     
  Partials      109      109              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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: 4

🧹 Nitpick comments (5)
serverport/serverport.go (2)

14-22: Potential panic risk with type assertion.

The type assertion on line 21 (siAsAny.(*ServerInfo)) lacks a safety check, which could cause a panic if the wrong type is stored in the context. Although this should not happen if only this package manipulates the context value, it's best to use a safer approach.

Consider modifying the code to use the safer two-value type assertion pattern:

func GetActualServerInfo(ctx context.Context, discr string) *ServerInfo {
	siAsAny := ctx.Value(serverInfoContextKey(discr))
	if siAsAny == nil {
		return nil
	}
-	return siAsAny.(*ServerInfo)
+	si, ok := siAsAny.(*ServerInfo)
+	if !ok {
+		return nil
+	}
+	return si
}
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 16-21: serverport/serverport.go#L16-L21
Added lines #L16 - L21 were not covered by tests


57-61: Consider adding thread safety mechanisms.

The Server struct holds state that might be accessed concurrently, especially when used in a server context. Without proper synchronization, this could lead to race conditions.

Consider adding a mutex to protect access to the fields, especially when updating the listener:

type Server struct {
	Listener net.Listener
	Address  string
	Discr    string
+	mu       sync.Mutex
}

And then protect critical sections with lock/unlock operations.

testing/testservice/instrumentation_grpcserver.go (1)

18-20: Consider adding error handling.

The GetGRPCAddress function doesn't handle the case where the address might not be available yet. If called before the server is fully initialized, it will simply return an empty string with no indication of the failure condition.

Consider returning an error or providing a timeout-based approach:

-func GetGRPCAddress(service *Service) string {
+func GetGRPCAddress(service *Service) (string, error) {
	addr := grpcserver.Address(service.GetContext())
+	if addr == "" {
+		return "", errors.New("gRPC server address not available")
+	}
-	return grpcserver.Address(service.GetContext())
+	return addr, nil
}
grpcserver/serverport.go (1)

34-38: Graceful shutdown should also close the listener

grpc.Server.GracefulStop() stops accepting new connections but does not close the underlying listener.
When a custom listener is injected through serverport.WithListener, the application may hold on to the socket after shutdown.

 return func(ctx context.Context) error {
     grpcServer.GracefulStop()
+    if s.Listener != nil {
+        _ = s.Listener.Close()
+    }
     return nil
 }, nil

This prevents “address already in use” errors on subsequent restarts (handy in tests).

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 34-38: grpcserver/serverport.go#L34-L38
Added lines #L34 - L38 were not covered by tests

httpserver/serverport.go (1)

42-44: Avoid panicking on serve errors – use structured logging like the gRPC path

A panic will tear down the entire Fx app, whereas a logged error (plus returning the error through a channel if you want to fail the lifecycle) gives callers a chance to react.

-    err := srv.Serve(s.Listener)
-    if err != nil && err != http.ErrServerClosed {
-        panic(err)
+    if err := srv.Serve(s.Listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
+        logging.FromContext(ctx).Errorf("HTTP server failed to serve: %v", err)
+    }

This change keeps behaviour consistent with the gRPC starter and avoids unexpected crashes in production.
(Requires errors import.)

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 42-42: httpserver/serverport.go#L42
Added line #L42 was not covered by tests

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec98813 and 0689c5e.

⛔ Files ignored due to path filters (1)
  • go.mod is excluded by !**/*.mod
📒 Files selected for processing (6)
  • grpcserver/serverport.go (1 hunks)
  • httpserver/serverport.go (4 hunks)
  • serverport/serverport.go (1 hunks)
  • testing/deferred/deferred.go (2 hunks)
  • testing/platform/clickhousetesting/clickhouse.go (4 hunks)
  • testing/testservice/instrumentation_grpcserver.go (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
testing/testservice/instrumentation_grpcserver.go (4)
testing/testservice/instrumentation.go (3)
  • Instrumentation (35-37)
  • InstrumentationFunc (38-38)
  • RunConfiguration (8-13)
serverport/serverport.go (2)
  • ContextWithServerInfo (24-28)
  • Address (38-44)
grpcserver/serverport.go (2)
  • ContextWithServerInfo (14-16)
  • Address (41-43)
testing/testservice/service.go (1)
  • Service (15-22)
httpserver/serverport.go (2)
serverport/serverport.go (7)
  • ContextWithServerInfo (24-28)
  • Address (38-44)
  • Server (57-61)
  • ServerOpts (92-92)
  • WithListener (94-98)
  • WithAddress (100-104)
  • NewServer (80-90)
grpcserver/serverport.go (6)
  • ContextWithServerInfo (14-16)
  • Address (41-43)
  • ServerOptions (45-49)
  • WithServerPortOptions (53-57)
  • ServerOptionModifier (51-51)
  • NewHook (71-106)
grpcserver/serverport.go (3)
serverport/serverport.go (5)
  • ContextWithServerInfo (24-28)
  • Server (57-61)
  • NewServer (80-90)
  • Address (38-44)
  • ServerOpts (92-92)
httpserver/serverport.go (5)
  • ContextWithServerInfo (17-19)
  • ServerOptions (53-56)
  • WithServerPortOptions (60-64)
  • ServerOptionModifier (58-58)
  • NewHook (80-116)
logging/context.go (1)
  • FromContext (12-20)
🪛 GitHub Check: codecov/patch
serverport/serverport.go

[warning] 16-21: serverport/serverport.go#L16-L21
Added lines #L16 - L21 were not covered by tests


[warning] 24-27: serverport/serverport.go#L24-L27
Added lines #L24 - L27 were not covered by tests


[warning] 30-35: serverport/serverport.go#L30-L35
Added lines #L30 - L35 were not covered by tests


[warning] 38-43: serverport/serverport.go#L38-L43
Added lines #L38 - L43 were not covered by tests


[warning] 46-50: serverport/serverport.go#L46-L50
Added lines #L46 - L50 were not covered by tests


[warning] 52-54: serverport/serverport.go#L52-L54
Added lines #L52 - L54 were not covered by tests


[warning] 63-72: serverport/serverport.go#L63-L72
Added lines #L63 - L72 were not covered by tests

httpserver/serverport.go

[warning] 18-18: httpserver/serverport.go#L18
Added line #L18 was not covered by tests


[warning] 24-24: httpserver/serverport.go#L24
Added line #L24 was not covered by tests


[warning] 27-27: httpserver/serverport.go#L27
Added line #L27 was not covered by tests


[warning] 29-30: httpserver/serverport.go#L29-L30
Added lines #L29 - L30 were not covered by tests


[warning] 42-42: httpserver/serverport.go#L42
Added line #L42 was not covered by tests


[warning] 60-62: httpserver/serverport.go#L60-L62
Added lines #L60 - L62 were not covered by tests


[warning] 66-67: httpserver/serverport.go#L66-L67
Added lines #L66 - L67 were not covered by tests


[warning] 70-71: httpserver/serverport.go#L70-L71
Added lines #L70 - L71 were not covered by tests


[warning] 74-75: httpserver/serverport.go#L74-L75
Added lines #L74 - L75 were not covered by tests


[warning] 80-80: httpserver/serverport.go#L80
Added line #L80 was not covered by tests


[warning] 86-89: httpserver/serverport.go#L86-L89
Added lines #L86 - L89 were not covered by tests


[warning] 91-93: httpserver/serverport.go#L91-L93
Added lines #L91 - L93 were not covered by tests


[warning] 102-102: httpserver/serverport.go#L102
Added line #L102 was not covered by tests

grpcserver/serverport.go

[warning] 14-15: grpcserver/serverport.go#L14-L15
Added lines #L14 - L15 were not covered by tests


[warning] 18-22: grpcserver/serverport.go#L18-L22
Added lines #L18 - L22 were not covered by tests


[warning] 24-31: grpcserver/serverport.go#L24-L31
Added lines #L24 - L31 were not covered by tests


[warning] 34-38: grpcserver/serverport.go#L34-L38
Added lines #L34 - L38 were not covered by tests


[warning] 41-42: grpcserver/serverport.go#L41-L42
Added lines #L41 - L42 were not covered by tests


[warning] 53-56: grpcserver/serverport.go#L53-L56
Added lines #L53 - L56 were not covered by tests


[warning] 59-62: grpcserver/serverport.go#L59-L62
Added lines #L59 - L62 were not covered by tests


[warning] 65-68: grpcserver/serverport.go#L65-L68
Added lines #L65 - L68 were not covered by tests


[warning] 71-80: grpcserver/serverport.go#L71-L80
Added lines #L71 - L80 were not covered by tests


[warning] 82-103: grpcserver/serverport.go#L82-L103
Added lines #L82 - L103 were not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (7)
serverport/serverport.go (1)

80-90: Good use of functional options pattern.

The implementation of NewServer with functional options is clean and follows Go best practices. This approach provides a flexible and extensible way to configure the server.

testing/deferred/deferred.go (2)

53-53: Good fix: Clear error field on reset.

Adding d.err = nil ensures that when a deferred operation is reset, any previous error state is properly cleared. This prevents stale errors from affecting future operations after a reset.


69-71: Improved error handling in Wait method.

The change to check for errors before checking if the value is nil is a sound improvement. It properly prioritizes error reporting over nil value reporting, ensuring that errors are surfaced correctly to callers.

testing/testservice/instrumentation_grpcserver.go (1)

9-16: Clean implementation of gRPC server instrumentation.

The GRPCServerInstrumentation function effectively injects gRPC server information into the context. This is a clean approach that keeps server lifecycle management consistent with the patterns used elsewhere in the codebase.

testing/platform/clickhousetesting/clickhouse.go (3)

59-75: Good resilience improvement with retry logic.

The added retry logic for database cleanup is a solid improvement. It addresses potential race conditions when dropping databases by retrying the operation when ClickHouse responds with a "database not empty" error. The use of a reasonable max retry count (10) and delay (100ms) balances resilience with test responsiveness.


85-96: Well-implemented functional options pattern.

The modification to CreateServer to use functional options follows Go best practices and provides a clean, extensible way to configure the ClickHouse test server. The approach aligns with similar patterns used in the new serverport package.


131-145: Good addition of server configuration options.

The implemented ServerOptions, ServerOption, and WithVersion components provide a flexible way to configure the ClickHouse server version. The default version (25.2-alpine) is sensibly chosen.

Comment on lines +16 to +22
func GetActualServerInfo(ctx context.Context, discr string) *ServerInfo {
siAsAny := ctx.Value(serverInfoContextKey(discr))
if siAsAny == nil {
return nil
}
return siAsAny.(*ServerInfo)
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

Add unit tests for critical context manipulation functions.

The static analysis reports indicate that several key functions like GetActualServerInfo, ContextWithServerInfo, Started, Address, StartedServer, and Listen are not covered by tests. These functions are central to the package's functionality and should be thoroughly tested.

Also applies to: 24-28, 30-36, 38-44, 46-55, 63-78


🏁 Script executed:

#!/bin/bash
# Check if there are any test files for this package
fd -t f "_test.go" serverport/

Length of output: 30


Let’s search more thoroughly for any Go test files or test functions in the serverport package:


🏁 Script executed:

#!/bin/bash
# Find any *_test.go files under serverport/
find serverport/ -type f -name "*_test.go"

# Search for Go test or benchmark functions in serverport/
rg -n "func (Test|Benchmark)[A-Za-z0-9_]*" serverport/

Length of output: 101


Add comprehensive unit tests for serverport package

There are currently no _test.go files or test functions covering critical operations in serverport/serverport.go. Please add unit tests for:

  • ContextWithServerInfo / GetActualServerInfo (lines 16–22)
  • Started, Address
  • StartedServer, Listen

These functions manipulate and extract server info via context.Context and form the core API; testing their behavior (valid key, missing key, nil handling, correct value retrieval) is essential.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 16-21: serverport/serverport.go#L16-L21
Added lines #L16 - L21 were not covered by tests

Comment on lines +28 to +32
go func() {
if err := grpcServer.Serve(s.Listener); err != nil {
logging.FromContext(ctx).Errorf("failed to serve: %v", err)
}
}()
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Surface serving errors – align behaviour with the HTTP implementation

grpcServer.Serve can exit immediately (e.g. port already in use, TLS mis‑configuration).
In the HTTP starter we panic on such unrecoverable conditions, but here we only log, allowing the application to keep running in a half‑initialised state.

 go func() {
-    if err := grpcServer.Serve(s.Listener); err != nil {
-        logging.FromContext(ctx).Errorf("failed to serve: %v", err)
+    if err := grpcServer.Serve(s.Listener); err != nil && !errors.Is(err, grpc.ErrServerStopped) {
+        panic(fmt.Errorf("GRPC server failed to serve: %w", err))
     }
 }()

Doing so keeps both stacks consistent and fails fast when the port cannot be bound.
(Requires the errors and fmt imports.)

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
go func() {
if err := grpcServer.Serve(s.Listener); err != nil {
logging.FromContext(ctx).Errorf("failed to serve: %v", err)
}
}()
go func() {
if err := grpcServer.Serve(s.Listener); err != nil && !errors.Is(err, grpc.ErrServerStopped) {
panic(fmt.Errorf("GRPC server failed to serve: %w", err))
}
}()

Comment on lines +91 to 94
server := serverport.NewServer(serverPortDiscr)
for _, option := range serverOptions.serverOptions {
option(server)
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Pass accumulated server‑port options directly when constructing the server

You already gather serverOptions.serverOptions; pass them to the constructor like the gRPC implementation and drop the follow‑up mutation loop for simplicity & immutability.

-server := serverport.NewServer(serverPortDiscr)
-for _, option := range serverOptions.serverOptions {
-    option(server)
-}
+server := serverport.NewServer(serverPortDiscr, serverOptions.serverOptions...)

Reduces cognitive load and the risk of future divergence between HTTP and gRPC helpers.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
server := serverport.NewServer(serverPortDiscr)
for _, option := range serverOptions.serverOptions {
option(server)
}
server := serverport.NewServer(serverPortDiscr, serverOptions.serverOptions...)
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 91-93: httpserver/serverport.go#L91-L93
Added lines #L91 - L93 were not covered by tests

Comment on lines +74 to 77
func WithHttpServerOpts(opts ...func(server *http.Server)) ServerOptionModifier {
return func(server *ServerOptions) {
server.httpServerOpts = opts
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Functional‑option modifier overrides previous values instead of appending

WithHttpServerOpts replaces the slice each time it’s used, unlike the other modifiers that append.
Multiple call sites will silently lose options.

-return func(server *ServerOptions) {
-    server.httpServerOpts = opts
+return func(server *ServerOptions) {
+    server.httpServerOpts = append(server.httpServerOpts, opts...)
 }

Unit tests configuring several timeouts/handlers would currently apply only the last one.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 74-75: httpserver/serverport.go#L74-L75
Added lines #L74 - L75 were not covered by tests

@gfyrag gfyrag enabled auto-merge May 15, 2025 10:52
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