a deploy lays out the git read maps instead of the first write after it
Signed-off-by: dawn <90008@klbr.net>
352 unmodified linesExpand all35335435535635735835936036136236336436536636736836937037137237337437537637737837988 unmodified lines352 unmodified linesExpand all timerConfig.OnUnitActiveSec = "5min"; timerConfig.OnBootSec = "5min"; };
# a new binary may serve from files the old one didn't write, lay them out now # instead of in the first write after the switch systemd.services.knot-static-prepare = { description = "lay out what a new knot-static serves from"; wantedBy = [ "multi-user.target" ]; restartTriggers = [ cfg.package ]; unitConfig.ConditionPathExists = cfg.environmentFile; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; User = cfg.user; Group = cfg.group; EnvironmentFile = cfg.environmentFile; ExecStart = "${binPath} --config ${configPath} prepare"; Nice = 19; IOSchedulingClass = "idle"; }; };
# rolls each hosted repo's pushed packs and loose objects into one, keeping # the big pack the exports hardlink systemd.services.knot-static-repack = { description = "repack knot-static's hosted repos";88 unmodified lines113 unmodified linesExpand all114115116117118119120121122123124305 unmodified linesExpand all113 unmodified linesExpand all /// when the activation happened, in unix seconds #[arg(long)] at: u64, }, /// after a deploy, lay out what this binary serves from before a write has to #[command(hide = true)] Prepare, /// ask configured crawlers to crawl this knot now Crawl, /// run repack, gc or prune on one or all hosted repos under the build lock Maintenance {305 unmodified linesExpand all205 unmodified linesExpand all20620720820921021121221321421521621721893 unmodified lines205 unmodified linesExpand all generation, previous, at, } => activate::after_activation(&config, &generation, previous.as_deref(), at), Command::Prepare => { let written = git_xrpc::prepare(&config.output_root)?; eprintln!("prepared the git read maps of {written} repos"); Ok(()) } Command::Crawl => { crawl::request_all(&config).await; Ok(()) }93 unmodified lines215 unmodified linesExpand all21621721821922022022122222322427 unmodified lines25225325425525625625725825926026126226226326426526626726826927027127226826927027127211 unmodified lines284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328476 unmodified linesExpand all215 unmodified linesExpand all if let Some(sealed) = read(&key).filter(|sealed| holds(&dir, &sealed.files) && sealed.paths.held(&dir)) { let unlaid = paths::split(&sealed.rows, paths::folds(&dir)?).1; write_maps(input, &maps_root.join(&key), &sealed, &unlaid)?; write_maps(&input.did, &maps_root.join(&key), &sealed, &unlaid)?; if last_key.as_deref() != Some(key.as_str()) { atomic_write(&last, key.as_bytes())?; } return Ok(sealed_repo(&key, sealed.paths.seal));27 unmodified lines paths: laid, memo, }; input.served.publish_file(SEAL_KIND, &key, &sealed)?; write_maps(input, &maps_root.join(&key), &sealed, &unlaid)?; write_maps(&input.did, &maps_root.join(&key), &sealed, &unlaid)?; atomic_write(&last, key.as_bytes())?; Ok(sealed_repo(&key, sealed.paths.seal))}
/// the carry file goes last, a seal without one gets its fragments written againfn write_maps(input: &RepoInput, dir: &Path, sealed: &Sealed, unlaid: &Rows) -> anyhow::Result<()> {fn write_maps(did: &RepoDid, dir: &Path, sealed: &Sealed, unlaid: &Rows) -> anyhow::Result<()> { if dir.join(CARRY_FILE).is_file() { return Ok(()); } std::fs::create_dir_all(dir)?; let mut maps = Maps::default(); maps.add( &crate::plan::repo_token(input.did.as_str()), &sealed.rows, unlaid, ); maps.add(&crate::plan::repo_token(did.as_str()), &sealed.rows, unlaid); for (_, variable) in sources() { let rows = Block::file().entries(maps.take(variable)); atomic_write(&dir.join(fragment(variable)), rows.to_string().as_bytes())?; }11 unmodified lines &serde_json::to_vec(&carry)?, )?)}
/// writes the map fragments of every active repo's seal, which the first write after a deploy/// would otherwise do for every repo it carriespub fn prepare(output_root: &Path) -> anyhow::Result<usize> { let Some(active) = crate::plan::load_active_generation(output_root)? else { return Ok(0); }; let mut written = 0; for repo in &active.manifest.repos { let did = RepoDid::new(repo.repo_did.as_str())?; let repo_dir = output_root .join("repos") .join(crate::plan::repo_key(did.as_str())); if prepare_repo(&RepoStore::served(&repo_dir), &did) .with_context(|| format!("prepare git reads of {did}"))? { written += 1; } } Ok(written)}
fn prepare_repo(served: &RepoStore, did: &RepoDid) -> anyhow::Result<bool> { let Some(key) = last_seal(served) else { return Ok(false); }; let dir = served.kind_dir(MAPS_KIND).join(&key); if dir.join(CARRY_FILE).is_file() { return Ok(false); } let Some(sealed) = served.read_file::<Sealed>(SEAL_KIND, &key) else { return Ok(false); }; let unlaid = paths::split(&sealed.rows, paths::folds(&served.pool(POOL_KIND))?).1; write_maps(did, &dir, &sealed, &unlaid)?; Ok(true)}
fn fragment(variable: &str) -> String { format!("{}.conf", variable.trim_start_matches('$'))}
476 unmodified linesExpand all832 unmodified linesExpand all833834835836837838839840841842843844845846847848849850851852853854855856857858859860861832 unmodified linesExpand all }; assert!(blame("was").is_none()); assert!(blame("a.txt").is_some());}
#[test]fn prepare_lays_out_the_maps_a_seal_from_an_older_binary_lacks() { let fixture = fixture(); let sealed = seal(&fixture.input(Vec::new())).unwrap(); let written: Vec<(PathBuf, Vec<u8>)> = std::fs::read_dir(&sealed.maps) .unwrap() .map(|entry| { let path = entry.unwrap().path(); let bytes = std::fs::read(&path).unwrap(); (path, bytes) }) .collect(); std::fs::remove_dir_all(&sealed.maps).unwrap(); let served = fixture.input(Vec::new()).served; let did = RepoDid::new(DID).unwrap(); assert!(super::prepare_repo(&served, &did).unwrap()); for (path, bytes) in &written { assert_eq!(&std::fs::read(path).unwrap(), bytes, "{}", path.display()); } assert!( !super::prepare_repo(&served, &did).unwrap(), "a second run writes nothing" );}