fix: cache sampler constraints per process

Replace the endpoint's timed response cache with a process-local cached serialized constraints document. This makes the published sampler constraints a pure function of the running code, avoids stale cross-deploy cache entries, updates the developer docs to match, and adds an integration test to ensure repeated requests return the same document.
This commit is contained in:
tazlin committed 2026-08-19 14:02:10 -04:00
1 parent f317017ee8
commit d1e9067158
4 files changed
+39 -6

No files matched your search

+3
View File
@@ -167,6 +167,9 @@ Rules that follow from those being separate:
- **Version pins.** A new SDK symbol means bumping the `horde_sdk` bound in `pyproject.toml` and
`requirements.txt`, and regenerating `uv.lock`. reGen pins the SDK separately, so a worker-visible
addition needs both bumps before the capability gate can open.
- **Publishing the change.** The sampler constraints endpoint compiles its document once per process
and holds it, with no response cache in front, so a deployed change serves as soon as the process
restarts. Nothing needs invalidating and no cache flush belongs in the deploy.
- **Tests.** `tests/unit/test_consts.py` pins the vocabularies, `tests/unit/test_sampler_constraints.py`
compares the published document with the registry, `tests/unit/test_kudos_pricing.py` pins prices for
pre-existing requests, and `tests/unit/test_bridge_reference.py` pins capability gating. The Locust
+5 -5
View File
@@ -55,7 +55,7 @@ from horde.metrics import (
)
from horde.model_reference import model_reference
from horde.patreon import patrons
from horde.sampler_constraints import compile_sampler_constraints
from horde.sampler_constraints import published_sampler_constraints
from horde.telemetry import (
get_traceparent,
pyroscope_tag,
@@ -1520,7 +1520,6 @@ class ImageSamplerConstraints(Resource):
decorators = [limiter.exempt]
@logger.catch(reraise=True)
@cache.cached(timeout=3600)
@api.expect(get_parser)
@api.response(200, "Constraints Published", models.response_model_sampler_constraints)
def get(self):
@@ -1532,6 +1531,7 @@ class ImageSamplerConstraints(Resource):
Recommendations are advisory and each carries the provenance of the claim, because they range
from statements by the image backend's own author to third-party folklore.
"""
# The document is typed all the way up, and is rendered to plain JSON types only here, at the
# boundary, so nothing downstream of the compiler works in anonymous dicts.
return compile_sampler_constraints().model_dump(mode="json"), 200
# The document is a pure function of the installed code, so it is compiled once per process and
# held rather than cached between them: a response cache could only ever return what this
# process already has, and would outlive the build that filled it.
return published_sampler_constraints(), 200
+22 -1
View File
@@ -13,11 +13,15 @@ The document's type also lives in horde_sdk, as
:class:`~horde_sdk.generation_parameters.image.constraints_document.SamplerConstraintsDocument`, so a
python client parses the response back into the same models this module builds it from.
The public entry point is :func:`compile_sampler_constraints`.
The endpoint serves :func:`published_sampler_constraints`, which renders what
:func:`compile_sampler_constraints` builds.
"""
from __future__ import annotations
import functools
from typing import Any
from horde_model_reference.meta_consts import KNOWN_IMAGE_GENERATION_BASELINE
from horde_sdk.generation_parameters.image.constraints import (
CFG_PP_SAMPLERS,
@@ -264,3 +268,20 @@ def compile_sampler_constraints() -> SamplerConstraintsDocument:
recommended=sorted(sampler for sampler in RECOMMENDED_SAMPLERS if str(sampler) in KNOWN_SAMPLERS),
),
)
@functools.cache
def published_sampler_constraints() -> dict[str, Any]:
"""Return the document the endpoint publishes, compiled and serialised once per process.
The document is a pure function of the installed code: no request input, no database read, nothing a
running process can change. Holding it removes any window in which a process could publish a document
other than the one its own code produces, and it is cheaper than fetching one from a shared cache.
The returned mapping is shared by every caller and must not be mutated.
Returns:
The document rendered to plain JSON types.
"""
return compile_sampler_constraints().model_dump(mode="json")
@@ -147,3 +147,12 @@ def test_both_measured_cost_ratios_are_served_with_their_basis(client):
},
],
}
def test_repeated_requests_serve_an_unchanged_document(client):
# The document is compiled once per process and handed to every caller, so anything that mutated it
# on the way out would corrupt it for every later request rather than just its own.
first = client.get(CONSTRAINTS_URL).get_json()
second = client.get(CONSTRAINTS_URL).get_json()
assert first == second