Skip to content

fix: use executor when WithExecutor is set without SetDefaultExecutor#53

Merged
ankurs merged 3 commits intomainfrom
fix/executor-without-default
Apr 24, 2026
Merged

fix: use executor when WithExecutor is set without SetDefaultExecutor#53
ankurs merged 3 commits intomainfrom
fix/executor-without-default

Conversation

@ankurs
Copy link
Copy Markdown
Member

@ankurs ankurs commented Apr 23, 2026

Summary

  • DefaultClientInterceptors now always uses ExecutorClientInterceptor instead of choosing between it and HystrixClientInterceptor at construction time
  • When no executor is configured (neither global nor per-call), falls back to Hystrix for backward compatibility via hystrixFallback
  • When WithExecutor is passed per-call or per-connection, the executor is used directly — no longer requires SetDefaultExecutor to activate the executor code path

Test plan

  • Existing tests pass (make test with -race)
  • New test: per-call WithExecutor without global executor
  • New test: per-connection WithExecutor without global executor
  • New test: WithoutHystrix passthrough without global executor
  • New test: WithoutExecutor passthrough without global executor
  • make lint clean (0 issues)
  • README.md regenerated via make doc

Summary by CodeRabbit

Release Notes

  • Documentation

    • Updated documentation clarifying executor selection precedence and fallback behavior with Hystrix integration.
  • Improvements

    • Enhanced executor selection logic: per-call configuration takes precedence with consistent Hystrix fallback when no executor is configured.
    • Added explicit opt-out options for executor and Hystrix fallback functionality.

ExecutorClientInterceptor is now always in the default client chain.
When no executor is configured (neither global nor per-call), it falls
back to Hystrix for backward compatibility. When WithExecutor is passed
per-call or per-connection, the executor is used directly — no longer
requires a global SetDefaultExecutor to activate the executor code path.
Copilot AI review requested due to automatic review settings April 23, 2026 17:01
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 23, 2026

📝 Walkthrough

Walkthrough

The changes refactor client interceptor wiring to ensure ExecutorClientInterceptor is always installed in the default chain, with Hystrix serving as a fallback when no executor is configured. Per-call executor options take precedence over global defaults, and explicit opt-outs bypass Hystrix entirely. Documentation is updated to reflect this new behavior.

Changes

Cohort / File(s) Summary
Documentation Updates
README.md, config.go
Updated docs to clarify executor selection precedence (per-call WithExecutor > global SetDefaultExecutor > Hystrix fallback) and behavior when opt-outs are used. Function anchor links adjusted for upstream source line shifts.
Interceptor Refactoring
client.go
DefaultClientInterceptors now always installs ExecutorClientInterceptor. New centralized hystrixFallback function handles Hystrix execution logic (naming, panic recovery, error filtering). ExecutorClientInterceptor uses this fallback when no executor is configured; explicit opt-outs bypass Hystrix entirely.
Test Coverage
interceptors_test.go
Renamed test to reflect hystrix fallback behavior. Added test cases for per-call WithExecutor precedence and WithoutExecutor/WithoutHystrix passthrough assertions when no global executor exists.

Sequence Diagram

sequenceDiagram
    participant Client
    participant ExecutorClientInterceptor
    participant HystrixFallback
    participant Invoker
    
    Client->>ExecutorClientInterceptor: RPC Call with options
    
    alt Per-call executor via WithExecutor
        ExecutorClientInterceptor->>Invoker: Use per-call executor
    else Global executor via SetDefaultExecutor
        ExecutorClientInterceptor->>Invoker: Use global executor
    else Explicit opt-out (WithoutExecutor/WithoutHystrix)
        ExecutorClientInterceptor->>Invoker: Direct passthrough
    else No executor configured
        ExecutorClientInterceptor->>HystrixFallback: Hystrix fallback
        HystrixFallback->>Invoker: Execute via Hystrix circuit
        Invoker-->>HystrixFallback: Result/Error
        alt Hystrix error handling
            HystrixFallback->>HystrixFallback: Filter errors, recover panics
        end
        HystrixFallback-->>ExecutorClientInterceptor: Return result
    end
    
    Invoker-->>Client: Response
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly Related PRs

