Problem
S3Storage creates its own tokio::runtime::Runtime solely to call block_on() from synchronous Storage trait methods. In the napi context, this means a redundant tokio runtime running alongside the one napi already provides.
Every S3 method enters that private runtime, does one async operation, and exits. The overhead is small per-call, but the pattern is structurally wasteful — two full runtimes (thread pools, I/O drivers, timers) in the same process.
Proposal
Make the Storage trait async. This would let S3Storage use the caller's runtime directly instead of owning its own.
Considerations
Storage is used synchronously in the CLI server (rw-server), filesystem backend (rw-storage-fs), and rw-site. All callers would need to be updated.
FsStorage is inherently synchronous — its async impl would just wrap sync I/O, which is fine.
rw-site would need to become async or use spawn_blocking at the boundary.
- Async traits are stable since Rust 1.75, so no
async-trait crate needed.
🤖 Generated with Claude Code
Problem
S3Storagecreates its owntokio::runtime::Runtimesolely to callblock_on()from synchronousStoragetrait methods. In the napi context, this means a redundant tokio runtime running alongside the one napi already provides.Every S3 method enters that private runtime, does one async operation, and exits. The overhead is small per-call, but the pattern is structurally wasteful — two full runtimes (thread pools, I/O drivers, timers) in the same process.
Proposal
Make the
Storagetrait async. This would letS3Storageuse the caller's runtime directly instead of owning its own.Considerations
Storageis used synchronously in the CLI server (rw-server), filesystem backend (rw-storage-fs), andrw-site. All callers would need to be updated.FsStorageis inherently synchronous — its async impl would just wrap sync I/O, which is fine.rw-sitewould need to become async or usespawn_blockingat the boundary.async-traitcrate needed.🤖 Generated with Claude Code