Pin oxygen with the Linux-scale work; read change metadata alone df15b74774ca
oxygen 397d9f98: the working-copy lock, change skeletons in history-only loads, metadata-only change reads, shared line buffers, faster graphs. Nothing on the wire changes. Where the hub only lists a change's message or dependencies (push reports, the issue chain, file history's states, Flow's check that a change is known) it now reads its metadata (Store::get_change_meta), and where it needs only the nodes a change touches (a file's history, a directory's newest changes) its skeleton: neither reads the change's text. closes #58
- Author
- Andy McCall @andymccall <[email protected]>
- When
- · 2026-09-30 00:05 UTC
- Signature
- ✔ signed by Andy McCall
- Hash
df15b74774ca5bc2a21596eef9d70be392e4517c948b8af98000f4ac48223d92- Depends on
- 18e381ea88c2 380996db84e5 38833ed78707 3d3d29fbcb00 42fa95540468 4f6925337848 6ae41081ccd3 9ff27da517fe b19606f28101 d23464c0ac60
- Depended on by
- 7c36794d3630
- In bookmarks
- api-unknown-fields cancel-landed-runs clear-waiting close-proposal-140 diffusion-pin-bookmark draft-ready image-check job-waits main oh-comment-body-file proposal-list-fast run-one-job wiki-says-so
- In tags
- v0.1.0 v0.2.0 v0.3.0 v0.3.1 v0.4.0 v0.4.1 v0.4.2 v0.5.0 v0.5.1 v0.5.2 v0.6.0 v0.6.1 v0.7.0 v0.8.0 v0.9.0 v0.9.1 v0.9.11 v0.9.15 v0.9.16 v0.9.19 v0.9.2 v0.9.20 v0.9.21 v0.9.22 v0.9.23 v0.9.24 v0.9.3 v0.9.4 v0.9.5 v0.9.6 v0.9.7 v0.9.8 v0.9.9
- Edits
- 12 atoms, 0 tree operations, 5 files
Browse the tree at this change
modified crates/hub/src/flow.rs +1 −1
| … | 72 unchanged lines |
||
| 73 | 73 | } |
|
| 74 | 74 | let h = ChangeHash::from_hex(change.trim().trim_start_matches('#')).ok_or("give the full hash of a change")?; |
|
| 75 | 75 | let repo = RepoName::new(&row.owner, &row.name).ok_or("bad repository name")?; |
|
| 76 | - | let known = app.repos.read(&repo, move |r, _| Ok(r.store().get_change(&h).is_ok())).await.map_err(|e| e.to_string())?; |
|
| 76 | + | let known = app.repos.read(&repo, move |r, _| Ok(r.store().get_change_meta(&h).is_ok())).await.map_err(|e| e.to_string())?; |
|
| 77 | 77 | if !known { |
|
| 78 | 78 | return Err(format!("no change {} in this repository", &change.trim()[..12.min(change.trim().len())])); |
|
| 79 | 79 | } |
|
| … | 591 unchanged lines |
modified crates/hub/src/protocol.rs +3 −1
| … | 199 unchanged lines |
||
| 200 | 200 | } else { |
|
| 201 | 201 | self.repos |
|
| 202 | 202 | .open(&parsed) |
|
| 203 | - | .map(|r| report.imported.iter().filter_map(|h| r.store().get_change(h).ok().map(|c| (h.to_hex(), c.message))).collect()) |
|
| 203 | + | .map(|r| { |
|
| 204 | + | report.imported.iter().filter_map(|h| r.store().get_change_meta(h).ok().map(|c| (h.to_hex(), c.message))).collect() |
|
| 205 | + | }) |
|
| 204 | 206 | .unwrap_or_default() |
|
| 205 | 207 | }; |
|
| 206 | 208 | let messages: Vec<(String, String)> = if bookmarks.contains(&row.default_bookmark) { imported.clone() } else { vec![] }; |
|
| … | 69 unchanged lines |
modified crates/hub/src/repos/view.rs +5 −4
| … | 313 unchanged lines |
||
| 314 | 314 | .state |
|
| 315 | 315 | .changes() |
|
| 316 | 316 | .filter(|(h, _)| { |
|
| 317 | + | // The skeleton says which nodes a change touches, without its text. |
|
| 317 | 318 | repo.store() |
|
| 318 | - | .get_change(h) |
|
| 319 | - | .map(|c| c.tree_ops.iter().any(|o| o.node() == node) || c.edits.iter().any(|x| x.node() == node)) |
|
| 319 | + | .get_change_lazy(h) |
|
| 320 | + | .map(|(c, _)| c.tree_ops.iter().any(|o| o.node() == node) || c.edits.iter().any(|x| x.node() == node)) |
|
| 320 | 321 | .unwrap_or(false) |
|
| 321 | 322 | }) |
|
| 322 | 323 | .map(|(h, m)| (*h, m.clone())) |
|
| … | 399 unchanged lines |
||
| 722 | 723 | // Newest change touching each node, from one pass over the log. |
|
| 723 | 724 | let mut newest: HashMap<oxy_core::ids::NodeId, (ChangeHash, u64)> = HashMap::new(); |
|
| 724 | 725 | for e in repo.log_of(state) { |
|
| 725 | - | let Ok(c) = repo.store().get_change(&e.hash) else { continue }; |
|
| 726 | + | let Ok((c, _)) = repo.store().get_change_lazy(&e.hash) else { continue }; |
|
| 726 | 727 | let when = e.change.hlc.wall_ms; |
|
| 727 | 728 | for node in c.tree_ops.iter().map(|o| o.node()).chain(c.edits.iter().map(|x| x.node())) { |
|
| 728 | 729 | newest.entry(node).or_insert((e.hash, when)); |
|
| … | 41 unchanged lines |
||
| 770 | 771 | let lines = blame_cached(repo, cache, &heads, path)?; |
|
| 771 | 772 | let mut before = HashMap::new(); |
|
| 772 | 773 | for l in &lines { |
|
| 773 | - | before.entry(l.hash).or_insert_with(|| repo.store().get_change(&l.hash).ok().and_then(|c| state_spec(&c.deps))); |
|
| 774 | + | before.entry(l.hash).or_insert_with(|| repo.store().get_change_meta(&l.hash).ok().and_then(|c| state_spec(&c.deps))); |
|
| 774 | 775 | } |
|
| 775 | 776 | Ok(Blame { file, lines, before }) |
|
| 776 | 777 | } |
|
| … | 600 unchanged lines |
modified crates/hub/src/web/chain.rs +1 −1
| … | 47 unchanged lines |
||
| 48 | 48 | .map(|hs| { |
|
| 49 | 49 | hs.iter() |
|
| 50 | 50 | .filter_map(|h| oxy_core::hash::ChangeHash::from_hex(h)) |
|
| 51 | - | .filter_map(|h| r.store().get_change(&h).ok().map(|c| c.message)) |
|
| 51 | + | .filter_map(|h| r.store().get_change_meta(&h).ok().map(|c| c.message)) |
|
| 52 | 52 | .collect() |
|
| 53 | 53 | }) |
|
| 54 | 54 | .collect()) |
|
| … | 20 unchanged lines |
replaced deps/oxygenflow +0 −0
No line changes.