airc-queue card
Coordinates work via the AIRC queue substrate (airc#562). Edit this card by commenting OR by running airc queue claim/airc queue release/airc queue heartbeat (later PRs).
{
"kind": "airc-queue-card-v1",
"id": "#1246",
"owner": "claude-tab-2",
"status": "merged",
"evidence": "Adopted existing GitHub issue into airc queue.",
"next_action": "Triage, claim, or close this adopted backlog card."
}
Close this issue when the work is done (status=merged/abandoned).
Original issue body
Pre-adoption body
Smell
Two parallel traits cover the same conceptual ground:
| Trait |
File |
Methods |
Origin |
PressureSource |
paging/broker.rs |
name, pressure, evict_some, stats_snapshot |
Phase 7 broker (PagedResourcePool-shaped) |
ResourcePool |
paging/pool.rs |
tier_name, capacity_bytes, usage_bytes, evict_at_least, snapshot |
#1228 (Docker / VRAM / NVMe tiers) |
PagedResourcePool<K, V> happens to implement both via two separate manual impls. Tier pools that don't follow the per-key-page shape (DockerTierPool, future HF-cache tier, future system-RAM tier) only implement ResourcePool — and so couldn't register with the broker at all without the adapter shim added in #1245 (PR-4 of #1222).
Why it matters
Joel directive 2026-05-14: "code concurrency ONCE then incorporate it. Any hard coded into a subclass or at a lower level use of tokio etc are probably WRONG. ... Reimplenting concurrency is STUPID. ... I would call that out in issues as you find it."
Same principle applies to pressure/capacity surface. One canonical trait, every tier plugs in. The current situation forces an adapter type (ResourcePoolAdapter in paging/adapter.rs) that derives PressureSource from ResourcePool — works, but it's vestigial duplication and two impls drift without coordination.
Proposal sketch (NOT this PR)
- Pick a winner. ResourcePool's surface is more general (capacity_bytes/usage_bytes is more diagnostic than pressure 0..1; evict_at_least(want_bytes) is more controllable than evict_some). PressureSource is just a derived-view over ResourcePool.
- Move
stats_snapshot() onto ResourcePool (it currently mixes with the diagnostic-only fields like hit_count that don't belong on a tier).
- Delete PressureSource. PressureBroker takes
Arc<dyn ResourcePool> directly.
- Delete ResourcePoolAdapter (vestigial after the merge).
- Update PagedResourcePool's manual ResourcePool impl to expose stats_snapshot natively (it already has the data internally).
Constraints
- Keep PagedResourcePool's existing pressure() / stats_blocking() public APIs working — those have other consumers (gpu/memory_manager.rs, possibly more). Add a
fn pressure(&self) -> f64 { self.usage_bytes() as f64 / self.capacity_bytes() as f64 } default-method on ResourcePool so consumers reading pressure don't break.
- Migration is one PR per consumer (broker, then each ResourcePool impl, then deletion of PressureSource + adapter), to keep diffs reviewable.
Status
Filed by claude-tab-2 after #1245 (PR-4 of #1222) added the adapter shim that revealed the smell. Not blocking — the adapter is functional. Logged so the cleanup happens before more tier pools land and the adapter becomes architectural by accident.
Status log
airc-queue card
Coordinates work via the AIRC queue substrate (airc#562). Edit this card by commenting OR by running
airc queue claim/airc queue release/airc queue heartbeat(later PRs).{ "kind": "airc-queue-card-v1", "id": "#1246", "owner": "claude-tab-2", "status": "merged", "evidence": "Adopted existing GitHub issue into airc queue.", "next_action": "Triage, claim, or close this adopted backlog card." }Close this issue when the work is done (status=merged/abandoned).
Original issue body
Pre-adoption body
Smell
Two parallel traits cover the same conceptual ground:
PressureSourceResourcePoolPagedResourcePool<K, V>happens to implement both via two separate manual impls. Tier pools that don't follow the per-key-page shape (DockerTierPool, future HF-cache tier, future system-RAM tier) only implement ResourcePool — and so couldn't register with the broker at all without the adapter shim added in #1245 (PR-4 of #1222).Why it matters
Joel directive 2026-05-14: "code concurrency ONCE then incorporate it. Any hard coded into a subclass or at a lower level use of tokio etc are probably WRONG. ... Reimplenting concurrency is STUPID. ... I would call that out in issues as you find it."
Same principle applies to pressure/capacity surface. One canonical trait, every tier plugs in. The current situation forces an adapter type (
ResourcePoolAdapterin paging/adapter.rs) that derives PressureSource from ResourcePool — works, but it's vestigial duplication and two impls drift without coordination.Proposal sketch (NOT this PR)
stats_snapshot()onto ResourcePool (it currently mixes with the diagnostic-only fields like hit_count that don't belong on a tier).Arc<dyn ResourcePool>directly.Constraints
fn pressure(&self) -> f64 { self.usage_bytes() as f64 / self.capacity_bytes() as f64 }default-method on ResourcePool so consumers reading pressure don't break.Status
Filed by claude-tab-2 after #1245 (PR-4 of #1222) added the adapter shim that revealed the smell. Not blocking — the adapter is functional. Logged so the cleanup happens before more tier pools land and the adapter becomes architectural by accident.
Status log