Poem

🐰 The executor hops with purpose bright,
Per-call takes lead—a gleaming sight!
When none exist, dear Hystrix stands,
A faithful guardian with helping hands. ✨
Opt-out says "nay," straight paths run true,
Refactored flows—what splendid glue!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly summarizes the main fix: enabling WithExecutor to work without requiring SetDefaultExecutor, which is the primary change across the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/executor-without-default

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

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes client-side interceptor selection so WithExecutor activates the executor path even when no global executor has been configured, while preserving backward compatibility by falling back to Hystrix when no executor is available.

Changes:

  • DefaultClientInterceptors now always includes ExecutorClientInterceptor, which internally falls back to Hystrix when no executor is configured.
  • Added hystrixFallback to preserve legacy Hystrix behavior when neither global nor per-call executors are set.
  • Expanded tests to cover per-call/per-connection WithExecutor without a global executor and passthrough behavior for WithoutHystrix / WithoutExecutor.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
client.go Always uses ExecutorClientInterceptor and adds Hystrix fallback behavior when no executor is configured.
config.go Updates SetDefaultExecutor docs to reflect new default-chain behavior.
interceptors_test.go Adds/updates tests for executor selection and fallback semantics.
README.md Regenerates docs to reflect updated comments/line references.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread config.go Outdated
Comment thread client.go
- SetDefaultExecutor doc now notes the useCBClientInterceptors gate
- HystrixClientInterceptor delegates to hystrixFallback to avoid drift
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread client.go Outdated
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)
client.go (1)

174-216: Good deduplication — one observation on a now-unreachable branch.

Extracting hystrixFallback and routing both ExecutorClientInterceptor's fallback and HystrixClientInterceptor through it is a clean consolidation.

Minor observation: the o.disableHystrix short-circuit at Line 180-181 is effectively only reachable from HystrixClientInterceptor now, because WithoutHystrix() also sets hasExecutor=true (see interceptors.go Line 52-62), which makes ExecutorClientInterceptor return the passthrough at Line 139 before ever calling hystrixFallback. That's fine as defensive coding for the direct-HystrixClientInterceptor caller path, just worth keeping in mind if HystrixClientInterceptor is eventually removed in v1 — the check can go with it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client.go` around lines 174 - 216, The o.disableHystrix early-return in
hystrixFallback is effectively unreachable when ExecutorClientInterceptor is
used (because WithoutHystrix sets hasExecutor=true), so remove the
disableHystrix short-circuit from hystrixFallback and rely on callers
(ExecutorClientInterceptor / HystrixClientInterceptor) to decide whether to call
hystrixFallback; update/remove any tests that expect hystrixFallback to honor
o.disableHystrix and ensure WithoutHystrix and hasExecutor logic remain the
single source determining passthrough behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@client.go`:
- Around line 174-216: The o.disableHystrix early-return in hystrixFallback is
effectively unreachable when ExecutorClientInterceptor is used (because
WithoutHystrix sets hasExecutor=true), so remove the disableHystrix
short-circuit from hystrixFallback and rely on callers
(ExecutorClientInterceptor / HystrixClientInterceptor) to decide whether to call
hystrixFallback; update/remove any tests that expect hystrixFallback to honor
o.disableHystrix and ensure WithoutHystrix and hasExecutor logic remain the
single source determining passthrough behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c81f14f4-a54e-4b94-abdd-76d7e012e4a7

📥 Commits

Reviewing files that changed from the base of the PR and between 0f4a43a and f61330c.

📒 Files selected for processing (4)
  • README.md
  • client.go
  • config.go
  • interceptors_test.go

@ankurs ankurs merged commit 831689d into main Apr 24, 2026
7 checks passed
@ankurs ankurs deleted the fix/executor-without-default branch April 24, 2026 04:17
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