fix(docker): restore someguy sidecar with corrected IPNS config#325
Conversation
…ocally Entire-Checkpoint: e2afefc2dcf0
…NS testing Previous staging deployment failed because: no libp2p port exposed (4004), standard DHT mode instead of accelerated, and resource limits too tight. This config fixes all three: exposes 4004 for DHT participation, uses accelerated mode (default), and gives 2GB RAM / 1 CPU with 1GB libp2p memory. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 1743c748c3e8
…324) * chore(ci): parallelize CI jobs and bump Kubo to v0.40.0 in all workflows Parallelize independent CI jobs to reduce pipeline time: - test: no longer waits for typecheck (builds packages itself) - sdk-e2e: no longer waits for test (independent suite with own services) - build: no longer waits for all checks (compilation check only) Before: changes → typecheck → test → sdk-e2e → build (sequential) After: changes → lint → {test, sdk-e2e, build} (parallel) Also bumps Kubo v0.34.0 → v0.40.0 in ci.yml, e2e.yml, and load-test.yml service containers to match docker-compose (PR #321). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: d1f8e21dba94 * chore(ci): add lint to all job needs, simplify if conditions Address PR review: - Add lint to typecheck/api-spec/migration-check needs for fail-fast - Remove redundant !failure() && !cancelled() conditions now that jobs only depend on changes + lint Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: fbaacaeafccc --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause of the Phase 19 someguy failure was threefold: 1. No libp2p port (4004) exposed — DHT couldn't receive inbound connections 2. DHT mode set to 'standard' instead of 'accelerated' (default) 3. Resource limits too tight (0.5 CPU, 768MB RAM, 512MB libp2p memory) Fix: expose port 4004 (TCP+UDP), use accelerated DHT mode, allocate 2GB RAM / 1 CPU / 1GB libp2p memory, and increase start period to 60s. Verified locally: someguy IPNS GET resolves in ~0.5s, PUT in ~0.1s, and all 83 SDK E2E tests pass with someguy as the routing backend. Also restores someguy Prometheus metrics scraping in Alloy config and updates deploy-staging workflow to use http://someguy:8190. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 58b1c8d9fd40
Vitest does not auto-load .env files into process.env — env vars must be passed explicitly on the command line or via dotenv setup. This caused spurious 429 failures during someguy testing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 8a5fc5b5e16a
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
WalkthroughAdds a self-hosted IPFS routing service (someguy) and monitoring, bumps Kubo/IPFS service images in CI/workflows, simplifies CI job wiring, and implements delegated-routing fallback, observability counters, and tests in the API codebase; plus operational notes and compose/stack updates. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client
participant DelegatedRoutingClient
participant PrimaryBackend as Primary (someguy/remote)
participant FallbackBackend as Fallback (someguy/remote)
participant Metrics
Client->>DelegatedRoutingClient: publish / resolve request
DelegatedRoutingClient->>Metrics: delegatedRoutingRequests.inc(operation=..., backend=primary, outcome=attempt)
DelegatedRoutingClient->>PrimaryBackend: attempt request (with retries)
alt Primary succeeds
PrimaryBackend-->>DelegatedRoutingClient: 2xx response
DelegatedRoutingClient->>Metrics: delegatedRoutingRequests.inc(operation=..., backend=primary, outcome=success)
DelegatedRoutingClient-->>Client: return success
else Primary fails (after retries) and fallback configured
PrimaryBackend-->>DelegatedRoutingClient: terminal error
DelegatedRoutingClient->>Metrics: delegatedRoutingRequests.inc(operation=..., backend=primary, outcome=error)
DelegatedRoutingClient->>Metrics: delegatedRoutingFallbacks.inc(operation=...)
DelegatedRoutingClient->>FallbackBackend: retry request against fallback (with retries)
alt Fallback succeeds
FallbackBackend-->>DelegatedRoutingClient: 2xx response
DelegatedRoutingClient->>Metrics: delegatedRoutingRequests.inc(operation=..., backend=fallback, outcome=success)
DelegatedRoutingClient-->>Client: return success
else Fallback fails
FallbackBackend-->>DelegatedRoutingClient: terminal error
DelegatedRoutingClient->>Metrics: delegatedRoutingRequests.inc(operation=..., backend=fallback, outcome=error)
DelegatedRoutingClient-->>Client: throw HttpException(BAD_GATEWAY)
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docker/docker-compose.staging.yml`:
- Around line 121-122: Update the healthcheck command for the someguy service to
use curl instead of wget so the probe works with ghcr.io/ipfs/someguy:v0.11.1;
locate the healthcheck block (healthcheck: test:) in the docker-compose service
definition for someguy and replace the current 'wget -qO-
http://localhost:8190/version || exit 1' invocation with an equivalent curl
invocation that returns nonzero on failure (e.g., using curl --fail or -sS) so
the container can be marked healthy.
In `@docker/docker-compose.yml`:
- Around line 84-85: The healthcheck uses wget but the
ghcr.io/ipfs/someguy:v0.11.1 image does not include wget; update the healthcheck
test in the healthcheck block (the `test:` line) to call curl instead of wget
(e.g. use curl with silent/fail flags such as curl -fsS --fail
http://localhost:8190/version or similar so it returns non‑zero on failure) so
the container healthcheck works with the someguy image.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9e2f6c3d-b7f1-4474-aaf3-d07f2d185b8a
📒 Files selected for processing (9)
.github/workflows/ci.yml.github/workflows/deploy-staging.yml.github/workflows/e2e.yml.github/workflows/load-test.yml.learnings/2026-03-23-vitest-env-vars-not-auto-loaded.md.planning/todos/done/2026-03-23-investigate-someguy-ipns-routing-failure-locally.mddocker/alloy-config.riverdocker/docker-compose.staging.ymldocker/docker-compose.yml
When the primary routing backend (someguy) fails after all retries,
the DelegatedRoutingClient now falls back to a configurable secondary
URL (DELEGATED_ROUTING_FALLBACK_URL). For staging, this is
delegated-ipfs.dev as a safety net.
New Prometheus metrics:
- cipherbox_delegated_routing_requests_total{operation,backend,outcome}
tracks every routing request with primary/fallback backend label
- cipherbox_delegated_routing_fallbacks_total{operation}
counts how often the primary fails and fallback is triggered
These enable Grafana alerting on frequent fallback usage, which would
indicate someguy health issues.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: a6f0bc4244a3
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #325 +/- ##
==========================================
+ Coverage 50.58% 50.63% +0.04%
==========================================
Files 115 116 +1
Lines 9196 9919 +723
Branches 720 727 +7
==========================================
+ Hits 4652 5022 +370
- Misses 4367 4718 +351
- Partials 177 179 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
The ghcr.io/ipfs/someguy image includes curl but not wget, so the wget-based healthcheck would fail inside the container. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: ed489ad9746f
There was a problem hiding this comment.
Pull request overview
Restores the self-hosted Someguy delegated-routing sidecar and updates the API + staging infrastructure to use it as the primary IPNS delegated routing backend, with fallback to delegated-ipfs.dev and added observability.
Changes:
- Add Someguy service back to local + staging docker-compose with corrected DHT/libp2p configuration and resource limits.
- Add delegated routing Prometheus counters and implement primary→fallback routing logic in the API client.
- Update staging deploy + monitoring to point to
http://someguy:8190and re-enable Someguy metrics scraping; bump Kubo versions in CI workflows.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| docker/docker-compose.yml | Restores Someguy service for local/dev with ports, env, and healthcheck. |
| docker/docker-compose.staging.yml | Restores Someguy service in staging stack with DHT/libp2p config and healthcheck. |
| docker/alloy-config.river | Re-adds Prometheus scraping for Someguy metrics endpoint. |
| apps/api/src/metrics/metrics.service.ts | Adds Prometheus counters for delegated routing requests and fallbacks. |
| apps/api/src/ipns/delegated-routing.client.ts | Implements primary/fallback routing URLs + emits delegated routing metrics. |
| apps/api/src/ipns/delegated-routing.client.spec.ts | Extends tests for metrics emission and fallback behavior. |
| apps/api/.env.example | Documents DELEGATED_ROUTING_FALLBACK_URL usage. |
| .planning/todos/done/2026-03-23-investigate-someguy-ipns-routing-failure-locally.md | Adds investigation notes and resolution summary. |
| .learnings/2026-03-23-vitest-env-vars-not-auto-loaded.md | Documents Vitest env var loading behavior relevant to E2E runs. |
| .github/workflows/load-test.yml | Bumps Kubo service image to v0.40.0 for load tests. |
| .github/workflows/e2e.yml | Bumps Kubo service image to v0.40.0 for E2E workflow. |
| .github/workflows/deploy-staging.yml | Points staging delegated routing primary at Someguy with fallback to delegated-ipfs.dev. |
| .github/workflows/ci.yml | Simplifies job gating and bumps Kubo service image to v0.40.0 across CI jobs. |
Comments suppressed due to low confidence (2)
apps/api/src/ipns/delegated-routing.client.ts:140
- If all retry attempts return HTTP 429,
lastErroris never set, so the final error log/exception path loses the actual failure reason (it will log an undefined message). Track the 429 case as an error (e.g., setlastErrorwhen rate-limited, especially on the last attempt) so the final failure message is informative.
// Handle rate limiting
if (status === 429) {
if (attempt < this.maxRetries - 1) {
const delayMs = this.getRetryDelayMs(retryAfter, attempt);
this.logger.warn(`Rate limited on IPNS publish (${backend}), retrying in ${delayMs}ms`);
await this.delay(delayMs);
}
continue;
}
apps/api/src/ipns/delegated-routing.client.ts:248
- In the 429 branch for resolve,
lastErroris never populated. If all retries hit rate limiting, the final error path won’t include the real reason. SetlastError(and optionally record a distinct outcome) when rate-limited so persistent 429 failures produce actionable logs/metrics.
// Handle rate limiting
if (status === 429) {
if (attempt < this.maxRetries - 1) {
const delayMs = this.getRetryDelayMs(retryAfter, attempt);
this.logger.warn(`Rate limited on IPNS resolve (${backend}), retrying in ${delayMs}ms`);
await this.delay(delayMs);
}
continue;
}
Prevents invalid Prometheus label values from being emitted. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: b7c371d3f753
Summary
standardDHT mode instead ofaccelerated, and resource limits too tight (0.5 CPU / 768MB / 512MB libp2p)http://someguy:8190instead ofhttps://delegated-ipfs.devVerification
Direct endpoint testing (someguy on Docker host):
GET /routing/v1/ipns/<key>— 200 OK in 0.53s (was hanging indefinitely)PUT /routing/v1/ipns/<key>— 200 OK in 0.12s (was hanging indefinitely)SDK E2E tests: 83/83 pass with someguy as routing backend
Load test comparison (5 clients, IPNS publish storm):
Someguy has ~20% higher median latency (single node vs fleet) but tighter p99 tail latency. The latency gap will shrink as the DHT routing table warms over time.
Config changes vs previous (broken) deployment
standardacceleratedTest plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Chores
Documentation