From 4378f89fd918b067c1ef885975f3afe05c637ac8 Mon Sep 17 00:00:00 2001 From: Diego Augusto Molina Date: Mon, 10 Jun 2024 08:30:17 -0300 Subject: [PATCH] fix data race in dev runtime (#88887) --- pkg/web/render.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pkg/web/render.go b/pkg/web/render.go index 75d8f1e17b6..0766b80e3be 100644 --- a/pkg/web/render.go +++ b/pkg/web/render.go @@ -21,12 +21,15 @@ import ( "net/http" "os" "path/filepath" + + "golang.org/x/sync/singleflight" ) // Renderer is a Middleware that injects a template renderer into the macaron context, enabling ctx.HTML calls in the handlers. // If MACARON_ENV is set to "development" then templates will be recompiled on every request. For more performance, set the // MACARON_ENV environment variable to "production". func Renderer(dir, leftDelim, rightDelim string) Middleware { + var devEnvGr singleflight.Group fs := os.DirFS(dir) t, err := compileTemplates(fs, leftDelim, rightDelim) if err != nil { @@ -35,12 +38,16 @@ func Renderer(dir, leftDelim, rightDelim string) Middleware { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { ctx := FromContext(req.Context()) + ctx.template = t if Env == DEV { - if t, err = compileTemplates(fs, leftDelim, rightDelim); err != nil { + tt, err, _ := devEnvGr.Do("dev", func() (any, error) { + return compileTemplates(fs, leftDelim, rightDelim) + }) + if err != nil { panic("Context.HTML:" + err.Error()) } + ctx.template = tt.(*template.Template) } - ctx.template = t next.ServeHTTP(rw, req) }) }