- bootstrap: TracingLayer from mytheclipse-tracing (composed with scraper env filter), RuntimeConfig::auto() thread logging, init job queue + cron. - proxy_fetch: leader task via ::mytheclipse::spawn_io, gzip decompression offloaded to ::mytheclipse::compute (sized rayon pool, panic-isolated), bounded by new async fetch limiter (tokio Semaphore bridge). - queue: new infrastructure/queue module over mytheclipse-queue (InMemoryQueue + WorkerPool + BackpressureEnforcer) for repair jobs. - scheduler: new infrastructure/scheduler.rs using mytheclipse::cron for the daily 02:00 UTC image-cache cleanup. - deps: add mytheclipse-queue + mytheclipse-tracing path deps; mytheclipse -> full feature; rayon 1.12; keep path deps for unpublished crates. - tests: infra_round2 runtime smoke tests (compute panic isolation, spawn_io, backpressure admission, cron parse, queue roundtrip). - Fix: local cache::mytheclipse bridge module shadowed the mytheclipse crate name; use leading :: at spawn_io/compute call sites.
6.5 KiB
Spec Round 2 — Scraper → mytheclipse Deep Infra Migration (thread/async/queue)
Date: 2026-08-30 Repo: /home/code/scraper (scraper-service) Library: /home/code/mytheclipse (mytheclipse crates v1.20+ local path)
Scope
Round 1 (committed c7ffd29) migrated retry, redis cache, event bus, ratelimit,
config. Round 2 targets the remaining runtime/concurrency/queue/observability
infrastructure — the parts the user explicitly asked to push "sampai tingkat
thread, async, queue dan lainnya".
1. Runtime thread sizing — mytheclipse::runtime_auto::RuntimeConfig
Current: bootstrap logs std::thread::available_parallelism() manually;
tokio runtime is #[tokio::main(flavor = "multi_thread")] with default
worker counts.
Change:
- Add
mytheclipse = { features = ["lifecycle", ...] }(addlifecyclefeature). - In
bootstrap/mod.rs, computeRuntimeConfig::auto()once at build, log worker/blocking/compute/io counts, and keep the tokio runtime default (already multi_thread). Optionally passworker_threadsvia a#[tokio::main]alternative — but sincemainuses the macro, we keep the macro form and simply surface the auto-derived counts in logs + store them inAppStatefor future pool sizing. - Replace the manual
available_parallelism()log withRuntimeConfig::auto().
2. Async I/O + background task spawns — mytheclipse::spawn_io / spawn_bg
Current:
proxy_fetch.rs:114usestokio::spawn(...)for the request-coalescing leader- 30+
tokio::task::spawn_blocking(...)sites across otakudesu.rs, anime2 use_cases, komik use_cases, proxy_fetch (gzip decompress) - No bounded background task pool
Change:
proxy_fetch.rsleader task →mytheclipse::spawn_io(...)(same semantics, adds tracing span instrumentation). No behavior change.- Add
mytheclipse = { features = ["io", "bg"] }. - The
spawn_blockingsites stay as-is this round (they're CPU-bound parser calls andspawn_blockingis the correct tokio primitive; mytheclipsecompute()would replace them but that's a 2k+ LOC parser sweep — deferred as before). Document this in the spec's residual section. - Add
bgfeature and expose a bounded background executor viamytheclipse::spawn_bgfor the cache-write / relay-fallback background tasks that currently fire-and-forget (if any are found in use_cases).
3. Worker queue — mytheclipse-queue InMemoryQueue + WorkerPool
Current: no queue abstraction; the only "background" work is the cache
batch writes (cache_image_urls_batch_lazy in the proxy image-cache path —
but proxy routes were removed, so that path may be dead). Event bus has no
worker pool.
Change:
- Add
mytheclipse-queue = { path = ..., features = ["in-memory"] }. - Wire a small application-level
JobQueueinsrc/infrastructure/queue/:InMemoryQueue+WorkerPoolconsuming ascrape:repairtopic for background image-cache repair/re-sync jobs.- Graceful shutdown: on app shutdown, stop workers.
- This is additive infra (no existing behavior replaced), so it's low-risk and demonstrates the queue crate in the scraper.
- Actually use it: the
image_cacherepair path (cache cleanup at 2 AM) is currently absent (scheduler dir missing). Introduce a smallsrc/infrastructure/scheduler.rsusingmytheclipse::cron(lifecycle feature) ORtokio::time::intervalfor the daily 02:00 cleanup that enqueues repair jobs onto the queue. Given the original CLAUDE.md mentions "scheduler — Cron jobs (daily cache cleanup at 2 AM)", recreating it on mytheclipse-queue is a faithful, additive migration.
4. Backpressure / concurrency — mytheclipse::ConcurrencyLimiter / BackpressureQueue
Current: proxy_fetch has request coalescing via DashMap + broadcast (kept — it's application logic, not infra). No app-level backpressure.
Change:
- Add
mytheclipse = { features = ["traffic"] }(already enabled for RateLimiter in round 1). - Wrap the fetch-with-proxy path with a
ConcurrencyLimiter(bound concurrent outbound scrapes, default e.g. 16) so burst traffic can't saturate the upstream. This is a real, central hot path (every scrape goes through it). - Keep the RateLimiter middleware (round 1) for inbound.
5. Observability — mytheclipse-tracing TracingLayer (+ keep OTel metrics)
Current: tracing_subscriber::fmt().with_env_filter(...) in bootstrap;
opentelemetry metrics in observability/metrics.rs (kept — mytheclipse-tracing
has no metrics exporter, round-1 decision).
Change:
- Add
mytheclipse-tracing = { path = ..., features = ["env"] }. - Replace
tracing_subscriber::fmt()in bootstrap withmytheclipse_tracing::TracingLayer::install()(same RUST_LOG env-filter semantics, adds tracing span layer compatibility). - Keep
init_otel_metrics()untouched (OTel exporter stays).
6. HTTP client — mytheclipse-http HttpClient (optional, re-evaluate)
Round 1 deferred this because mytheclipse-http's client "loses header/UA/status
control". Re-check: mytheclipse-http::client::HttpClient — if it exposes
with_timeout, get_text, get_json, post_json, and header injection,
use it for the non-critical relay fetches (fetch_via_relays). If not
header-capable, skip (kept as residual).
Files touched
- Cargo.toml (features: add lifecycle, io, bg; add mytheclipse-queue, mytheclipse-tracing)
- src/bootstrap/mod.rs (RuntimeConfig log + TracingLayer + scheduler start)
- src/infrastructure/scraping/proxy_fetch.rs (spawn_io + ConcurrencyLimiter)
- src/infrastructure/queue/mod.rs (NEW — InMemoryQueue + WorkerPool + repair topic)
- src/infrastructure/scheduler.rs (NEW — daily 02:00 cleanup → queue enqueue)
- src/infrastructure/cache/mytheclipse.rs (maybe wire limiter through cache path)
- src/presentation/state.rs (add queue handle / limiter if needed)
Verification
cargo check— green after each batchcargo test— all passcargo build --release— greencargo fmt --checkon touched files- Runtime smoke: boot server, hit
/health, confirm logs show RuntimeConfig and scheduler started; queue jobs process (test harness)
Residual (deliberately deferred)
spawn_blocking→mytheclipse::compute()sweep (2k+ LOC parser files)- OTel metrics → mytheclipse-tracing (no metrics exporter in library yet)
- rayon in komik_parser
- mytheclipse-http client if header control is insufficient
Commit
Single commit at end: refactor: migrate runtime/queue/concurrency infra to mytheclipse (round 2)