Azure / Azure/azure-functions-host
[Compute Separation][HT10-M1+HT13B-M1] Publish first-worker readiness and revisioned capacity
- Dominant language
- C#
- Stars
- 2k
- Forks
- 482
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 36
Description
## Roadmap mapping
| Field | Value |
|---|---|
| Roadmap IDs | `HT10-M1` + `HT13B-M1` |
| Lane | Host |
| BYOC milestone | M1 |
| Parent | #11965 |
| Depends on | `HT9`, `HP3+HP5A-M1`, `HT13` / #11971 |
| Blocks | [internal BYOC #219](https://github.com/serverless-paas-balam/FlexConsumption-BYOC/issues/219) stamp routing |
| Pull request | One PR |
The readiness transition and its capacity snapshot are one externally observable M1 state change; neither has an independent M1 consumer.
## Why this PR exists
After HT9, a worker can link and ScriptHost can start, but appserver cannot route Frontend traffic until Host publishes positive capacity. This PR publishes zero before eligibility, one monotonic positive snapshot after readiness, and a higher zero snapshot when the worker becomes ineligible.
## Source material
- `platform-control-apis.md`: runtime state push `operation=publish-runtime-state`, appserver slot ownership, and not-routable-with-zero-workers rule.
- Roadmap HT10/HT13B and incremental runtime-state milestone.
- HT13 / #11971 and [internal BYOC #219](https://github.com/serverless-paas-balam/FlexConsumption-BYOC/issues/219).
- Prototype `IRuntimeStateManager`, `RuntimeStateManager`, `RuntimeState`, `RuntimeStatePublisher`, and Mesh publish are behavior references only. Do not port placement in shared Script/WebHost or the prototype RequestSlotsController/lease APIs.
## Current state
HT4/HT9 know eligibility and HT8b starts ScriptHost. No compute runtime-state type, appserver client, monotonic revision, or capacity publisher exists. Appserver therefore cannot make the runtime routable or diagnose zero capacity.
## Proposed implementation
1. Confirm payload fields, revision ownership, M1 max-linked value, worker-concurrency source/fallback, and publish failure ownership in HT13.
2. Add immutable compute-owned runtime-state snapshot with revision, max/linked workers, total/available slots. Use `System.Text.Json`; keep types out of Grpc, Server, Script, and standard WebHost.
3. Add root `ComputeRuntimeStateManager` observing HT4/HT9 eligibility and HT8b ScriptHost-started state. A worker contributes capacity only when linked, handshake-complete, ready, and Host-eligible.
4. Read worker-reported concurrency from negotiated capability/status using the HT13 key/fallback. Do not silently retain prototype constants.
5. Assign strictly increasing revisions with `Interlocked.Increment`; snapshots are immutable.
6. Add one-way stopping/ineligible transition forcing zero, without implementing drain workflow.
7. Add `IAppServerCapacityClient` and HTTP implementation posting the frozen `publish-runtime-state` operation to environment-configured appserver endpoint. Non-success/exception is logged and non-fatal; next state change retries.
8. Add root hosted publisher that serializes/coalesces in-flight publishes and sends newest snapshot only, never a stale lower revision.
9. Publish on initial specialized/no-worker zero, first ready positive, worker loss/unhealthy/unlink zero, and process stopping zero.
10. Register manager/publisher/client in compute composition and update compute snapshot.
### Ownership and lifecycle
Manager observes but never owns/mutates channels. HT4 owns channel lifetime, HT9 admission. Appserver owns Frontend leases and allocation revision. Publisher owns one subscription and one publish pipeline; failures do not crash Host.
## Tests and evidence
- initial zero publish before link;
- positive publish after HT9 ready worker with expected reported concurrency and higher revision;
- worker loss yields higher zero;
- rapid transitions preserve strict monotonic order and final state;
- blocked in-flight publish coalesces to newest snapshot;
- failed publish logged/non-fatal and next change republishes;
- exact golden payload/form shape;
- stopping latch one-way zero;
- no Host request-slot route/service and no shared/standard runtime-state type;
- HT14 standard graph/publish/deps/startup and compute output evidence.
The stamp exit signal is a positive revision that [internal BYOC #219](https://github.com/serverless-paas-balam/FlexConsumption-BYOC/issues/219) waits for before sending the request.
## Explicit exclusions
No Host RequestSlotsController/lease accounting, multi-worker policy, link ceiling, drain/eviction/reconnect/relink, billing, debounce optimization beyond correctness, management auth, read/status API, shared-product state types, host.json, extension gRPC, or assembly streaming.
## Acceptance criteria
- Zero capacity before ready worker.
- One higher positive revision after link/init/readiness using worker concurrency.
- Higher zero revision on worker ineligibility.
- No out-of-order snapshots; coalescing publishes latest.
- Publish failure is observable/non-fatal.
- Host exposes no slot lease API; standard product has no capacity behavior.
## PR stop condition
Stop when compute Host publishes zero-before-ready, monotonic positive-after-ready, and zero-after-loss with frozen payload and no Host-side slot leasing. Drain, reconnect, multi-worker, billing, and read APIs are later work.
Contributor guide
Assessment
This issue has not been assessed yet.