feat(changelogs): rolling 12-month window for updates stream#750
Conversation
OS release events and app release events older than 365 days are excluded from the Updates Stream. Pinned "Current Versions" cards are unaffected — they always show the latest release regardless of age. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces a 12-month rolling window for the updates stream by filtering OS and app events. The review feedback identifies a hydration mismatch risk in the SSR/SSG environment caused by using Date.now() and recommends using a stable reference time from the metadata. Additionally, the reviewer notes that filtering the primary allEvents list may cause unintended side effects on global statistics and sidebar filters, suggesting the filter be applied specifically to the stream instead.
| }; | ||
|
|
||
| /** Rolling window for the Updates Stream — entries older than this are not shown. */ | ||
| const ROLLING_WINDOW_MS = 365 * 24 * 60 * 60 * 1000; |
There was a problem hiding this comment.
Using Date.now() for filtering logic in a React SSR/SSG environment like Docusaurus leads to hydration mismatches. The value of Date.now() during the server build will differ from the value when the client hydrates, potentially causing inconsistent rendering of the updates stream.
It is recommended to define a stable reference time at the module level, preferably derived from the data's own metadata (e.g., firehoseData.metadata.generatedAt), to ensure consistent results across server and client.
| const ROLLING_WINDOW_MS = 365 * 24 * 60 * 60 * 1000; | |
| const ROLLING_WINDOW_MS = 365 * 24 * 60 * 60 * 1000; | |
| const STREAM_CUTOFF_MS = (firehoseData.metadata?.generatedAt ? new Date(firehoseData.metadata.generatedAt).getTime() : Date.now()) - ROLLING_WINDOW_MS; |
References
- In React SSR environments, ensure consistent date and time values between server and client to avoid hydration mismatches.
|
|
||
| // Rolling 12-month window for the stream — pinned cards (PINNED_OS_EVENTS) are unaffected. | ||
| const ALL_OS_STREAM_EVENTS: OsReleaseEvent[] = (() => { | ||
| const cutoff = Date.now() - ROLLING_WINDOW_MS; |
There was a problem hiding this comment.
Use the stable STREAM_CUTOFF_MS constant here to avoid hydration mismatches and ensure consistency with other filtered streams.
| const cutoff = Date.now() - ROLLING_WINDOW_MS; | |
| const cutoff = STREAM_CUTOFF_MS; |
References
- In React SSR environments, ensure consistent date and time values between server and client to avoid hydration mismatches.
| const allEvents: FlatRelease[] = useMemo(() => { | ||
| const cutoff = Date.now() - ROLLING_WINDOW_MS; | ||
| return flattenReleases(firehoseData.apps ?? []).filter((e) => e.dateMs > cutoff); | ||
| }, []); |
There was a problem hiding this comment.
Filtering allEvents by date here has a significant side effect: it excludes older apps from the Statistics panel ("Total apps") and the Filters sidebar, even when no filters are active. This may be misleading if the user expects to see the total catalog size. If the intent was only to filter the "Updates Stream" feed, consider keeping allEvents as the full list and applying the date filter only when generating the unifiedStream.
Additionally, use the stable STREAM_CUTOFF_MS to prevent hydration mismatches.
const allEvents: FlatRelease[] = useMemo(() => {
return flattenReleases(firehoseData.apps ?? []).filter((e) => e.dateMs > STREAM_CUTOFF_MS);
}, []);
References
- In React SSR environments, ensure consistent date and time values between server and client to avoid hydration mismatches.
OS release events and app release events older than 365 days are excluded from the Updates Stream. Pinned "Current Versions" cards are unaffected — they always show the latest release regardless of age.