1
0
forked from GRIN/grim

nostr: raise news cap to 18 so English variant survives multi-language batches

A single news post now ships as nine per-`d` language variants and the
publisher emits English first, giving it the oldest `created_at` in the
batch. With the store capped at 8 events across all d-tags, the English
event was always the 9th-newest and got evicted — English readers saw no
news. The catch-up/subscription filter also capped fetches at 4, so fresh
installs only ever received the newest four events.

Raise NEWS_CAP from 8 to 18 (two full nine-language posts) and bump the
news filter limit from 4 to 18 to match. Selection logic is unchanged.
Extend the reconcile_news test with a nine-variant batch that proves the
untagged English event survives under the real cap.
This commit is contained in:
2ro
2026-07-07 17:05:24 -04:00
parent 567c054fe6
commit debad91e29
2 changed files with 34 additions and 4 deletions
+1 -1
View File
@@ -1387,7 +1387,7 @@ async fn run_service(svc: Arc<NostrService>, wallet: Wallet) {
Filter::new()
.kind(Kind::LongFormTextNote)
.author(pk)
.limit(4)
.limit(18)
});
if let Ok(events) = client
+33 -3
View File
@@ -30,8 +30,10 @@ use crate::nostr::types::*;
const PROCESSED_TTL_SECS: i64 = 30 * 86_400;
/// Cap on stored news posts (newest kept, older pruned) — the panel only ever
/// shows the latest, so this is just a small archive bound.
const NEWS_CAP: usize = 8;
/// shows the latest, so this is just a small archive bound. Sized for two full
/// nine-language posts so the oldest-`created_at` variant (English is published
/// first) is not evicted before its readers see it.
const NEWS_CAP: usize = 18;
/// Nostr metadata archive for a wallet.
pub struct NostrStore {
@@ -385,12 +387,16 @@ mod tests {
use super::*;
fn item(d: &str, created_at: i64) -> NewsItem {
item_lang(d, created_at, None)
}
fn item_lang(d: &str, created_at: i64, lang: Option<&str>) -> NewsItem {
NewsItem {
d: d.to_string(),
created_at,
title: format!("t{created_at}"),
summary: String::new(),
lang: None,
lang: lang.map(str::to_string),
published_at: None,
}
}
@@ -418,4 +424,28 @@ mod tests {
assert_eq!(all[0].created_at, 9);
assert_eq!(all[2].created_at, 7);
}
#[test]
fn nine_language_batch_retains_english_under_news_cap() {
// A single post now ships as nine per-`d` language variants. The
// publisher emits English FIRST, so the untagged (lang == None) English
// event carries the OLDEST `created_at` in the batch. Under the real
// `NEWS_CAP` the whole batch must survive so English readers see it.
let langs = ["es", "fr", "de", "it", "pt", "ja", "zh", "ko"];
let mut all = vec![];
// English published first → oldest created_at, no lang tag.
all = reconcile_news(all, item_lang("post-en", 100, None), NEWS_CAP);
for (i, code) in langs.iter().enumerate() {
all = reconcile_news(
all,
item_lang(&format!("post-{code}"), 101 + i as i64, Some(code)),
NEWS_CAP,
);
}
assert_eq!(all.len(), 9);
assert!(
all.iter().any(|n| n.d == "post-en" && n.lang.is_none()),
"untagged English variant must survive the cap"
);
}
}