Warm pool: a baseline kind is learned on its Nth lease in 24 h and warms its newest version
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 15/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- typescript
- Lĩnh vực
- devtools
Hướng nghiên cứu
Start with ADR 0062 and the listed modules: src/core/warm-pool/learned.ts, converger.ts, and config.ts; then check the contract schema, protocol, tests, and the two worker documentation pages. Follow the issue’s technical spec and test plan across the warm pool state, config, and contract changes. Done means the Nth-lease learning rule, newest-version warming, migration, config exposure, docs, and protocol update all match the spec.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Part of #1257.
Scope
All of #1257: the worker setting warmPool.baselineLearnAfter, the rule that learns a baseline kind only on its Nth lease within 24 hours, one learned record per baseline name warmed as the baseline's newest version, the warm pool's third schema version, and the docs. ADR 0062 (PR #1260) is the decision.
In short
After this PR a baseline leased fewer than N times in 24 hours leaves nothing booted after its lease; N is warmPool.baselineLearnAfter, default 3. The lease that brings it to N learns it, and from then on it is kept warm like a plain kind. A learned baseline is warmed as its newest version's platform, model, OS, mode, image tag and version, so a version saved from another model is warmed as that model on the next pass. Plain kinds are learned on their first lease, as today.
flowchart LR
A[lease.granted of a baseline copy] --> B[record the lease under the baseline's one row]
B --> L{already learned?}
L -->|yes| E
L -->|no| C{"grants of it in the last 24 h ≥ N? (changed)"}
C -->|no| D[counting: not planned, not listed]
C -->|yes| E[learned, kept learned]
E --> F["each pass: spec = newest version's platform, model, OS, mode, tag, version (changed)"]
- counting: a baseline row not yet learned, with fewer than N grants in 24 hours; recorded, not planned, not in
figures(), not intargeted(), not matched bywarm forget. A row once learned stays learned whatever its later grants: the learned mark is stored, never worked out from the window. - grants in the last 24 hours: leases of the row whose grant time is later than 24 hours (86,400,000 ms) before the grant being recorded, that grant included, read by the worker's clock. A lease granted exactly 24 hours before is out.
A bad value fails the load with Invalid config value for "warmPool.baselineLearnAfter": expected a positive integer; through simlock config set the CLI prints it after Invalid config after setting warmPool.baselineLearnAfter: (exit 2).
warmPool.baselineLearnAfter |
Today | After |
|---|---|---|
| unset | no such key | 3 |
1 |
no such key | a baseline learned on its first lease |
5 |
no such key | learned on the 5th lease in 24 h |
0, -1, 2.5, "3" |
no such key | config load fails with the message above |
If this goes wrong, a busy baseline is never kept warm and every lease of it pays a copy and a boot, or a one-off baseline still stays booted.
Technical spec
Facts
Commit 059a270.
| # | Fact | Source |
|---|---|---|
| F1 | The pool learns on lease.granted, only with warmPool.enabled, from the leased device's spec in the registry |
src/core/warm-pool/converger.ts:206-219 |
| F2 | A learned row is keyed on platform, model, OS, mode, image tag and baseline name | src/core/warm-pool/learned.ts:27-38 |
| F3 | Each pass swaps in only the baseline's newest version number; model, OS, mode and image tag stay the stored ones | src/core/warm-pool/converger.ts:249-258 |
| F4 | baselines.current(name) answers the newest version's platform, model, OS, mode, image tag, version and stale reason, or undefined |
src/core/baselines.ts:217-235 |
| F5 | Baselines are keyed by name alone: current reads WHERE name = ? with no platform |
src/core/baselines.ts:220-222 |
| F6 | A copy is made of the version current at that moment; the provisioner sets the copy's baseline name and version from current |
src/core/device-provisioner.ts:64-78 |
| F7 | A lease naming a baseline takes the baseline's platform, model, OS, mode and image tag | src/leasing/lease-acquisition-coordinator.ts:553-566 |
| F8 | learn upserts the row, writes the lease row, deletes lease rows that ended more than 24 h ago, and drops rows past 32 per platform, oldest last_leased_at first |
src/core/warm-pool/learned.ts:80-118 |
| F9 | A lease granted within the last 24 h keeps its lease row: only rows whose ended_at is more than 24 h old are deleted |
src/core/warm-pool/learned.ts:105-107 |
| F10 | kinds(now) lists every row, count = 24 h peak, at least 1; nothing ages a row out |
src/core/warm-pool/learned.ts:184-209 |
| F11 | forgetMatching matches on the stored model, OS, mode and image tag |
src/core/warm-pool/learned.ts:143-157, :217-231 |
| F12 | The pool's owner is warm-pool, version 2, migrations [WARM_POOL_V1, WARM_POOL_V2] |
src/core/warm-pool/learned.ts:54-58 |
| F13 | state.db runs each owner's missing migrations in one transaction; a throw rolls every owner back and refuses the start |
src/state/open.ts:159-168 |
| F14 | The learned kinds feed the plan, figures(), targeted() and the catalog check through #learnedKinds(), empty with learn: false |
src/core/warm-pool/converger.ts:261-275, :335, :452, :612-653 |
| F15 | The catalog check drops a baseline kind whose baseline is removed or stale | src/core/warm-pool/catalog-check.ts:45-48 |
| F16 | WarmPoolConfig and its validators: learn a boolean, maxConcurrentBoots a positive integer, defaults in defaultWarmPoolConfig |
src/core/warm-pool/config.ts:28-50, :111-117 |
| F17 | positiveInteger refuses a non-number, a non-integer and anything below 1 with expected a positive integer; the message is Invalid config value for "<path>": expected <what> |
src/core/validation.ts:17-19, :62-67 |
| F18 | Core composes the warm pool validators into the warmPool object |
src/core/config.ts:1109 |
| F19 | config.get's answer declares each warmPool key; an undeclared one is stripped |
src/contract/schemas.ts:1030-1035; src/contract/AGENTS.md (Rules: "a core field the schema does not declare is stripped") |
| F20 | config set parses the value as JSON and wraps a load failure as Invalid config after setting <key>: <message> (a UsageError, code USAGE, exit 2) |
src/cli/commands/config.ts:56-60, :115; src/cli/errors.ts:46 |
| F21 | The protocol range is { min: 73, max: 73 } |
src/contract/protocol.ts:13 |
| F22 | warm forget reaches WarmPool.forgetKinds through core.warmKinds |
src/core/create-core.ts:388, src/core/warm-pool/converger.ts:190-203 |
| F23 | warmPool.learn: false still records leases; it only stops planning |
src/core/warm-pool/converger.ts:209-219, :262 |
| F24 | The website describes learning in capacity.mdx and the keys in configuration.mdx; config-reference.test.ts holds the key list to the validators |
website/src/content/docs/docs/worker/capacity.mdx:161, :181; website/src/content/docs/docs/reference/configuration.mdx:118-119; src/core/config-reference.test.ts:79 |
| F25 | Baselines are in no release: v0.5.0 does not contain commit 659c318 |
git tag --contains 659c318b5 printed nothing |
| F26 | Leasing never grants a copy of a version a save replaced | src/leasing/lease-acquisition-coordinator.ts:1338-1343 |
Modules touched
Searches: learn, LearnedKinds, warm_kinds, warmPoolOwner, atCurrentVersion, forgetMatching, maxConcurrentBoots (every place a warmPool key is declared) over src/ and website/.
src/core/warm-pool/learned.ts: schema version 3, the Nth-lease rule, one row per baseline name, the counting state.src/core/warm-pool/converger.ts: passes N to the record; a baseline kind's spec from the newest version;forgetKindsmatches it.src/core/warm-pool/config.ts:baselineLearnAfter, default and validator.src/contract/schemas.ts,src/contract/protocol.ts: the key inconfig.get'swarmPool; the bump.src/core/warm-pool/AGENTS.md,website/src/content/docs/docs/worker/capacity.mdx,website/src/content/docs/docs/reference/configuration.mdx.
flowchart LR
CFG[core/warm-pool/config.ts *] --> CONV[core/warm-pool/converger.ts *]
CONV --> LK[core/warm-pool/learned.ts *]
CONV --> BS[core/baselines.ts current]
LK --> ST[state.db warm-pool owner *]
CORECFG[core/config.ts] --> CFG
SCH[contract/schemas.ts config.get *] --> CORECFG
Contract and event changes
config.get's warmPool gains baselineLearnAfter: number (optional, as learn is; F19). This PR bumps the protocol by one. The file key: an integer of at least 1, no upper bound, as maxConcurrentBoots (F16, F17); anything else fails the load naming the key. No event changes.
Other code on the same state
Searches: warm_kinds and warm_kind_leases (2 files: learned.ts, learned.test.ts), #learnedKinds( (5 calls in converger.ts), .learned. (8 calls in converger.ts).
| Component | What happens when both act | Wins |
|---|---|---|
#learnedKinds() readers: plan, figures(), targeted(), catalog check (F14) |
They see learned rows only; a counting row is never listed, so it is never planned, spared or checked | the record |
forget() on nuke, the third failed boot, the catalog check (F15) |
Delete the row and its lease rows, a baseline row found by its name, since the spec they pass is the newest version's (converger.ts:454, :833); the next lease counts from zero |
the forget |
warm forget (F22) |
Matches a learned baseline kind on the newest version's platform, model, OS, mode and image tag; a counting row is never matched, answered or deleted, so the CLI's The warm pool has learned no kind matching … stays true (src/cli/commands/warm.ts:68-72) |
the forget |
closeOpen at start |
Closes counting rows' open leases too; grant times are untouched, so the count holds | n/a |
The 32-row cap in learn (F8) |
A counting row is a row: it counts and can be dropped, oldest last_leased_at first. Each lease rewrites a baseline row's stored platform, model, OS, mode and image tag to the leased copy's, so it counts under the platform of its latest lease |
as today |
BaselineService save (F4, F6) |
A save between two passes: the next pass reads the new version and warms its model; a copy of the old version made before is never granted (F26) | the newest version |
| #1143 (open, not ready) | Also raises the warm-pool owner's version; whichever merges second takes the next number |
the later merge renumbers |
Failure modes
| Call | Outcome | What happens | Limit, counted from |
|---|---|---|---|
LearnedKinds.learn on lease.granted |
ok | lease recorded; row learned once its grants in 24 h reach N | none |
LearnedKinds.learn |
throws | one warn line, the lease goes on, as today (#recording) |
none |
baselines.current(name) in a pass |
undefined (removed) |
the kind keeps its stored spec for that pass; the catalog check forgets it (F15) | the next pass |
baselines.current(name) |
stale | the catalog check forgets it (F15) | the next pass |
warmPoolOwner migration 3 |
throws | state.db refuses the start and rolls every owner back (F13) |
none |
A restart between a grant and its record leaves the grant uncounted, as today. Two grants at once are two learn calls, each in its own transaction (F8); the second sees the first's lease row. No Tests line for the throw rows: they are today's paths, proved by converger.test.ts "logs a LearnedKinds throw once" and the state module's tests.
Rules in play
- ADR 0062 §1: "learned on the Nth lease within 24 hours"; the record counts grants and sets the row learned on the Nth.
- ADR 0062 §2: "keys a baseline kind on its baseline name only"; one row per name, platform and spec from the newest version each pass.
- ADR 0062 §3: "Rows of baseline kinds written before it are deleted with their lease rows"; migration 3.
- ADR 0038 §1, §2, §4: plain kinds, the peak and the forget reasons unchanged.
- Documentation rule 9: a change to the config surface updates the pages that describe it;
capacity.mdxandconfiguration.mdx. - Testing rule 7: a claim an existing test proves extends that test; the converger's learning and figures tests and
learned.test.ts's migration test are extended.
Tests
Seam: WarmPool through its bus and figures() with a fake clock and baselines port, modelled on src/core/warm-pool/converger.test.ts ("learns on lease.granted…", line 2265); the config line on src/core/config.test.ts (describe("warmPool.targets and warmPool.maxConcurrentBoots")); the restart line on src/core/warm-pool/learned.test.ts.
- An operator sets
warmPool.baselineLearnAfterand the daemon loads it and answers it inconfig.get: unset → 3;1;5;0,-1,2.5,"3"→ invalid config naming the key;config.getreturns the value. - Agents lease a baseline, and the warm pool learns its kind only on the Nth lease within 24 hours: N = 3: 1st and 2nd leases → no learned kind, nothing booted after release; 3rd within 24 h → learned, kept booted; leases at 0 h, 1 h, 25 h, 26 h → not learned; at 0 h, 20 h, 23 h → learned at 23 h; at 0 h, 12 h, 24 h → not learned; learned at 2 h (leases at 0, 1, 2 h) → still learned and kept booted at 30 h, and a 4th lease at 30 h keeps it learned; N = 1 → 1st lease learns; leases of v1 and v2 count together; a plain kind learned on its 1st lease; a forgotten baseline kind counts from zero.
- A learned baseline kind is warmed as the baseline's newest version: new version from another model → kind shows and creates the new model and version; another OS; another image tag; another platform; same model, new version → version only; after a save from another model, its third failed boot in a row forgets it.
- An operator forgets a learned baseline kind with
warm forget: match by the newest version's model → forgotten; by the old version's model → not forgotten; narrowed by OS, mode, image tag; a baseline still counting → not answered, keeps counting. - A worker restarts, and the record keeps what it learned: a learned baseline kind stays learned; a counting one keeps its lease rows and counts on; a file at warm pool version 2 opens at version 3 with plain kinds and their leases kept and baseline kinds dropped.
Done when
pnpm testpasses the five Tests lines above.simlock config get warmPool.baselineLearnAfterprints3on a worker with no such key inconfig.json.capacity.mdxsays a baseline is learned on its Nth lease within 24 hours and is warmed as its newest version;configuration.mdxlistswarmPool.baselineLearnAfter;config-reference.test.tspasses.- The protocol range is one above
main's when the PR merges.
Out of scope
- A baseline in
warmPool.targets. warm forget --baseline <name>.- Showing counting baselines in status or the console.
Depends on
- #1239 (both bump the protocol; #1239 depends on #1238)
Written by an agent.
- Ngôn ngữ chính
- TypeScript
- Star
- 535
- Fork
- 21
- Merge trung bình
- 9 giờ 31 phút
- Pull request đã merge (30 ngày)
- 434
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của callstackincubator/simlock
-
bug:new platform:ios
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
callstackincubator/simlock#1293 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Full-mode iOS boot wait is fixed at 120 s: on a busy 16 GiB Mac every new full simulator failsĐang mởrequest:new
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
callstackincubator/simlock#1248 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug:new
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
callstackincubator/simlock#1234 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug:new
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
callstackincubator/simlock#1229 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
os:windows request:new
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
callstackincubator/simlock#1071 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của callstackincubator/simlock
Issue tương tự
-
cloudflare-cache-binding: `unstorage://` keys are rejected by the Cache API, cache never storesĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 3 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
Maintainer thường phản hồi trong vòng 2 ngày
-
reproduced
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
anomalyco/opencode#62052 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
strapi/design-system#2084 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
Maintainer thường phản hồi trong vòng 1 ngày