desktop reads everything by itself: one background read scheduler (4 per store, starts spaced per account, App Store Connect X-Rate-Limit slows it below 20 % and pauses at 100 left, backoff with jitter on 429 / RESOURCE_EXHAUSTED, visible app first, one read per key), per-method TTLs over the saved reads, Settings auto-read (on) and interval (15 min, paused while hidden), Refresh all, a refresh icon and 'read 3 min ago' / 'couldn't refresh' per card, writes invalidate, status line with progress and quota; quota reaches the window through ToolResult.quota (cli/lib/quota.ts); Health top issues open with versions, sample stack (health --issue / --signature, read health_issue), Open in Play Console, Copy for AI and likely-cause hints (cli/lib/crash-hints.ts); tests/scheduler.test.ts, tests/quota-crash-hints.test.ts, boot check auto-read case
This commit is contained in:
parent
89256f1e80
commit
0fb4ce0001
46 changed files with 1531 additions and 141 deletions
|
|
@ -251,6 +251,12 @@ pub struct RefreshSettings {
|
|||
pub parallel: u8,
|
||||
/// Read app icons from the stores when importing (an extra request per app).
|
||||
pub icons: bool,
|
||||
/// Background reading of every app (status, releases, catalog, prices, listings, TestFlight, health, reviews,
|
||||
/// analytics, checks): on start, when the window shows again and every `every_minutes` while it is open.
|
||||
pub auto_read: bool,
|
||||
/// Minutes between background passes while the window is visible (only reads past their TTL run); 0 = only on
|
||||
/// start and when the window shows again.
|
||||
pub every_minutes: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
|
@ -282,7 +288,7 @@ pub struct Settings {
|
|||
// build that lacks a newer setting keeps the rest.
|
||||
impl Default for RefreshSettings {
|
||||
fn default() -> RefreshSettings {
|
||||
RefreshSettings { auto_minutes: 0, on_launch: false, parallel: 4, icons: true }
|
||||
RefreshSettings { auto_minutes: 0, on_launch: false, parallel: 4, icons: true, auto_read: true, every_minutes: 15 }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -306,11 +312,15 @@ impl Default for Settings {
|
|||
|
||||
pub const AUTO_MINUTES: &[u32] = &[0, 15, 30, 60, 180, 720];
|
||||
pub const KEEP_DAYS: &[u32] = &[0, 7, 30, 90, 365];
|
||||
pub const EVERY_MINUTES: &[u32] = &[0, 5, 15, 30, 60];
|
||||
|
||||
pub fn check_settings(s: &Settings) -> Result<(), String> {
|
||||
if !AUTO_MINUTES.contains(&s.refresh.auto_minutes) {
|
||||
return Err("refresh: 0 (off), 15, 30, 60, 180 or 720 minutes".into());
|
||||
}
|
||||
if !EVERY_MINUTES.contains(&s.refresh.every_minutes) {
|
||||
return Err("background reading: 0 (only on start), 5, 15, 30 or 60 minutes".into());
|
||||
}
|
||||
if !(1..=8).contains(&s.refresh.parallel) {
|
||||
return Err("parallel reads: 1 to 8".into());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,15 @@ fn settings_have_safe_defaults_and_bounds() {
|
|||
s = d.clone();
|
||||
s.refresh.auto_minutes = 1;
|
||||
assert!(check_settings(&s).is_err(), "no tight polling of the store APIs");
|
||||
assert_eq!((d.refresh.auto_read, d.refresh.every_minutes), (true, 15), "background reading is on by default, every 15 minutes");
|
||||
s = d.clone();
|
||||
s.refresh.every_minutes = 1;
|
||||
assert!(check_settings(&s).is_err(), "no background pass more often than every 5 minutes");
|
||||
s = d.clone();
|
||||
s.refresh.every_minutes = 0;
|
||||
assert!(check_settings(&s).is_ok());
|
||||
let old: Settings = serde_json::from_value(serde_json::json!({ "refresh": { "autoMinutes": 15 } })).unwrap();
|
||||
assert_eq!((old.refresh.auto_read, old.refresh.every_minutes, old.refresh.auto_minutes), (true, 15, 15), "an older settings file gets the new defaults");
|
||||
s = d.clone();
|
||||
s.cache.keep_days = 3;
|
||||
assert!(check_settings(&s).is_err());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue