Skip to content

chore(cli): connect bound, audible cache writes, fetch-failure sweep - #185

Merged
Sootopolis merged 1 commit into
mainfrom
chore/cli-hygiene
Jul 27, 2026
Merged

chore(cli): connect bound, audible cache writes, fetch-failure sweep#185
Sootopolis merged 1 commit into
mainfrom
chore/cli-hygiene

Conversation

@Sootopolis

Copy link
Copy Markdown
Owner

Three independent hygiene fixes — the cheap wins sequenced ahead of the club-resolver chain (#180). All on one PR since they're small and share Dispatcher.scala.

#182 — CLI connect bound

Dispatch and use-club's verify probe provisioned stock Client.default, whose connect is unbounded (zio-http's 30s default), so a black-holed/misconfigured api_url hung the CLI for 30s before any message. Both sites now provision HttpClientLayer.live — the repo's shared transport, which already sets connectionTimeout(10s). Bounding connect at the Netty layer (below ZIO interruption) sidesteps the uninterruptible-unwind problem a ZIO-level .timeout hits, and — unlike a blanket request timeout — leaves legitimately-slow synchronous calls (a large blacklist add) and the streaming follows (logs, job follow) untouched. This also makes HttpClientLayer's scaladoc claim ("used at every provisioning site") finally true.

#181 — audible completion-cache writes

club add / club remove now repopulate the completion cache through a reported write: an unwritable cache dir is named on stderr instead of failing silently forever. Never changes the exit code (a broken completion cache is not a failed command). The write is a better signal than the old invalidate here — deleting an absent file succeeds, so a failed delete can't detect an unwritable dir, which is exactly the issue's repro. A fetch failure stays silent (the preceding server call just succeeded, so a managed-set fetch blip is not a cache-dir problem).

#184 — sweep api_fetch_failure on startup

ApiFetchFailure.deleteBefore had zero callers, so the failure audit trail grew unbounded — 404 bodies embed the requested slug, defeating SHA-256 dedup, and orphan bodies are pinned by ON DELETE RESTRICT. Now swept on the same startup pass as the cache, behind a new DB-owned FetchFailureRetentionDays app_setting (default 30d). deleteBefore already chains deleteOrphans and has orphan-cleanup test coverage.

Testing

  • Full suite green locally (pre-push hook): 1111 passed, 0 failed.
  • AppSetting.all iterates generically, so the new key is auto-covered by TestAppSettingSql.

Closes #182
Closes #181
Closes #184

🤖 Generated with Claude Code

https://claude.ai/code/session_017eZg53up5PrYiMgukmc65Q

Three independent hygiene fixes ahead of the club-resolver chain (#180).

#182: CLI dispatch and use-club's verify probe now provision
HttpClientLayer.live instead of Client.default, inheriting the shared
transport's connectionTimeout(10s). A black-holed server fails connect
natively at 10s instead of parking a fiber on zio-http's unbounded 30s
default. Bounding connect at the Netty layer (below ZIO interruption)
sidesteps the uninterruptible-unwind problem and, unlike a blanket
request timeout, leaves slow synchronous calls (a large blacklist add)
and the streaming follows untouched.

#181: club add / club remove repopulate the completion cache through a
reported write; an unwritable cache dir is now named on stderr instead
of failing silently forever. Never changes the exit code. The write is
a better signal than the old invalidate here (deleting an absent file
succeeds, so a failed delete can't detect an unwritable dir).

#184: sweep api_fetch_failure on startup behind a new
FetchFailureRetentionDays app_setting (30d), chained after the cache
sweep. deleteBefore had zero callers, so the failure audit trail grew
unbounded (404 bodies embed the requested slug, defeating SHA-256 dedup).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eZg53up5PrYiMgukmc65Q
@Sootopolis
Sootopolis merged commit 5315079 into main Jul 27, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant