Skip to content

fix: wire keepalive configuration fields into gRPC server options#399

Open
raballew wants to merge 2 commits intojumpstarter-dev:mainfrom
raballew:030-wire-keepalive-grpc
Open

fix: wire keepalive configuration fields into gRPC server options#399
raballew wants to merge 2 commits intojumpstarter-dev:mainfrom
raballew:030-wire-keepalive-grpc

Conversation

@raballew
Copy link
Copy Markdown
Contributor

Summary

  • The five keepalive config fields (Timeout, IntervalTime, MaxConnectionIdle, MaxConnectionAge, MaxConnectionAgeGrace) were parsed from configuration but never wired into keepalive.ServerParameters, making them silently ignored
  • LoadGrpcConfiguration now returns []grpc.ServerOption and constructs a ServerParameters option when any keepalive field is non-zero
  • Propagates the slice type change through all callers (controller service, router service, cmd entrypoints)

Test plan

  • 8 new tests covering: timeout/interval wiring, connection lifetime fields, invalid value errors for all 5 fields, empty fields produce zero-value params, backward compatibility
  • All existing config tests pass with no regressions
  • Full go build ./... clean

Closes #363

🤖 Generated with Claude Code

The five keepalive config fields (Timeout, IntervalTime,
MaxConnectionIdle, MaxConnectionAge, MaxConnectionAgeGrace) were parsed
from configuration but never passed to keepalive.ServerParameters,
making them silently ignored.

Changes LoadGrpcConfiguration to return []grpc.ServerOption and
constructs a ServerParameters option when any keepalive field is
non-zero. Propagates the slice type change through all callers.

Closes jumpstarter-dev#363

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@netlify
Copy link
Copy Markdown

netlify bot commented Mar 31, 2026

Deploy Preview for jumpstarter-docs ready!

Name Link
🔨 Latest commit 8404dfc
🔍 Latest deploy log https://app.netlify.com/projects/jumpstarter-docs/deploys/69cd135ac6c14000083a397e
😎 Deploy Preview https://deploy-preview-399--jumpstarter-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4e73182f-9b9a-44d3-be9c-8fc30c3abd29

📥 Commits

Reviewing files that changed from the base of the PR and between 833a9c4 and 8404dfc.

📒 Files selected for processing (3)
  • controller/cmd/main.go
  • controller/internal/service/controller_service.go
  • controller/internal/service/router_service.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • controller/cmd/main.go
  • controller/internal/service/router_service.go
  • controller/internal/service/controller_service.go

📝 Walkthrough

Walkthrough

The code refactors gRPC server configuration handling to support multiple grpc.ServerOption values instead of single options. Configuration loaders now return slices of server options, services store ServerOptions []grpc.ServerOption, and startup paths assemble and pass combined option slices to grpc.NewServer().

Changes

Cohort / File(s) Summary
Config Loading
controller/internal/config/config.go, controller/internal/config/grpc.go
Changed loaders to return []grpc.ServerOption. LoadGrpcConfiguration now parses additional keepalive duration fields (Timeout, IntervalTime, MaxConnectionIdle, MaxConnectionAge, MaxConnectionAgeGrace), builds keepalive.ServerParameters when present, accumulates multiple grpc.ServerOption entries, and returns detailed parse errors for invalid durations.
Services
controller/internal/service/controller_service.go, controller/internal/service/router_service.go
Replaced ServerOption grpc.ServerOption with ServerOptions []grpc.ServerOption. Start() now appends interceptors/credentials to s.ServerOptions and calls grpc.NewServer(opts...) with the combined slice.
Command Entrypoints
controller/cmd/main.go, controller/cmd/router/main.go
Updated struct literals to set ServerOptions: option (slice) instead of the previous singular ServerOption: option.
Tests
controller/internal/config/grpc_test.go
Added unit tests covering various Keepalive inputs: option counts, defaulting behavior, and error messages for invalid duration fields.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as Main (cmd)
    participant Config as Config Loader
    participant Service as Router/Controller Service
    participant gRPC as gRPC Server

    CLI->>Config: LoadConfiguration / LoadGrpcConfiguration
    Config-->>CLI: []grpc.ServerOption (enforcement, params...)
    CLI->>Service: construct service with ServerOptions slice
    Service->>Service: append interceptors/credentials to options
    Service->>gRPC: grpc.NewServer(opts...)
    gRPC-->>Service: server running
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • NickCao

