~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

Diffs are read four at a time, highlighted off the async threads

Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:serve/diff-bound
crates/knotless-serve/src/web.rs+21−8
@@ -3134,10 +3134,16 @@ fn row(r: diff::Row) -> DiffRowView {
}
}
/// How many diffs are read at once, git's patch and blobs and the
/// highlighting of their rows: the rest wait their turn. A crawler walking
/// commit and pull pages asks for dozens together, which, run at once,
/// held every other request's answer up for tens of seconds.
static DIFFING: tokio::sync::Semaphore = tokio::sync::Semaphore::const_new(4);
/// What `git <verb> <rev>` prints as a patch of `paths` (all, if none),
/// read into files in the order an editor's file tree lists them, with
/// their rows as `rows` says: a file without is neither highlighted nor
/// has its blobs read.
/// has its blobs read. At most [`DIFFING`] are read at once.
async fn files(
git: &Git,
verb: &[&str],
@@ -3145,6 +3151,7 @@ async fn files(
paths: &[&str],
rows: Rows,
) -> Result<Vec<FileDiffView>> {
let _turn = DIFFING.acquire().await.expect("never closed");
let mut args = vec!["-c", "core.quotePath=false"];
args.extend(verb);
args.extend([
@@ -3172,13 +3179,19 @@ async fn files(
.filter_map(|oid| oid.as_deref())
.collect();
let texts = texts(git, &shown).await;
// Each listed, and those with their rows drawn in its place.
let mut out: Vec<FileDiffView> = parsed.iter().map(listed).collect();
let picked = parsed.into_iter().zip(with).enumerate();
for (i, (f, _)) in picked.filter(|(_, (_, with))| *with) {
out[i] = file_diff(f, &texts);
}
Ok(out)
// Each listed, and those with their rows drawn in its place, off the
// async threads: highlighting parses the whole of each side, a good
// part of a second for a long file, and on them it would hold up every
// other request, and the reading of git's output, until it was done.
let drawn = tokio::task::spawn_blocking(move || {
let mut out: Vec<FileDiffView> = parsed.iter().map(listed).collect();
let picked = parsed.into_iter().zip(with).enumerate();
for (i, (f, _)) in picked.filter(|(_, (_, with))| *with) {
out[i] = file_diff(f, &texts);
}
out
});
Ok(drawn.await.expect("drawing a diff does not panic"))
}
/// Which of `files` a pull's files page draws with their rows at once:
docs/design/serve.md+14−1
@@ -807,7 +807,10 @@ Discord's, is not held to it, as someone shared that link.
A crawler that calls itself a browser is not caught, and each request's
log line names its client (`user_agent.original`), so they can be told
apart.
apart. What its pages cost is bounded instead: the diffs of commit and
pull pages, the dearest it can ask for, are read a few at a time (see
[Highlighting and diffs](#highlighting-and-diffs)), as blames and
archives are ([Git and the object API](#git-and-the-object-api)).
Crawlers and old browsers ask for `/favicon.ico` whatever a page names
as its icon. Handed to the pages, it would be drawn as the profile of a
@@ -1621,6 +1624,16 @@ browser fetches the rest from `getCommit` with `paths`, ten at a time, as
each nears the screen. A commit that touches hundreds of files is otherwise
an answer of megabytes, read, highlighted and drawn before any of it shows.
At most four diffs are read at once, of commits, pulls and compares
together: git's patch, the blobs of the files drawn with their rows, and
their highlighting, which runs off the server's async threads. The rest
wait their turn. A crawler posing as browsers once asked for about a
hundred commit and pull diffs in a minute: sixty git processes ran at
once on the server's two cores, and highlighting on the async threads
held every other answer up behind them, a profile or a tree as much as a
commit, for seconds and up to half a minute. Now such a burst waits on
itself, and the rest of the site answers as before.
A diff shows each hunk with three lines around it; the rest of a file
changed in place is left out. A pull's, a commit's and a compare's files can
show more: the arrows in a hunk's header put back 20 lines at a time from