perf: replace trivial async implementations with ready - #655
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Cache::from_config now eagerly performs work at call time via ready(...), which changes the laziness/side-effect timing compared to the prior async fn behavior.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR refactors several trivial async fn implementations into synchronous functions that return immediately-ready futures (or poll_fn where needed), with the goal of removing unused_async_trait_impl suppressions and reducing async state-machine overhead across the Cot workspace.
Changes:
- Replaced trivial
asynctrait method impls withfn ... -> impl Future<...>returningcore::future::ready(...)in multiple extractors/handlers. - Used
core::future::poll_fn(...)for cases whereready(...)would impose additionalSendconstraints or where side effects should remain lazy (e.g.,Path,UrlQuery, console email transport). - Updated
cot-macrosderive output to generate a non-asyncready future for emptyFromRequestHeadstructs.
File summaries
| File | Description |
|---|---|
| cot/tests/from_request.rs | Updates a test extractor impl to return an immediately-ready future instead of async fn. |
| cot/src/router.rs | Updates a test RequestHandler impl to return a ready future and removes the clippy suppression. |
| cot/src/request/extractors.rs | Converts several built-in extractor impls to return ready futures instead of trivial async. |
| cot/src/project.rs | Refactors bootstrapper cache setup/boot APIs to return futures without trivial async fn wrappers. |
| cot/src/error/handler.rs | Converts error extractors to return ready futures rather than trivial async fn. |
| cot/src/email/transport/console.rs | Converts console transport send to use poll_fn to keep stdout side effects lazy. |
| cot/src/db/impl_postgres.rs | Replaces a trivial async init with a ready future and updates clippy expectations accordingly. |
| cot/src/db/impl_mysql.rs | Replaces a trivial async init with a ready future and updates clippy expectations accordingly. |
| cot/src/cache.rs | Converts Cache::from_config to return a ready future (now eager at call time). |
| cot/src/admin.rs | Converts AdminModelManagers extractor impl to return a ready future. |
| cot-macros/src/from_request.rs | Emits a ready-future implementation for empty structs derived with FromRequestHead. |
| cot-core/src/request/extractors.rs | Refactors core extractors to ready futures, using poll_fn for Path/UrlQuery to avoid extra Send constraints. |
Review details
- Files reviewed: 12/12 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Defer cache store selection until the returned future is polled, matching the behavior of the previous async function.
|
I found and fixed one more laziness regression during a follow-up audit. |
Replaces #654, which GitHub closed automatically when its head fork was accidentally deleted. This branch restores the exact reviewed commit.
Related issue or discussion
Fixes #651
Description
Replaces trivial
asyncimplementations with regular functions returning immediately-ready futures, removing theunused_async_trait_implsuppressions from production code and generated empty extractors.PathandUrlQueryusepoll_fnrather thanready: storing their result inReadywould add aSendrequirement to the deserialized output and narrow the existing generic API. The console transport also usespoll_fnso its stdout side effects remain lazy. Each computation still completes on the first poll without an async state machine.Type of change
Checklist
just test-all) — the full non-ignored workspace and doctest suite passes; ignored service tests could not start because local port 5432 is occupiedjust clippy)cargo fmt)Commands run
cargo test --workspace --all-featurescargo clippy --workspace --all-targets --all-features -- -D warningscargo fmt --check