From ec1371a9f33b9e5748eed88e783cdaef247a8951 Mon Sep 17 00:00:00 2001 From: Alec Thomas Date: Wed, 20 Sep 2023 11:46:09 +1000 Subject: [PATCH] fix: use build timestamp for resources rather than embedded FS (#410) Turns out, embedded files don't contain any filesystem metadata, which meant that ServeContent() caching was unable to function. --- Bitfile | 4 ++-- Dockerfile.controller | 4 ++-- Makefile | 2 +- backend/controller/controller.go | 3 ++- cmd/ftl-controller/main.go | 14 +++++++++++--- console/local.go | 3 ++- console/release.go | 10 +++------- 7 files changed, 23 insertions(+), 17 deletions(-) diff --git a/Bitfile b/Bitfile index aba4688c01..81383c816a 100644 --- a/Bitfile +++ b/Bitfile @@ -46,10 +46,10 @@ NODE_MODULES_IN = console/client/package{,-lock}.json # Build all binaries implicit %{RELEASE}/%{1}: cmd/* inputs: %{RELEASE} %{GO_SOURCES} %{CLIENT_OUT} - build: go build -o %{OUT} -tags release -ldflags "-X main.version=%{VERSION}" ./cmd/%{1} + build: go build -o %{OUT} -tags release -ldflags "-X main.version=%{VERSION} -X main.timestamp=$(date +%s)" ./cmd/%{1} #%{RELEASE}/ftl-controller: %{RELEASE} %{GO_SOURCES} %{CLIENT_OUT} -# build: go build -o %{OUT} -tags release -ldflags "-X main.version=%{VERSION}" ./cmd/ftl-controller +# build: go build -o %{OUT} -tags release -ldflags "-X main.version=%{VERSION} -X main.timestamp=$(date +%s)" ./cmd/ftl-controller %{SCHEMA_OUT}: %{SCHEMA_IN} build: diff --git a/Dockerfile.controller b/Dockerfile.controller index 75b5f9cb98..0bc14b5175 100644 --- a/Dockerfile.controller +++ b/Dockerfile.controller @@ -18,8 +18,8 @@ RUN go mod download -x # Build COPY . /src/ -RUN make build/release/ftl-controller -RUN make build/release/ftl +RUN bit build/release/ftl-controller +RUN bit build/release/ftl # Finally create the runtime image. FROM ubuntu:22.04 diff --git a/Makefile b/Makefile index ffef800648..607aff3a77 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,7 @@ clean: ## Clean build artifacts. release: build/release/ftl-controller build/release/ftl-runner build/release/ftl ## Build release binaries. build/release/%: console/client/dist/index.html - go build -o $@ -tags release -ldflags "-X main.version=$(VERSION)" ./cmd/$(shell basename $@) + go build -o $@ -tags release -ldflags "-X main.version=$(VERSION) -X main.timestamp=$(shell date +%s)" ./cmd/$(shell basename $@) $(KT_MVN_OUT): $(KT_RUNTIME_IN) mvn -pl :ftl-runtime clean package diff --git a/backend/controller/controller.go b/backend/controller/controller.go index 79928c42d3..d10ae01e88 100644 --- a/backend/controller/controller.go +++ b/backend/controller/controller.go @@ -47,6 +47,7 @@ type Config struct { Bind *url.URL `help:"Socket to bind to." default:"http://localhost:8892" env:"FTL_CONTROLLER_BIND"` Advertise *url.URL `help:"Endpoint the Controller should advertise (must be unique across the cluster, defaults to --bind if omitted)." env:"FTL_CONTROLLER_ADVERTISE"` AllowOrigin string `help:"Allow CORS requests from this origin." default:"*" env:"FTL_CONTROLLER_ALLOW_ORIGIN"` + ContentTime time.Time `help:"Time to use for console resource timestamps." default:"${timestamp=2006-01-02T15:04:05Z07:00}"` Key model.ControllerKey `help:"Controller key (auto)." placeholder:"C" default:"C00000000000000000000000000"` DSN string `help:"DAL DSN." default:"postgres://localhost/ftl?sslmode=disable&user=postgres&password=secret" env:"FTL_CONTROLLER_DSN"` RunnerTimeout time.Duration `help:"Runner heartbeat timeout." default:"10s"` @@ -67,7 +68,7 @@ func Start(ctx context.Context, config Config) error { logger := log.FromContext(ctx) logger.Infof("Starting FTL controller") - c, err := console.Server(ctx, config.AllowOrigin) + c, err := console.Server(ctx, config.ContentTime, config.AllowOrigin) if err != nil { return errors.WithStack(err) } diff --git a/cmd/ftl-controller/main.go b/cmd/ftl-controller/main.go index ee0ba7f154..2a9d1e9c3c 100644 --- a/cmd/ftl-controller/main.go +++ b/cmd/ftl-controller/main.go @@ -2,16 +2,20 @@ package main import ( "context" + "fmt" "os" + "strconv" + "time" "github.com/alecthomas/kong" _ "github.com/TBD54566975/ftl/backend/common/automaxprocs" // Set GOMAXPROCS to match Linux container CPU quota. - log "github.com/TBD54566975/ftl/backend/common/log" + "github.com/TBD54566975/ftl/backend/common/log" "github.com/TBD54566975/ftl/backend/controller" ) var version = "dev" +var timestamp = "0" var cli struct { Version kong.VersionFlag `help:"Show version."` @@ -20,12 +24,16 @@ var cli struct { } func main() { + t, err := strconv.ParseInt(timestamp, 10, 64) + if err != nil { + panic(fmt.Sprintf("invalid timestamp %q: %s", timestamp, err)) + } kctx := kong.Parse(&cli, kong.Description(`FTL - Towards a 𝝺-calculus for large-scale systems`), kong.UsageOnError(), - kong.Vars{"version": version}, + kong.Vars{"version": version, "timestamp": time.Unix(t, 0).Format(time.RFC3339)}, ) ctx := log.ContextWithLogger(context.Background(), log.Configure(os.Stderr, cli.LogConfig)) - err := controller.Start(ctx, cli.ControllerConfig) + err = controller.Start(ctx, cli.ControllerConfig) kctx.FatalIfErrorf(err) } diff --git a/console/local.go b/console/local.go index 6af49fbf41..c9f9ccaa65 100644 --- a/console/local.go +++ b/console/local.go @@ -7,6 +7,7 @@ import ( "net/http" "net/http/httputil" "net/url" + "time" "github.com/alecthomas/errors" @@ -17,7 +18,7 @@ import ( var consoleURL, _ = url.Parse("http://localhost:5173") var proxy = httputil.NewSingleHostReverseProxy(consoleURL) -func Server(ctx context.Context, allowOrigin string) (http.Handler, error) { +func Server(ctx context.Context, timestamp time.Time, allowOrigin string) (http.Handler, error) { logger := log.FromContext(ctx) logger.Infof("Building console...") diff --git a/console/release.go b/console/release.go index 16e1f67775..643e28c6c0 100644 --- a/console/release.go +++ b/console/release.go @@ -11,6 +11,7 @@ import ( "os" "path" "strings" + "time" "github.com/alecthomas/errors" ) @@ -18,7 +19,7 @@ import ( //go:embed all:client/dist var build embed.FS -func Server(ctx context.Context, allowOrigin string) (http.Handler, error) { +func Server(ctx context.Context, timestamp time.Time, allowOrigin string) (http.Handler, error) { dir, err := fs.Sub(build, "client/dist") if err != nil { return nil, errors.WithStack(err) @@ -41,11 +42,6 @@ func Server(ctx context.Context, allowOrigin string) (http.Handler, error) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - info, err := f.Stat() - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - http.ServeContent(w, r, filePath, info.ModTime(), f.(io.ReadSeeker)) + http.ServeContent(w, r, filePath, timestamp, f.(io.ReadSeeker)) }), nil }