feat(core): bound subprocess and network calls with timeouts (closes #145) - #217
Merged
Conversation
…145) No subprocess or network call in @caatinga/core had a timeout, so a stalled registry, wedged network, or hung process hung the CLI forever with no error and no recourse. runCommand gains an optional `timeout` wired into execa. A run killed by it (execa's `timedOut`) throws CaatingaError(CAATINGA_COMMAND_TIMEOUT) naming the limit that was exceeded, ahead of the generic failureCode path so the diagnosis is not swallowed. Budgets live in shell/command-timeouts.ts as named constants rather than a single global default. Caatinga drives commands whose legitimate runtime spans four orders of magnitude, so one default is either tight enough to kill real work or loose enough to catch nothing: - 30s version and capability probes (stellar --version, check-binary, stellar keys address, feature probes) - 60s registry lookups (npm view @stellar/stellar-sdk) - 120s bindings generation (npx --yes @stellar/stellar-sdk generate) - 300s Stellar CLI transactions: deploy, upgrade, upload, invoke, read, simulate, post-deploy hooks, contract-id recovery Contract builds and every @caatinga/zk circuit/ceremony command are deliberately left untimed: a cold Cargo compile or a powers-of-tau ceremony legitimately runs for many minutes, and bounding those needs a per-project budget rather than a constant. The 300s bound on transactions also means a mainnet deploy or upgrade can no longer hang indefinitely mid-flight, which is the failure mode the retry loops in #138 would otherwise sit on top of. Follows the approach proposed by @Galmanus in #183, extended past the two calls the issue named to every network-facing and transaction call site, plus the COMMAND_TIMEOUT-over-failureCode precedence.
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.
Motivation
Closes #145.
No subprocess or network call in
@caatinga/corehad a timeout. A stalled registry, wedged network, or hungstellarprocess hung the CLI forever — no error, no hint, no recourse but Ctrl-C.This also matters for #138: the retry loops around deploy/upgrade/post-deploy sit on top of calls that could block indefinitely mid-flight, on an irreversible mainnet operation.
Behavior
runCommandgains an optionaltimeout, wired into execa. A run killed by it (execa'stimedOut) throwsCaatingaError(CAATINGA_COMMAND_TIMEOUT)naming the limit that was exceeded. That check runs ahead of the genericfailureCodepath — otherwise a deploy killed by its timeout would reportCAATINGA_DEPLOY_FAILEDand bury the actual diagnosis.Budgets are named constants in
packages/core/src/shell/command-timeouts.ts, not a single global default. Caatinga drives commands whose legitimate runtime spans four orders of magnitude, so one default is either tight enough to kill real work or loose enough to catch nothing:stellar --version,check-binary,stellar keys address, CLI feature probesnpm view @stellar/stellar-sdk versionnpx --yes @stellar/stellar-sdk generate(downloads, then generates)Deliberately left untimed: contract builds (
stellar contract build, cold Cargo compiles) and every circuit/ceremony command in@caatinga/zk. A powers-of-tau ceremony or a cold build legitimately runs for many minutes; bounding those needs a per-project budget, not a constant. This is documented incommand-timeouts.tsso the omission reads as a decision rather than an oversight.New public error code
CAATINGA_COMMAND_TIMEOUT, with its row indocs/errors.md.Tests
run-command.test.ts: timeout passes through to execa; staysundefinedwhen not requested; atimedOutrejection maps toCOMMAND_TIMEOUTwith the limit in the hint;COMMAND_TIMEOUTwins over a configuredfailureCode.runCommand/execaand were updated to include the new field.error-surface.test.tscovers the new code.Full run on this branch: core 514/514, cli 175/175, client 94/94, zk 26/26.
pnpm -r build,tsc --noEmitand prettier all clean.Release Impact
Minor. New public error code (additive), new optional
RunCommandOptions.timeout, and new exported timeout constants. Behavior change: commands that previously hung now fail after their budget — intended, but worth a release note for anyone whose network path is slower than the version-probe and registry budgets.Credit
Follows the approach @Galmanus proposed in #183, which was closed unmerged by the author to reduce review load. Extended past the two calls the issue named to every network-facing and transaction call site, plus the
COMMAND_TIMEOUT-over-failureCodeprecedence.Checklist
CAATINGA_*errors added or updated when public failures change.--sourceexamples use a local Stellar CLI identity, not a publicG...address.