mirror of
https://github.com/kvcache-ai/AgentENV.git
synced 2026-11-05 01:17:36 +00:00
[PR #51] [CLOSED] feat(scheduler): add snapshot artifact locality preference #141
Labels
No labels
bug
documentation
enhancement
enhancement
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
kvcache-ai/AgentENV#141
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/kvcache-ai/AgentENV/pull/51
Author: @shudorcl
Created: 7/28/2026
Status: ❌ Closed
Base:
main← Head:issue-15-snapshot-locality📝 Commits (10+)
a762adafeat(gateway): add snapshot locality requirements1c1af6crefactor(scheduler): expose node locality context086e71dfeat(scheduler): score artifact localityaf1a96efeat(scheduler): apply locality before node selection1b82399chore(api): format generated scheduler protobuf211fbf4docs(services): document snapshot locality schedulingecd391bUpdate services/scheduler/internal/locality.go89f1dadUpdate services/scheduler/internal/service.go460c590Update services/scheduler/internal/locality.go186df1dfix(services): harden snapshot locality scheduling📊 Changes
18 files changed (+1123 additions, -229 deletions)
View changed files
📝
services/README.md(+29 -0)📝
services/api/proto/scheduler.pb.go(+277 -207)📝
services/api/proto/scheduler.proto(+9 -0)📝
services/gateway/internal/schedule_hint.go(+18 -2)📝
services/gateway/internal/schedule_hint_test.go(+49 -0)📝
services/gateway/internal/server.go(+2 -1)➕
services/gateway/internal/template_resolution.go(+47 -0)➕
services/gateway/internal/template_resolution_test.go(+95 -0)📝
services/go.mod(+1 -1)➕
services/scheduler/internal/locality.go(+116 -0)➕
services/scheduler/internal/locality_test.go(+184 -0)📝
services/scheduler/internal/node_registry.go(+12 -11)📝
services/scheduler/internal/node_registry_test.go(+44 -0)📝
services/scheduler/internal/service.go(+31 -3)📝
services/scheduler/internal/service_test.go(+133 -0)📝
services/scheduler/internal/store.go(+43 -3)📝
services/scheduler/internal/store_test.go(+22 -0)📝
services/scheduler/internal/types.go(+11 -1)📄 Description
What
This PR implements the first P2P-backed snapshot locality preference slice for #15.
For
POST /sandboxes, whentemplateIDis a canonical snapshot UUID in the standard hyphenated form, the Gateway derives two advisory locality requirements using the existing fixed snapshot artifact identities:snapshot/v1/artifacts/{snapshot_id}/vm_state.binsnapshot/v1/artifacts/{snapshot_id}/firecracker-manifest.jsonAfter resource-limit filtering, the Scheduler prefers eligible nodes that advertise the highest coverage of those artifacts in the existing P2P artifact index. The configured scheduling strategy performs the final selection among tied nodes.
Template aliases remain supported, but intentionally do not produce locality hints because the Gateway has no authoritative pre-scheduling alias resolver. Alias requests therefore use the existing scheduling behavior.
Why
The scheduler currently ignores whether an eligible node already provides the snapshot artifacts needed to start a sandbox. It can therefore select a cold node even when another feasible node advertises the required artifacts through the existing P2P index.
This change introduces a bounded, advisory locality preference without duplicating load-aware selection or changing runtime fallback behavior. It establishes the request and inventory path needed for later locality work while keeping the scheduler's artifact store limited to artifact-key-to-node mappings.
Related issue
Refs #15
This PR is one focused part of #15 and does not close the full issue.
Scope and non-goals
In scope:
Non-goals:
POST /sandboxes-cold;cache_awarestrategy;Design and behavior changes
The scheduling flow becomes:
The Gateway inspects only exact
POST /sandboxescreation requests. It buffers at most 64 KiB while extractingtemplateIDand restores the original body for upstream forwarding. Oversized, malformed, empty, alias-based, and non-canonical template IDs produce no locality requirements and continue through normal scheduling.For a canonical snapshot UUID, the Gateway normalizes the ID and emits the two fixed artifact keys listed above. It does not query runtime nodes to resolve aliases. Such fan-out would be non-authoritative, could observe inconsistent alias mappings, would amplify unauthenticated request work, and could expand credential exposure.
The Scheduler validates the request-controlled locality requirement count before node discovery. After resource filtering,
PreferLocalNodes:Artifact lookup intersects provider records with the eligible node-ID set inside the store, so scheduling work scales with current candidates rather than all historical providers. Locality does not create reservations or other request-lifetime state.
Locality remains advisory. Stale or missing records do not fail sandbox creation, and the selected runtime continues through its normal local cache, P2P, snapshot repository, or registry fallback path.
Compatibility and operations
ScheduleRequestHint.locality_requirements,LocalityRequirement.key, andNewSandboxHint.template_idfields to the internal scheduler protobuf. The additions are wire-compatible. Older senders omit them, and receivers without locality support ignore the unknown fields.round_robinandrandomstrategy behavior is unchanged when locality requirements or provider records are unavailable.snapshot/v1/artifacts/{snapshot_id}/...identities.github.com/google/uuidis promoted from an indirect to a direct Go dependency at the same version.Validation
make fmtmake clippymake test-unitmake -C services test(required whenservices/changes)maketargetCommands and results:
The Services commands above were run locally.
fmt-checkwas verified from an LF-normalized export of the same commit because this WSL checkout usescore.autocrlf=true.The following remote Services CI and integration jobs also passed for commit
b2f9346577b001bba28fb038d46ae0beb233c956:Skipped checks and reasons:
Risks and reviewer notes
LookupEligiblebounds work to the current eligible candidate IDs, and unregistering a node removes its artifact mappings.services/gateway/internal/schedule_hint.go,services/gateway/internal/template_resolution.go,services/scheduler/internal/locality.go, andservices/scheduler/internal/service.go.Checklist
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.