Trending Now 1.1.5
A SerpAPI source that fetched fine all afternoon began timing out overnight:
cURL error 28: Operation timed out after 5001 milliseconds with 0 bytes received
Nothing had broken. http_timeout defaults to 5 seconds and SerpAPI's endpoint does a live scrape whose latency varies. Three gaps turned a tunable-too-low into an outage nobody saw coming, and this release closes them.
Added
- Per-source HTTP timeout. Each source row takes its own
timeout, overriding the global. A slow news provider can have 30 seconds without an owned site waiting 30 seconds to fail. Blank or0inherits the global. - Attempt history. The last 20 fetches per source, with
p50,maxand the timeout in force shown together on the Sources tab. Latency drifting from 2s toward the ceiling is now a number you can see before it becomes a failure. - Ingest now. Retries one source from the admin — writes, rebuilds the list and purges caches, unlike Test fetch which deliberately writes nothing. No WP-CLI required. It ignores the failure backoff, because that is exactly when you would press it.
- Failure logs now carry
duration_msand the timeout in force, so a timeout explains itself instead of naming a number with no context.
Changed
max_age_hoursnow bounds/trending/as well as the widget, and defaults to 72. It previously defaulted to0— no cutoff — and applied only to widget selection, so the archive listed the entire 90-day retained set. An article four days old left the widget yesterday and sat on the archive for another twelve weeks. Rows outside the window stay in the table for deduplication until retention prunes them.exposure_floor_daysdefaults to 2, down from 3. The floor counts from when an item was first shown and the cutoff from when it was published, so an equal pair is cut short by any ingest lag. The Settings mismatch warning now fires when the two meet, not only when the floor exceeds the cutoff.
Upgrading: stored settings win over defaults, so an existing install keeps its current values. Check Settings → Maximum age if you want the new 72-hour window.
Fixed
http_timeoutnever applied torsssources at all.fetch_feed()builds its own SimplePie instance that WordPress never wires the timeout to, so every RSS source sat on SimplePie's default regardless of the setting.- A single-source retry no longer suppresses the next full cycle.
finalize()stampsadvtn_last_ingest, which gates the due-check, the 30-hour stale banner and thelast_ingestvalue external monitoring alerts on. Refreshing one source stamped it, deferring every other source's scheduled run by up toingest_interval_hours— making the button you press because a source is failing the thing that hid ingestion having stopped. Fixed for both the admin button andwp trending-now ingest --sync --source=<id>.