Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions horizon/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
from opal_common.schemas.data import CallbackEntry
from pydantic import parse_obj_as, parse_raw_as

# One-way import edge, config -> debounce: the default lives beside the clamp that falls back
# to it, so a value this module declares and a value the debouncer substitutes can never drift.
# horizon.debounce must never import this module back (it takes its window as a parameter).
from horizon.debounce import DEFAULT_DEBOUNCE_SECONDS

MOCK_API_KEY = "MUST BE DEFINED"


Expand Down Expand Up @@ -288,6 +293,28 @@ def parse_plugins(value: Any) -> dict[str, dict[str, int | bool | str]]:
),
)

TRIGGER_DEBOUNCE_SECONDS = confi.float(
"TRIGGER_DEBOUNCE_SECONDS",
DEFAULT_DEBOUNCE_SECONDS,
description=(
"Debounce window, in seconds, for forced full reloads triggered via the API trigger routes "
"(/policy-updater/trigger, /data-updater/trigger and their legacy /update_policy* aliases). "
"A trigger arriving within this many seconds of the last one - or while a forced reload is "
"already in flight - is coalesced instead of amplifying load onto the control plane, so data "
"served by this PDP may lag a forced trigger by up to this many seconds. A coalesced trigger "
"is never dropped: the PDP arms a background trailing reload that runs once the window "
"expires, so staleness is bounded by this value rather than by whenever a client happens to "
"trigger again. Under a sustained hammer that converges to one reload per window. Set to 0 to "
"disable the time window; concurrent triggers are still collapsed into a single in-flight "
"reload. Clamped to at most 300s. Values that cannot be interpreted as a non-negative number "
"(null, a typo, a non-finite) FAIL SAFE to the default rather than disabling the mitigation - "
"only an explicit, parseable 0 disables it. The effective value is logged at startup whenever "
"it differs from what was configured. Remote-config overridable fleet-wide, so ops can raise "
"it (e.g. to 30-60s under a degraded control plane) without shipping a release - but the "
"remote config is fetched once during startup, so a change needs a PDP restart to take effect."
),
)

@staticmethod
def parse_callbacks(value: Any) -> list[CallbackEntry]:
if isinstance(value, str):
Expand Down
415 changes: 415 additions & 0 deletions horizon/debounce.py

Large diffs are not rendered by default.

331 changes: 282 additions & 49 deletions horizon/pdp.py

Large diffs are not rendered by default.

Loading
Loading