Warm pool: a baseline kind is learned on its Nth lease in 24 h and warms its newest version

Đang mở
#1,261 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

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ả

task:ready

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 in targeted(), not matched by warm 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; forgetKinds matches it.
  • src/core/warm-pool/config.ts: baselineLearnAfter, default and validator.
  • src/contract/schemas.ts, src/contract/protocol.ts: the key in config.get's warmPool; 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.mdx and configuration.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.baselineLearnAfter and the daemon loads it and answers it in config.get: unset → 3; 1; 5; 0, -1, 2.5, "3" → invalid config naming the key; config.get returns 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 test passes the five Tests lines above.
  • simlock config get warmPool.baselineLearnAfter prints 3 on a worker with no such key in config.json.
  • capacity.mdx says a baseline is learned on its Nth lease within 24 hours and is warmed as its newest version; configuration.mdx lists warmPool.baselineLearnAfter; config-reference.test.ts passes.
  • 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

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của callstackincubator/simlock

Tất cả issue của callstackincubator/simlock

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.