d69a58e54a
A remote created through the API without `mutable_ttl` was stored as 0, so its mutable paths never refreshed. With `check_mutable`, the ETag expired together with the freshness key, so an expired mutable path was always refetched in full and never revalidated. - default an omitted `mutable_ttl` to 3600 on create; keep the stored value on update; explicit 0 still means never expire - keep mutable ETags for `max(10 × mutable_ttl, 7d)`, re-armed on each 304, only when `check_mutable` is set and `mutable_ttl` is non-zero - drop the stored ETag when a refetch returns none; never store one for immutable paths - flush a remote's Redis keys on delete - update docs/common/caching.md Reviewed-on: #151 Co-authored-by: unkin-agent <unkin-agent@unkin.net> Co-committed-by: unkin-agent <unkin-agent@unkin.net>
58 lines
1.5 KiB
Go
58 lines
1.5 KiB
Go
package v2
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"git.unkin.net/unkin/artifactapi/internal/database"
|
|
)
|
|
|
|
// An omitted mutable_ttl defaults to 3600 on create and keeps the stored value
|
|
// on update; an explicit 0 is stored as 0 in both.
|
|
func TestMutableTTLOmittedVsZero(t *testing.T) {
|
|
if testDSN == "" {
|
|
t.Skip("Docker unavailable")
|
|
}
|
|
db, err := database.New(testDSN)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
h := NewRemotesHandler(db, nil, nil).Routes()
|
|
ttl := func(name string) int {
|
|
t.Helper()
|
|
r, err := db.GetRemote(context.Background(), name)
|
|
if err != nil {
|
|
t.Fatalf("get %s: %v", name, err)
|
|
}
|
|
return r.MutableTTL
|
|
}
|
|
const body = `"package_type":"rpm","base_url":"https://example.com/repo"`
|
|
|
|
steps := []struct {
|
|
method, path, json string
|
|
want int
|
|
}{
|
|
{"POST", "/", `{"name":"ttl-omit",` + body + `}`, 3600},
|
|
{"PUT", "/ttl-omit", `{` + body + `,"mutable_ttl":120}`, 120},
|
|
{"PUT", "/ttl-omit", `{` + body + `}`, 120},
|
|
{"PUT", "/ttl-omit", `{` + body + `,"mutable_ttl":0}`, 0},
|
|
{"PUT", "/ttl-omit", `{` + body + `}`, 0},
|
|
}
|
|
for i, s := range steps {
|
|
if c := do(t, h, s.method, s.path, s.json); c/100 != 2 {
|
|
t.Fatalf("step %d %s %s = %d", i, s.method, s.path, c)
|
|
}
|
|
if got := ttl("ttl-omit"); got != s.want {
|
|
t.Errorf("step %d: mutable_ttl = %d, want %d", i, got, s.want)
|
|
}
|
|
}
|
|
|
|
if c := do(t, h, "POST", "/", `{"name":"ttl-zero",`+body+`,"mutable_ttl":0}`); c != 201 {
|
|
t.Fatalf("create explicit 0 = %d", c)
|
|
}
|
|
if got := ttl("ttl-zero"); got != 0 {
|
|
t.Errorf("explicit 0 stored as %d", got)
|
|
}
|
|
}
|