makepad/libs/asset/client/examples/thumb_audit.rs
Admin 69385ed1be libs/asset: batch publish in one transaction and its route with the hostile cases, hardware sha256 proved against the oracle, classic worlds stop being mirror images, sounds and sprites publish a picture, an interrupted model install can never load broken, ActorDef::scaled, and the asset-ai chat tells the truth
Squashed from work; the fine-grained history is under tag archive/work-2026-08-26:
- vj: the thumbnail pipeline becomes one honest machine, and effects go livecodable
- repo: context_ladder scratch bin stays local, not shipped
- vj: thumbnails become mp4 — hardware-coded sheets at measured-4K cells, and the bake stops racing the GPU
- store: the ceremony dies — batch publish, one transaction, and the engine stops re-reading its own log
- vj: the console grows real transports, and the deck stops lying about reverse
- models: an interrupted install can never load broken
- importer: the classic worlds stop being mirror images
- asset-ai: the chat tells the truth while it works
- sqlite: derived tables get their real names, their predicates, and all their arms
- llm: the step cost model is chosen per device — the RTX PRO 6000's measured verify curve (13.7 + 3.17·B ms) beside the 5090's; the bench warms every tail shape and times two windows
- importer: a sound and a single-tile sprite publish a picture like everything else
- asset: hardware sha256 kernels, proved against the software oracle before they run
- sim: a declared map facing becomes a body's heading through one rule
- asset: the batch publish route, with the hostile cases it has to refuse
- asset: an example that asks a live store which assets carry a thumbnail
- asset+sim: the two modules their own commits already declared
- asset: ActorDef::scaled — every linear quantity follows the map's person height — plus the place-dump and retire-stale store examples, and the game chat context stops reporting work it did not do
2026-08-26 08:49:46 +02:00

76 lines
2.9 KiB
Rust

//! Which catalog assets carry a thumbnail, and which do not — asked of a
//! LIVE server over HTTP, so it never touches a root a server is using.
//!
//! cargo run --release -p makepad-asset-client --example thumb_audit -- \
//! http://127.0.0.1:50213 http://127.0.0.1:50214 <token> [namespace]
use makepad_asset_client::{ApiEndpoints, AssetClient, CatalogQuery, ClientConfig};
fn alias(hit: &makepad_asset_client::CatalogHit) -> String {
hit.alias.as_ref().map(|a| a.to_string()).unwrap_or_else(|| "<no alias>".into())
}
fn main() {
let mut args = std::env::args().skip(1);
let control: std::net::SocketAddr = args.next().expect("control addr").parse().expect("control addr");
let data: std::net::SocketAddr = args.next().expect("data addr").parse().expect("data addr");
let token = args.next().expect("token");
let want_ns = args.next();
let mut config = ClientConfig::new(std::env::temp_dir().join("thumb-audit-cache"));
config.token = Some(token);
let endpoints = ApiEndpoints { control, data };
let mut client = AssetClient::connect(config, endpoints, None).expect("connect");
let mut query = CatalogQuery::browse(100);
query.live_only = true;
if let Some(ns) = &want_ns {
query.namespace = Some(ns.clone());
}
let page = client.catalog_search(&query, None).expect("search");
println!("hits {} (total {})", page.hits.len(), page.total);
let (mut with, mut without) = (0u32, 0u32);
let mut blanks: Vec<String> = Vec::new();
for hit in &page.hits {
let detail = match client.asset_detail(&hit.asset_id) {
Ok(d) => d,
Err(e) => {
println!("{}: detail failed: {e}", alias(hit));
continue;
}
};
let Some(head) = detail.latest_published() else {
println!("{}: no published revision", alias(hit));
continue;
};
let manifest = match client.fetch_asset_manifest(&head.revision) {
Ok(m) => m,
Err(e) => {
println!("{}: manifest failed: {e}", alias(hit));
continue;
}
};
if std::env::var("DUMP_ONE").ok().as_deref() == Some(alias(hit).as_str()) {
println!("=== {} ===\n{:#?}", alias(hit), manifest);
}
let roles: Vec<String> =
manifest.files.iter().map(|f| format!("{:?}", f.role)).collect();
match &manifest.thumbnail {
Some(_) => with += 1,
None => {
without += 1;
blanks.push(format!(
"{} kind={:?} files=[{}]",
alias(hit),
hit.kind,
roles.join(",")
));
}
}
}
println!("\nwith thumbnail: {with} WITHOUT: {without}");
for b in blanks.iter().take(60) {
println!(" BLANK {b}");
}
}