Skip to content

Commit

A push says where its time went: receiving it, the rules, the secret scan and the git store's answer each have their own Server-Timing step

syntaqxcommitted Parentbee5a81Browse files
3 files+20−50/3 viewed
+5−1
287287 | `access` | Deciding whether you may fetch from or push to it |
288288 | `kept` | A free workspace's limits, and looking for a ref listing and a store credential made a moment ago |
289289 | `mint` | Only when no credential was kept: the git store making one for the request |
290−| `store` | The git store's answer; for a push, checking it for secrets first |
290+| `store` | The git store's answer to a clone or fetch |
291+| `recv` | Only for a push: receiving it from git |
292+| `rules` | Only for a push: checking it against the rules of the branches and tags it changes, and for workflow files a token may not change |
293+| `scan` | Only for a push: checking it for secrets and private email addresses |
294+| `upload` | Only for a push: handing it to the git store and its answer |
291295 | `refs` | Only for a push: recording that the repository's refs changed |
292296 | `total` | Everything g1t did |
293297 | `repos` | The same, measured where your request arrived |
+13−4
866866 default_branch: Option<&str>,
867867 limits: PushLimits,
868868 scan: impl AsyncFnOnce(&[u8]) -> Result<Option<Response>>,
869+ timing: &mut Timing,
869870 ) -> Result<Push> {
870871 let headers = Headers::new();
871872 headers.set("authorization", &format!("Bearer {}", access.token))?;
881882 let namespace = crate::store::health_namespace(&access.remote);
882883
883884 if method == Method::Post && git.endpoint == "git-receive-pack" {
884− return push(request, &url, headers, rules, limits, scan, &namespace).await;
885+ return push(request, &url, headers, rules, limits, scan, &namespace, timing).await;
885886 }
886887
887888 // A read: the ref advertisement, `ls-refs`, or a fetch of objects.
962963 }))
963964 }
964965
965−/// A receive-pack request; see [`forward`].
966+/// A receive-pack request; see [`forward`]. Its steps: `recv` (the push
967+/// read), `rules`, `scan` (push protection), `upload` (the store's answer).
966968 #[allow(clippy::too_many_arguments)]
967969 async fn push(
968970 mut request: Request,
972974 limits: PushLimits,
973975 scan: impl AsyncFnOnce(&[u8]) -> Result<Option<Response>>,
974976 namespace: &str,
977+ timing: &mut Timing,
975978 ) -> Result<Push> {
976979 let mut stream = request.stream()?;
977980 let mut head: Vec<u8> = Vec::new();
993996 }
994997 }
995998 }
999+ timing.mark("recv");
9961000 // The rules of the branches and tags it changes, first: what they
9971001 // refuse is refused whatever else is wrong with it.
998− if let Some(response) = rules(&head, ended).await? {
1002+ let ruled = rules(&head, ended).await?;
1003+ timing.mark("rules");
1004+ if let Some(response) = ruled {
9991005 if !ended {
10001006 drain(&mut stream).await?;
10011007 }
10181024 init.with_method(Method::Post).with_headers(headers);
10191025 let started = g1t_kit::now_ms();
10201026 let (answered, pack_bytes, sent, unscanned) = if ended {
1021− if let Some(response) = scan(&head).await? {
1027+ let scanned = scan(&head).await?;
1028+ timing.mark("scan");
1029+ if let Some(response) = scanned {
10221030 return Ok(Push::Blocked(response));
10231031 }
10241032 let pack = pack_bytes(&head);
10611069 (answered, pack, first + walked.1, true)
10621070 };
10631071 let ms = g1t_kit::now_ms().saturating_sub(started);
1072+ timing.mark("upload");
10641073 let failure = match &answered {
10651074 Ok(response) => resilience::classify_status(response.status_code()),
10661075 Err(_) => Some(Failure::Transient),
+2−0
19841984 default_branch.as_deref(),
19851985 limits,
19861986 scan,
1987+ timing,
19871988 )
19881989 .await?;
19891990 let turned_down = matches!(
20042005 default_branch.as_deref(),
20052006 git_http::PushLimits::default(),
20062007 nothing,
2008+ timing,
20072009 )
20082010 .await?;
20092011 }