Skip to content

docs: correct interceptor execution order in CLAUDE.md - #575

Draft
atilafassina wants to merge 1 commit into
mainfrom
fix/interceptor-order-discrepancy
Draft

docs: correct interceptor execution order in CLAUDE.md#575
atilafassina wants to merge 1 commit into
mainfrom
fix/interceptor-order-discrepancy

Conversation

@atilafassina

Copy link
Copy Markdown
Contributor

What

Corrects the Execution Interceptor Pattern section of the root CLAUDE.md, which documented the interceptor nesting in the exact reverse of the runtime behavior, plus several wrong keys in the config example.

Why

The doc claimed the order was Telemetry (outermost) → Timeout → Retry → Cache (innermost). The actual runtime nesting is the reverse:

  • _buildInterceptors (packages/appkit/src/plugin/plugin.ts) pushes the array as [telemetry, timeout, retry, cache].
  • _executeWithInterceptors folds that array so each later entry becomes the inner wrapper.
  • Net effect, outermost → innermost: Cache → Retry → Timeout → Telemetry → fn().

The in-code comment at plugin.ts:700 (telemetry → timeout → retry → cache (innermost to outermost)) was already correct — only CLAUDE.md was stale.

Changes

  • Flip the interceptor order list to match runtime (Cache outermost → Telemetry innermost), with a one-line note on how the array fold produces it.
  • Add the layered-observability nuance: the innermost plugin.execute span doesn't wrap cache hits/retries/timeouts, but the cache layer emits its own cache.getOrExecute span + hit/miss metrics, and connectors carry their own spans; timeout/retry only log.
  • Fix the config example:
    • Wrap config in { default: ... } (PluginExecutionSettings) — the real execute() signature.
    • retry: { maxRetries: 3 }retry: { enabled: true, attempts: 3 } (RetryConfig.attempts).
    • cache.ttl is in seconds, and cache needs enabled + cacheKey to activate.
    • telemetry: { traces: true }telemetryInterceptor: { enabled: true } (the per-call key; traces is plugin-level config).

Docs-only change — no code touched.

Note / follow-up

There's a separate, deliberate design question left for a follow-up: whether the code should make TelemetryInterceptor outermost (so the span covers retries/timeout/cache-hit). Not done here — it changes the interceptor composition and trades away the pure-work-latency signal, so it wants its own PR + owner sign-off. Recommended alternative if pursued: an outer operation span plus the existing inner per-attempt span.

This pull request and its description were written by Isaac.

The documented interceptor order was the reverse of the runtime nesting.
_buildInterceptors pushes [telemetry, timeout, retry, cache] and
_executeWithInterceptors folds the array so each later entry becomes the
inner wrapper, netting outermost-to-innermost: Cache -> Retry -> Timeout
-> Telemetry -> fn().

Also fix the config example: it must be wrapped in { default: ... }
(PluginExecutionSettings), retry uses 'attempts' not 'maxRetries', cache
'ttl' is in seconds, cache/retry need 'enabled' to activate, and the
per-call telemetry key is 'telemetryInterceptor' (not 'telemetry: { traces }').
Add the layered-observability nuance (cache layer + connectors carry their
own spans; timeout/retry only log).

Co-authored-by: Isaac <no-reply@databricks.com>
Signed-off-by: Atila Fassina <atila@fassina.eu>
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

🤖 AppKit PR bot

🔬 Run evals

Start an eval for this PR from the evals-monitor app: Go to Evals Monitor →

📦 Try this PR's app template

Scaffolds a new app from this PR's SDK build. Run it in any folder (requires the GitHub CLI — gh auth login — and the Databricks CLI):

gh run download 33861774533 -R databricks/appkit -n appkit-template-0.71.0-pr.f444d6a-fix-interceptor-order-discrepancy-575 -D appkit-pr-575 \
  && unzip -o "appkit-pr-575/appkit-template-0.71.0-pr.f444d6a-fix-interceptor-order-discrepancy-575.zip" -d "appkit-pr-575" \
  && databricks apps init --template "appkit-pr-575"

The template pins @databricks/appkit and @databricks/appkit-ui to tarballs built from this branch, so the scaffolded app runs against this PR's code.

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