Skip to content

feat(BA-8635): choose how the AppProxy worker receives ingresses - #15890

Merged
HyeockJinKim merged 11 commits into
mainfrom
feat/BA-8443-worker-ingress-mode
Oct 20, 2026
Merged

HyeockJinKim merged 11 commits into
mainfrom
feat/BA-8443-worker-ingress-mode

Conversation

@jopemachine

@jopemachine jopemachine commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

📚 Stacked PRs

Part of the AppProxy worker Ingress stack (epic BA-8433). Merge in order (bottom-up):

  1. 👉 feat(BA-8635): choose how the AppProxy worker receives ingresses #15890 — feat(BA-8635): choose how the AppProxy worker receives ingresses ← you are here
  2. feat(BA-8443): push ingresses from the coordinator to api-delivery workers #15833 — feat(BA-8443): push ingresses from the coordinator to api-delivery workers

Resolves #15891 (BA-8635)

Summary

  • New worker config [proxy-worker.ingress] delivery_mode (IngressDeliveryMode) chooses how ingresses are delivered to the worker, as BA-8178 settles: each worker picks its method in its server config and reports it to the coordinator when it starts.
    • api: the coordinator sends ingresses to the worker on its API port.
    • redis (default): the worker reads what the manager writes to Redis. The default layers becomes ["in-memory", "redis"] to match.
    • api requires the in-memory layer and redis the redis layer.
    • Circuit events are written into the in-memory state with either delivery, so the existing circuit path keeps working (BA-8437).
  • The worker adds authority and ingress-delivery-mode labels to its existing service discovery entry, which the coordinator reads in feat(BA-8443): push ingresses from the coordinator to api-delivery workers #15833.
  • /v2/ingress stays on the existing API port and is now wired to the ingress state. The handler takes IngressStateCtx and IngressConfigCtx, MiddlewareParams that read the ingress state and the ingress config per request, as the storage proxy's StorageRootCtx does. It writes only with the api delivery and answers 501 otherwise. upsert and replace return IngressRevisionsResponse; remove stays 204.

Assumptions

  • The manager writes every Ingress to Redis whatever the delivery mode (BA-7123). An api-delivery worker with the redis layer then falls back to a complete set: get_all reads the last layer, and a key removed by a push stays removed in Redis.

Constraints from sharing the in-memory state with circuits

  • A frontend pushed with revision 1 or later fails a later circuit event for the same frontend with 409, since circuit events carry revision 0. Frontends the manager pushes must not overlap the coordinator's circuits.
  • /v2/ingress/replace replaces the whole state, including the ingresses from circuits. The coordinator in feat(BA-8443): push ingresses from the coordinator to api-delivery workers #15833 calls only upsert and remove.

Test plan

  • pants check / pants test on tests/unit/appproxy:: and src/ai/backend/appproxy::
  • tests/unit/appproxy/worker/api/test_ingress.py — writes with the api delivery, 501 otherwise
  • tests/unit/appproxy/worker/test_config.py — a delivery mode without the layer it needs is rejected

🤖 Generated with Claude Code

jopemachine and others added 2 commits October 20, 2026 11:07
[proxy-worker.ingress] mode picks circuit (default, the existing circuit
event path), api (the coordinator sends ingresses to the worker) or
redis. The worker announces its authority and mode as service discovery
labels. /v2/ingress on the API port is wired to the ingress state and
writes only in the api mode; upsert and replace return the revisions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…essState

IngressState holds the single in-memory writer and the configured mode.
The /v2/ingress handler writes only in the api mode and the circuit event
path only in the circuit mode, instead of splitting the same writer into
api_writer and circuit_writer fields.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jopemachine jopemachine changed the title feat(BA-8443): choose how the AppProxy worker receives ingresses feat(BA-8635): choose how the AppProxy worker receives ingresses Oct 20, 2026
jopemachine and others added 8 commits October 20, 2026 11:17
The ingress mode is api or redis, as BA-8178 settles, and defaults to
redis with the in-memory and redis layers. Circuit events are written
into the ingress state in either mode, so the existing circuit path
keeps working while pushes or Redis are added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…f the mode

The mode is configuration, not runtime state, so IngressState keeps the
IngressConfig it was built from and the /v2/ingress handler reads the
mode from it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The setting chooses how ingresses are delivered to the worker, so the
enum becomes IngressDeliveryMode, the config key delivery and the
service discovery label ingress-delivery.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rom the state

IngressState goes back to the reader and writer it holds on main. The
/v2/ingress handler takes the ingress config through IngressConfigCtx,
next to IngressStateCtx, and reads the delivery from it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jopemachine
jopemachine marked this pull request as ready for review October 20, 2026 02:54
@jopemachine
jopemachine requested a review from a team as a code owner October 20, 2026 02:54
Copilot AI balanced review requested due to automatic review settings October 20, 2026 02:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Generated local configuration fails validation, and revision reporting can differ from the worker’s effective state.

2 open issues
What changed in this PR

Adds configurable ingress delivery for AppProxy workers, preparing them for coordinator pushes in #15833.

Changes:

  • Adds API/Redis delivery modes and required-layer validation.
  • Publishes delivery mode and authority through service discovery.
  • Connects ingress endpoints to worker state and returns applied revisions.
File Description
tests/​unit/​appproxy/​worker/​test_config.py Tests delivery modes and layer validation.
tests/​unit/​appproxy/​worker/​ingress/​test_factory.py Updates factory tests with delivery modes.
tests/​unit/​appproxy/​worker/​api/​test_ingress.py Tests revision responses and write restrictions.
src/​ai/​backend/​appproxy/​worker/​server.py Adds worker discovery labels.
src/​ai/​backend/​appproxy/​worker/​dto/​context.py Provides request-scoped state and configuration.
src/​ai/​backend/​appproxy/​worker/​config.py Defines delivery settings and validation.
src/​ai/​backend/​appproxy/​worker/​api/​ingress.py Enables state-backed ingress operations.
src/​ai/​backend/​appproxy/​common/​types.py Adds the delivery-mode enum.
src/​ai/​backend/​appproxy/​common/​defs.py Defines discovery label constants.
configs/​app-proxy-worker/​sample.toml Documents the delivery setting.
changes/​15890.feature.md Records the feature.

Review effort: Balanced

async def revisions(self) -> APIResponse:
ingresses = await self._require_state().reader.get_all()
async def revisions(self, state_ctx: IngressStateCtx) -> APIResponse:
ingresses = await state_ctx.ingress_state.reader.get_all()
"manager writes to Redis. Circuit events are written in either delivery mode."
),
added_version=NEXT_RELEASE_VERSION,
example=ConfigExample(local="redis", prod="api"),
@HyeockJinKim
HyeockJinKim merged commit af9afe4 into main Oct 20, 2026
37 checks passed
@HyeockJinKim
HyeockJinKim deleted the feat/BA-8443-worker-ingress-mode branch October 20, 2026 03:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:app-proxy Related to App Proxy component size:L 100~500 LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Choose how Ingress is delivered to the AppProxy worker and accept pushes with the api delivery mode

3 participants