Respond to webhook deliveries in under 3 seconds.

This commit is contained in:
miyuko
2025-10-17 22:08:25 +01:00
parent 2ac2aee14a
commit fcc6245ce8

View File

@@ -397,6 +397,10 @@ func deletePage(w http.ResponseWriter, r *http.Request) error {
}
func postPage(w http.ResponseWriter, r *http.Request) error {
// Start a timer for the request timeout immediately.
requestTimeout := 3 * time.Second
requestTimer := time.NewTimer(requestTimeout)
auth, err := AuthorizeUpdateFromRepository(r)
if err != nil {
return err
@@ -414,8 +418,6 @@ func postPage(w http.ResponseWriter, r *http.Request) error {
webRoot := makeWebRoot(host, projectName)
isGitHub := strings.Contains(r.Header.Get("User-Agent"), "GitHub-Hookshot")
eventName := ""
for _, header := range []string{
"X-Forgejo-Event",
@@ -465,7 +467,7 @@ func postPage(w http.ResponseWriter, r *http.Request) error {
if event.Ref != fmt.Sprintf("refs/heads/%s", auth.branch) {
code := http.StatusUnauthorized
if isGitHub {
if strings.Contains(r.Header.Get("User-Agent"), "GitHub-Hookshot") {
// GitHub has no way to restrict branches for a webhook, and responding with 401
// for every non-pages branch makes the "Recent Deliveries" tab look awful.
code = http.StatusOK
@@ -481,34 +483,23 @@ func postPage(w http.ResponseWriter, r *http.Request) error {
return err
}
updateCtx := r.Context()
if isGitHub {
updateCtx = context.Background()
}
resultChan := make(chan UpdateResult, 1)
resultChan := make(chan UpdateResult)
go func(ctx context.Context) {
defer close(resultChan)
ctx, cancel := context.WithTimeout(ctx, time.Duration(config.Limits.UpdateTimeout))
defer cancel()
result := UpdateFromRepository(ctx, webRoot, repoURL, auth.branch)
resultChan <- result
reportSiteUpdate("webhook", &result)
}(updateCtx)
}(context.Background())
var result UpdateResult
if isGitHub {
select {
case result = <-resultChan:
case <-time.After(5 * time.Second):
w.WriteHeader(http.StatusAccepted)
fmt.Fprintf(w, "updating (taking longer than 5 seconds)")
return nil
}
} else {
result = <-resultChan
select {
case result = <-resultChan:
case <-requestTimer.C:
w.WriteHeader(http.StatusAccepted)
fmt.Fprintf(w, "updating (taking longer than %s)", requestTimeout)
return nil
}
switch result.outcome {