Poem

🐰 whiskers twitch with glee,
options gathered, snug as can be.
Keepalive threads now linked in line,
servers hum and configs shine,
hop, deploy — all set to be! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main objective: wiring keepalive configuration fields into gRPC server options.
Description check ✅ Passed The description is detailed and directly related to the changeset, explaining the problem, solution, and test coverage.
Linked Issues check ✅ Passed The changes fully implement the requirements from issue #363 by wiring the five keepalive fields into keepalive.ServerParameters and passing as gRPC server options.
Out of Scope Changes check ✅ Passed All changes are directly related to wiring keepalive configuration; no unrelated modifications are present in the changeset.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


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

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

Copy link
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (1)
controller/internal/service/controller_service.go (1)

941-959: Ordering difference from router_service.go.

In this file, user-configured options (s.ServerOptions) are placed first via append(s.ServerOptions, interceptors...), whereas router_service.go places defaults first and appends user options. While this likely doesn't cause functional issues (gRPC options are typically additive rather than overriding), consider aligning the ordering across both services for consistency and easier maintenance.

♻️ Optional: Align ordering with router_service.go
-	opts := append(s.ServerOptions,
+	opts := []grpc.ServerOption{
 		grpc.ChainUnaryInterceptor(func(
 			gctx context.Context,
 			req any,
 			_ *grpc.UnaryServerInfo,
 			handler grpc.UnaryHandler,
 		) (resp any, err error) {
 			return handler(logContext(gctx), req)
 		}, recovery.UnaryServerInterceptor()),
 		grpc.ChainStreamInterceptor(func(
 			srv any,
 			ss grpc.ServerStream,
 			_ *grpc.StreamServerInfo,
 			handler grpc.StreamHandler,
 		) error {
 			return handler(srv, &wrappedStream{ServerStream: ss})
 		}, recovery.StreamServerInterceptor()),
-	)
+	}
+	opts = append(opts, s.ServerOptions...)
 	server := grpc.NewServer(opts...)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@controller/internal/service/controller_service.go` around lines 941 - 959,
The append ordering of server options is inconsistent with router_service.go:
currently opts := append(s.ServerOptions, grpc.ChainUnaryInterceptor(...),
grpc.ChainStreamInterceptor(...)) places user options first; change it to
construct opts by starting with the default interceptors (the
grpc.ChainUnaryInterceptor and grpc.ChainStreamInterceptor entries) and then
append s.ServerOptions so defaults come first, ensuring the same ordering used
when creating the server via grpc.NewServer; update the block that builds opts
(references: s.ServerOptions, grpc.ChainUnaryInterceptor,
grpc.ChainStreamInterceptor, grpc.NewServer) accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@controller/internal/service/controller_service.go`:
- Around line 941-959: The append ordering of server options is inconsistent
with router_service.go: currently opts := append(s.ServerOptions,
grpc.ChainUnaryInterceptor(...), grpc.ChainStreamInterceptor(...)) places user
options first; change it to construct opts by starting with the default
interceptors (the grpc.ChainUnaryInterceptor and grpc.ChainStreamInterceptor
entries) and then append s.ServerOptions so defaults come first, ensuring the
same ordering used when creating the server via grpc.NewServer; update the block
that builds opts (references: s.ServerOptions, grpc.ChainUnaryInterceptor,
grpc.ChainStreamInterceptor, grpc.NewServer) accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 593c602c-894a-4978-88e9-b03ec3d765ad

📥 Commits

Reviewing files that changed from the base of the PR and between 03fc412 and 833a9c4.

📒 Files selected for processing (7)
  • controller/cmd/main.go
  • controller/cmd/router/main.go
  • controller/internal/config/config.go
  • controller/internal/config/grpc.go
  • controller/internal/config/grpc_test.go
  • controller/internal/service/controller_service.go
  • controller/internal/service/router_service.go

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

Keepalive configuration fields parsed but never wired

1 participant