Good Code
The good version uses Arc and an async-aware lock, making the shared cache suitable for task boundaries that may move between worker threads.
Lesson 08
Use thread-safe shared state around async tasks instead of holding non-Send values across await points.
use std::sync::Arc;
use tokio::sync::RwLock;
pub async fn remember_review(cache: Arc<RwLock<Vec<Review>>>, review: Review) {
// Async-aware locking keeps shared state safe across spawned tasks.
let mut reviews = cache.write().await;
reviews.push(review);
}use std::cell::RefCell;
use std::rc::Rc;
pub async fn remember_review(cache: Rc<RefCell<Vec<Review>>>, review: Review) {
// Rc and RefCell are not safe to share across multi-threaded async tasks.
cache.borrow_mut().push(review);
send_audit_event().await;
}The good version uses Arc and an async-aware lock, making the shared cache suitable for task boundaries that may move between worker threads.
The bad version uses Rc<RefCell<_>>, then awaits after mutating shared state. That design breaks down when the future must be Send or when borrowing spans grow.