Skip to content

feat(decdn_node): expose operator-facing config knobs (#29) - #32

Merged
thiras merged 2 commits into
mainfrom
feat/decdn-node-operator-knobs
Jul 12, 2026
Merged

feat(decdn_node): expose operator-facing config knobs (#29)#32
thiras merged 2 commits into
mainfrom
feat/decdn-node-operator-knobs

Conversation

@thiras

@thirasthiras commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes#29. The decdn-node daemon reads ~60 config fields, but the decdn_node role only templated the subset upstream ships in its own operator config (examples/configs/arbitrum-sepolia.toml). A field with no role knob had to be hand-edited into /etc/decdn/node.toml — which the next make deploy re-renders and silently reverts. Issue #29 is the concrete case: cache.node_to_node_pull_through_enabled gates all serve-time origin pull-through but had no decdn_* variable.

This exposes ~27 operator-facing knobs and closes the same gap for the rest of that surface. Deep-internal tuning with strong upstream defaults (rate limiters, circuit breaker, retry policy, gossip, receipts, prefetch) stays out of scope.

Design

  • Unset sentinel. Every new knob defaults to "" (or []) meaning "omit the key, use the daemon's own default". node.toml stays byte-identical to today unless an operator opts in — no pinning of upstream defaults. An explicit 0/falseis emitted (gated on != "", not | int > 0), because 0 is meaningful (gc_interval_sec = 0 disables the sweep, max_unrecouped_leech_bytes = 0 = off).
  • Fail-loud validation at deploy time so a bad value never reaches the daemon (which would crash-loop under deny_unknown_fields): bool/integer shape, an i64::MAX cap (TOML ints are i64), per-field ranges, cross-field constraints compared against the daemon's default-filled values, and TOML-injection guards (quote/whitespace/newline) on the string/list knobs.
  • Rendering correctness.Bytes/Percent emit as bare integers (pull_ahead_bytes = 1048576, pull_share_ratio_percent = 400 = 4.0×); new [cache] scalars render before[cache.origin] so the sub-table header doesn't absorb them; relay_urls supersedes the singular relay_url when both are set.

Knobs added

Node-to-node pull-through (#29) · settlement thresholds + auto-close · delivery floor/ceiling + voucher interval · cache tuning (probe holds, GC, pins, user-agent) · blockchain watchers (RPC watchdog, event poll, blacklist poll) · network (relay_urls, enable_0rtt) · observability (otlp_endpoint, region accounting). See roles/decdn_node/defaults/main.yml.

Testing

  • New molecule/validation negative scenario: asserts each bad-value family (cross-field, range, shape, bool, list, string) is rejected by the role's own validation (matched on ansible_failed_task.name, so a value slipping past validation → role fails elsewhere → caught).
  • molecule/default extended: asserts the emit-0, bare-int Bytes/Percent, bool, and two-element-list rendering forms with exact value + type (isinstance guards).
  • All 4 molecule scenarios pass with idempotence; ansible-lint (production profile) + yamllint clean; make build (galaxy collection) OK.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added extensive optional tuning controls for delivery, payments, caching, networking, blockchain monitoring, and observability.
    • Added support for multiple relay URLs, QUIC 0-RTT configuration, node-to-node pull-through, pinned hashes, and OTLP export settings.
    • Explicit zero and false values are now preserved in generated configuration.
  • Bug Fixes

    • Invalid tuning values are rejected during deployment with clear validation failures.
  • Documentation

    • Documented available tuning options, defaults, validation behavior, and deprecated relay configuration.

The decdn-node daemon reads ~60 config fields, but the role only templated
the subset upstream ships in its own operator config. Fields with no role knob
had to be hand-edited into /etc/decdn/node.toml, which the next `make deploy`
silently reverts. Issue #29 is the concrete case: cache.node_to_node_pull_through_enabled
gates all serve-time origin pull-through but had no variable.
Expose ~27 operator-facing knobs (node-to-node pull-through, settlement
thresholds, delivery clamps, cache tuning, blockchain watchers, network,
observability) using the role's existing discipline: each defaults to an
unset sentinel ("" / []) meaning "omit the key, use the daemon default", so
node.toml stays byte-identical unless an operator opts in. An explicit 0/false
is emitted (0 is meaningful, e.g. gc_interval_sec = 0 disables the sweep).
Every knob is fail-loud validated at deploy time so a bad value never reaches
the daemon (which would crash-loop under deny_unknown_fields): bool/integer
shape, i64::MAX cap, per-field ranges, cross-field constraints compared against
the daemon's default-filled values, and TOML-injection guards on string/list
knobs. Bytes/Percent render as bare integers; new [cache] scalars render before
[cache.origin] so the sub-table header doesn't absorb them.
Add a negative-path molecule scenario (validation) that asserts each bad-value
family is rejected by the role's own validation, plus positive coverage in the
default scenario for the emit-0/bare-int/bool/two-element-list forms.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CopilotAI review requested due to automatic review settings July 12, 2026 17:41
@coderabbitai

coderabbitaiBot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@thiras, you've reached your PR review limit, so we couldn't start this review.

Next review available in:37 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8376a3d0-9c6a-4057-b47e-95f08bd03800

📥 Commits

Reviewing files that changed from the base of the PR and between 611c21c and 7cac785.

📒 Files selected for processing (2)
  • ansible/roles/decdn_node/tasks/main.yml
  • ansible/roles/decdn_node/templates/node.toml.j2
📝 Walkthrough

Walkthrough

The role adds optional tuning variables, validates their types and ranges, renders them into node.toml, documents their behavior, and adds Molecule coverage for valid emission and invalid-value rejection.

Changes

Tuning knob configuration and validation

Layer / File(s)Summary
Tuning knob defaults and documentation
ansible/roles/decdn_node/defaults/main.yml, ansible/roles/decdn_node/README.md
Adds optional relay, economics, watcher, cache, pull-through, and observability settings, with documentation for omitted, zero, false, and invalid values.
Optional knob validation
ansible/roles/decdn_node/tasks/main.yml
Validates boolean and numeric shapes, daemon-specific ranges, cross-field constraints, list formats, and TOML-safe strings before startup.
TOML configuration emission
ansible/roles/decdn_node/templates/node.toml.j2
Conditionally renders the new network, payment, cache, pull-through, and observability settings, including relay lists and explicit false/zero values.
Positive and negative scenario coverage
ansible/molecule/default/converge.yml, ansible/molecule/default/verify.yml, ansible/molecule/validation/*
Tests typed and zero-valued output and verifies rejection of invalid cross-field, range, shape, boolean, list, and string inputs.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested reviewers:copilot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly summarizes the main change: exposing operator-facing config knobs in the decdn_node role.
Docstring Coverage✅ PassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/decdn-node-operator-knobs

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.

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces optional operator-facing tuning knobs for the decdn_node Ansible role, exposing various daemon configuration fields (such as node-to-node pull-through, settlement, delivery-rate clamps, cache tuning, and blockchain watchers) along with robust validation tasks and a negative-path Molecule test scenario. The review feedback highlights a critical, systematic issue across the validation tasks and Jinja2 templates: if an operator explicitly unsets any of these optional variables by setting them to null (which resolves to None in Ansible), the current checks against empty strings ("") will fail. This leads to unexpected validation failures, template rendering crashes (e.g., calling | length on NoneType), or dangerous type coercions (such as coercing None to 0, which would clamp the delivery ceiling to zero and block paid traffic). The reviewer provides actionable recommendations to use robust null/None checks, such as 'in ["", none]' and 'is not none', to safely handle unset variables.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment threadansible/roles/decdn_node/tasks/main.yml Outdated
Comment threadansible/roles/decdn_node/templates/node.toml.j2 Outdated
Comment threadansible/roles/decdn_node/tasks/main.yml Outdated
Comment threadansible/roles/decdn_node/tasks/main.yml Outdated
Comment threadansible/roles/decdn_node/tasks/main.yml Outdated
Comment threadansible/roles/decdn_node/templates/node.toml.j2 Outdated
Comment threadansible/roles/decdn_node/templates/node.toml.j2 Outdated

CopilotAI left a comment

Copy link
Copy Markdown

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 expands the ansible/roles/decdn_node role to expose a larger set of operator-facingdecdn_* configuration knobs (notably including cache.node_to_node_pull_through_enabled from #29), while keeping upstream defaults unpinned via an “unset sentinel” ("" / []) and adding deploy-time validation to prevent invalid TOML from crash-looping the daemon.

Changes:

  • Add ~27 new optional decdn_* variables (defaulting to "" / []) and emit them into node.toml only when set.
  • Add fail-loud Ansible validation for optional bool/int/list/string knobs (including cross-field constraints) to block invalid configs before host mutation.
  • Extend Molecule coverage with a new negative-path validation scenario and additional assertions in the default scenario.

Reviewed changes

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

Show a summary per file
FileDescription
ansible/roles/decdn_node/templates/node.toml.j2Emit new optional operator knobs into node.toml, including relay_urls, pull-through, cache tuning, and observability fields.
ansible/roles/decdn_node/tasks/main.ymlAdd deploy-time assertions to validate optional knob shapes/ranges/cross-field constraints before rendering/starting services.
ansible/roles/decdn_node/README.mdDocument the new optional tuning knobs and their intended semantics.
ansible/roles/decdn_node/defaults/main.ymlIntroduce the new decdn_* defaults using the unset-sentinel pattern ("" / []).
ansible/molecule/validation/molecule.ymlAdd a new Molecule scenario dedicated to negative-path validation behavior.
ansible/molecule/validation/converge.ymlImplement negative test cases that must fail specifically at the role’s validation asserts.
ansible/molecule/default/converge.ymlSet representative tuning knobs to exercise emission/validation paths in the default scenario.
ansible/molecule/default/verify.ymlAssert rendered TOML contains the expected tuning knobs with correct types (e.g., explicit 0, ints vs bools).

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

Comment threadansible/roles/decdn_node/tasks/main.yml Outdated
Comment threadansible/roles/decdn_node/tasks/main.yml Outdated
…trings
Address code-review feedback on the tuning-knob validation:
- null/None now behaves like the "" / [] unset sentinel everywhere (Gemini).
An operator writing `decdn_x:` (null) previously fail-loud'd on the shape
assert or crash'd `| length` on None; now it omits the key and uses the daemon
default, matching Ansible idiom. Scalars use `not in ["", none]` (NOT `| length`,
which errors on an integer value); lists use `is not none and | length`; the
integer-shape loop is a list expression so null keeps its type instead of
becoming the string "None".
- Reject backslashes in the interpolated string/URL knobs (Copilot). A backslash
in a TOML basic string starts an escape and a trailing `\` escapes the closing
quote (a daemon crash-loop); relay_urls/relay_url/user_agent/otlp_endpoint now
disallow it. Also validate the previously-unchecked singular decdn_relay_url.
Verified: null overrides render as omitted (no crash, default parity holds);
backslash/quote/whitespace values are rejected at deploy time; all prior
positive/negative cases still hold; ansible-lint + yamllint clean; all four
molecule scenarios pass (validation rescued=6).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@thiras
thiras merged commit c27ab49 into mainJul 12, 2026
9 checks passed
@thiras
thiras deleted the feat/decdn-node-operator-knobs branch July 12, 2026 18:22
Sign up for freeto 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.

decdn_node role: expose node_to_node_pull_through_enabled as a knob

2 participants

@thiras