ENG-534: Per-request instance sizing#4
Merged
clawhavenapp merged 2 commits intoJul 7, 2026
Conversation
czpython
force-pushed
the
commonzenpython/eng-534-per-request-instance-sizing
branch
from
July 7, 2026 00:42
e590048 to
a38e518
Compare
clawhavenapp
changed the base branch from
commonzenpython/eng-525-pool-per-provider-provider-aware-warm-pool
to
main
July 7, 2026 17:38
POST /hosts accepts optional instance_type (provider-native, e.g. t3.xlarge / cx33) and disk_gb. The values are stamped on the host row (NULL = provider default), forwarded from provision() to create_vm, and reflected by GET. Providers declare support via supports_instance_type / supports_disk_gb class vars: AWS honors both, Hetzner maps instance_type to its server type, exe.dev and docker expose no sizing — the service rejects unsupported sizing with a 400 before any row or VM exists. A sized request is never pool-eligible: warm hosts are provisioned at the provider's default size, so sizing joins image/env in the customization check that forces fresh provisioning. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
czpython
force-pushed
the
commonzenpython/eng-534-per-request-instance-sizing
branch
from
July 7, 2026 17:41
a38e518 to
c54f937
Compare
The base VMProvider already declares supports_instance_type/supports_disk_gb as ClassVar[bool]; pyright inherits that classification on override, so restating ClassVar on each subclass added nothing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
clawhavenapp
deleted the
commonzenpython/eng-534-per-request-instance-sizing
branch
July 7, 2026 18:00
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Was stacked on #1; #1 merged, now rebased onto main (base retargeted).
What
POST /hostsaccepts two optional sizing fields:instance_type(provider-native, e.g. AWSt3.xlarge, Hetznercx33) anddisk_gb(root disk in GB). The values are stamped on the host row (NULL= provider's configured default), forwarded fromprovision()tocreate_vm, and reflected byGET /hosts/{id}. Alembic migration0002_host_sizingadds the two nullable columns.Provider support is declared on the adapter via
supports_instance_type/supports_disk_gbclass vars (defaultFalseonVMProvider):instance_type→ EC2InstanceType,disk_gb→ root EBS volume size.instance_type(maps onto its nativeserver_type);disk_gbis rejected because Hetzner fixes root disk size by server type.HostService.create_hostchecks the flags right after resolving the provider, so unsupported sizing returns a clear 400 (same mapping as unknown provider) before any host row or VM exists — no silent fallback, nothing for the janitor to reap.Pool interaction (per the pool-per-provider work in #1): warm hosts are provisioned at the provider's default size, so sizing joins
image/envin the customization check — a sized request never claims a default-sized pool member and always provisions fresh. Noted indocs/architecture.md.Why raw provider-native
instance_typeinstead of a portable classThe ticket left portable-class (
standard/large) vs raw-type-passthrough open. This PR goes provider-native, as explicit named fields (instance_type+disk_gb), not a free-form bag:HostCreate.provider): a caller pinning a size knows which provider it's sizing for, so provider-native names are unambiguous, and the provider itself validates them (a bad type fails provisioning loudly).--typepassthrough alongside--class, so the raw field is the primitive either way.Unsupported sizing is refused via declarative class-var flags + one service-side check rather than a capability mix-in or a runtime
create_vmerror: there is no new method surface to mix in (sizing ridescreate_vmparams), and rejecting insidecreate_vmwould fire after the row exists, turning a caller mistake into a 502 + janitor cleanup instead of the required 4xx.Acceptance criteria
POST /hostswith no sizing fields behaves exactly as today (provider default;instance_type/disk_gbsurface asnull)POST /hostswith aninstance_typeprovisions a host of that size on AWS;GET /hosts/{id}reflects itVerification
uv run ruff check,uv run ruff format --check,uv run pyright,uv run pytest(290 passed) all green;alembic upgrade head/downgrade -1/upgrade headcycle verified on a scratch DB. Codex review against the stack base: clean, zero findings.Rebase note: rebased onto the base branch's review-fix commit 68719e5 (shuffled per-tick top-up order in
pool._maintain+ regression test). Clean replay, no conflicts; this PR doesn't touchpool._maintain, and the pool maintainer creates hosts without sizing, so there's no interaction with the shuffle fix. Full gate re-run green on the rebased tree (ruff, ruff format --check, pyright, pytest 291 passed).🤖 Generated with Claude Code