From 31131a636055cb28c4d3d39fe5caba8dfa9531bf Mon Sep 17 00:00:00 2001 From: miyuko Date: Wed, 17 Sep 2025 13:00:45 +0100 Subject: [PATCH] Use a context to ensure a time-based deadline for update operations. --- src/fetch.go | 5 +++-- src/pages.go | 9 +++++++-- src/update.go | 30 ++++++++---------------------- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/fetch.go b/src/fetch.go index bec0f1b..452ce16 100644 --- a/src/fetch.go +++ b/src/fetch.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "io" @@ -11,10 +12,10 @@ import ( "github.com/go-git/go-git/v6/storage/memory" ) -func FetchRepository(repoURL string, branch string) (*Manifest, error) { +func FetchRepository(ctx context.Context, repoURL string, branch string) (*Manifest, error) { storer := memory.NewStorage() - repo, err := git.Clone(storer, nil, &git.CloneOptions{ + repo, err := git.CloneContext(ctx, storer, nil, &git.CloneOptions{ Bare: true, URL: repoURL, ReferenceName: plumbing.ReferenceName(branch), diff --git a/src/pages.go b/src/pages.go index 8d63fb0..e722be5 100644 --- a/src/pages.go +++ b/src/pages.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "context" "encoding/json" "fmt" "io" @@ -176,7 +177,9 @@ func putPage(w http.ResponseWriter, r *http.Request) error { branch = "pages" } - result := UpdateWithTimeout(webRoot, repoURL, branch, updateTimeout) + ctx, cancel := context.WithTimeout(r.Context(), updateTimeout) + defer cancel() + result := Update(ctx, webRoot, repoURL, branch) if result.manifest != nil { w.Header().Add("Content-Location", r.URL.String()) } @@ -285,7 +288,9 @@ func postPage(w http.ResponseWriter, r *http.Request) error { return fmt.Errorf("invalid clone URL") } - result := UpdateWithTimeout(webRoot, repoURL, "pages", updateTimeout) + ctx, cancel := context.WithTimeout(r.Context(), updateTimeout) + defer cancel() + result := Update(ctx, webRoot, repoURL, "pages") switch result.outcome { case UpdateError: w.WriteHeader(http.StatusServiceUnavailable) diff --git a/src/update.go b/src/update.go index 2221fd2..0b38cab 100644 --- a/src/update.go +++ b/src/update.go @@ -1,9 +1,10 @@ package main import ( + "context" + "errors" "fmt" "log" - "time" ) type UpdateOutcome int @@ -23,6 +24,7 @@ type UpdateResult struct { } func Update( + ctx context.Context, webRoot string, repoURL string, branch string, @@ -33,8 +35,11 @@ func Update( log.Println("update:", webRoot, repoURL, branch) outcome := UpdateError - fetchManifest, err = FetchRepository(repoURL, branch) - if err == nil { + fetchManifest, err = FetchRepository(ctx, repoURL, branch) + if errors.Is(err, context.DeadlineExceeded) { + outcome = UpdateTimeout + err = fmt.Errorf("update timeout") + } else if err == nil { oldManifest, _ = backend.GetManifest(webRoot) newManifest, err = StoreManifest(backend, webRoot, fetchManifest) if err == nil { @@ -65,22 +70,3 @@ func Update( return UpdateResult{outcome, newManifest, err} } - -func UpdateWithTimeout( - webRoot string, - repoURL string, - branch string, - timeout time.Duration, -) UpdateResult { - c := make(chan UpdateResult, 1) - go func() { - result := Update(webRoot, repoURL, branch) - c <- result - }() - select { - case result := <-c: - return result - case <-time.After(timeout): - return UpdateResult{outcome: UpdateTimeout, err: fmt.Errorf("update timeout")} - } -}