Slight disagreement with the crowd: the channel design gets much more attractive if your writes ever need to be conditional on a read, like 'increment unless over the limit'. With a lock you either take a write lock for every check or you race. Rate limiting is exactly the kind of thing that tends to grow that requirement in month three.
Nadia Feld
@grepwitch
I spend most of my day in a terminal untangling other people's shell scripts. Ask me about awk, sed, and why your cron job runs at a different time than you think.
Also worth diffing the rendered HTML against a copy from the Wayback Machine on a date before the drop. 'We didn't touch the page' is true surprisingly often at the CMS level and false at the template level.
The unwrap bugs me slightly. if let Some(last) = events.last_mut() { ... } else { events.push(item) } doesn't work here because of the else branch, so an alternative is to match on should_merge and use events.last_mut().expect("checked above") so the invariant is at least documented.
Another shape that fits well when the decision needs more than a bool: pull whatever you need out of the last element as owned copies of the small fields, not the whole struct. If the merge decision depends on a timestamp and an id, copy those two, drop the borrow and carry on. You said the struct is 200 bytes but the decision probably needs 16.
Worth checking whether the new platform serves those pages client side. Fetch one with curl -s <url> | wc -c and then look at what's actually in the HTML. I've seen platforms where the indexed pages happen to be prerendered and the rest are an empty shell with a JS bundle, and Search Console's inspection tool renders it fine so you never notice.
Reading it bottom to top is genuinely the trick with these. The last few lines name your type and your await, everything above is the machinery explaining why it cares.
If you go with 8, redirect each old URL to the specific section anchor on the new page rather than dumping all 40 at the same top-level URL. Takes an extra hour and keeps the mapping meaningful if you ever need to unpick it.
Box<dyn Iterator + '_> is a perfectly reasonable escape hatch when you have several branches returning different iterator types, and one heap allocation for an iterator you'll poll thousands of times is noise. I wouldn't feel like you gave up, I'd feel like you shipped.
Arena patterns aren't dead in Rust, they just become indices into a Vec instead of pointers. Once you make that swap a lot of C-shaped designs work fine.
Two months, and the concept was that a reference is a borrow of a specific thing for a specific window, not a pointer that happens to be safe. Once I read every & as 'nobody may move or free this until I'm done', the rules stopped feeling arbitrary. Also, and I mean this kindly, coming from C is sometimes harder than coming from Python because you have a working mental model that is nearly right.