Skip to content
quarry Artifact [43d0117b69]
Login

Artifact [43d0117b69]

Artifact 43d0117b69c4b935ebc2d22a4c43aa3743e05eab49a25c772174c449242a0fa8:


package api

import (
	"context"
	"errors"
	"strings"
	"testing"

	"craftdesign.group/quarry/internal/artifact"
	"craftdesign.group/quarry/internal/index"
	"craftdesign.group/quarry/internal/ops"
	"craftdesign.group/quarry/internal/timing"
)

// A mirror can carry an A card whose blob its upstream never served:
// all six attachments on tcl's ticket 5d170b5c are like that. The head
// answer "not in this store" was never remembered, so every render of
// that page asked the store six times, warm or cold. It is remembered
// until the next fold — the only way the blob can arrive — and after a
// fold the store is asked again.
func TestAMissingAttachmentIsNotAskedForAgainUntilAFold(t *testing.T) {
	ix, z, event := attachStore(t)
	ghost := strings.Repeat("d", 40)
	if err := ix.FoldNow([]index.Parsed{{Hash: strings.Repeat("a", 40), Art: &artifact.Artifact{
		Type: artifact.Attachment, Date: "2026-01-02T00:00:00", User: "dan",
		Attachment: &artifact.Attach{Name: "gone.txt", Target: event, Source: ghost},
	}}}); err != nil {
		t.Fatal(err)
	}
	r := ops.NewRegistry()
	if err := RegisterAll(r, Deps{Version: "v", Repos: NewRepos(map[string]*Repo{"test": {Index: ix, Zit: z}})}); err != nil {
		t.Fatal(err)
	}
	// head answers whether the ask reached the store.
	head := func(what string) bool {
		ctx, tm := timing.With(context.Background())
		_, err := r.Invoke(ctx, "attachment.head", attachmentHeadIn{Repo: "test", Hash: ghost})
		if !errors.Is(err, ops.ErrNotFound) {
			t.Fatalf("FAIL: %s: a blob the store lacks answered %v, want not found", what, err)
		}
		return tm.Category(timing.Zit) > 0
	}
	if !head("first ask") {
		t.Fatal("FAIL: the first ask never reached the store")
	}
	if head("second ask") {
		t.Fatal("FAIL: the second ask went back to the store for a blob it already knew was missing")
	}
	if err := ix.FoldNow([]index.Parsed{{Hash: strings.Repeat("b", 40), Art: &artifact.Artifact{
		Type: artifact.Wiki, WikiTitle: "Later", Date: "2026-01-03T00:00:00", User: "dan", Body: []byte("x\n")}}}); err != nil {
		t.Fatal(err)
	}
	if !head("after a fold") {
		t.Fatal("FAIL: after a fold the missing verdict was still served; the blob may have arrived")
	}
	t.Log("ok: a missing blob is remembered until the next fold, then asked for again")
}