production runtime and mock removal
This commit is contained in:
1 parent
2ef3da7af5
commit
6480e503eb
55 files changed
+581
-540
No files matched your search
@@ -7,7 +7,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html"
|
||||
"io"
|
||||
"path"
|
||||
"regexp"
|
||||
@@ -236,16 +235,6 @@ type ImportGeneratedCommand struct {
|
||||
Metadata map[string]any
|
||||
}
|
||||
|
||||
// ImportMockCommand describes a locally generated development result. Unlike
|
||||
// ImportGeneratedCommand it carries no URL, so mock output never enters the
|
||||
// remote-fetch/SSRF boundary.
|
||||
type ImportMockCommand struct {
|
||||
Name, Capability, JobID string
|
||||
Kind Kind
|
||||
Tags []string
|
||||
Metadata map[string]any
|
||||
}
|
||||
|
||||
func (s *Service) Upload(ctx context.Context, scope Scope, cmd UploadCommand) (Asset, error) {
|
||||
if err := validScope(scope); err != nil {
|
||||
return Asset{}, err
|
||||
@@ -336,53 +325,6 @@ func (s *Service) ImportGenerated(ctx context.Context, scope Scope, cmd ImportGe
|
||||
}
|
||||
return created, nil
|
||||
}
|
||||
|
||||
// ImportMock stores a small deterministic placeholder in the configured blob
|
||||
// store and registers it as a generated asset. It is intentionally a separate
|
||||
// path from remote imports: relative mock provider URLs are never interpreted
|
||||
// as fetch destinations.
|
||||
func (s *Service) ImportMock(ctx context.Context, scope Scope, cmd ImportMockCommand) (Asset, error) {
|
||||
if err := validScope(scope); err != nil {
|
||||
return Asset{}, err
|
||||
}
|
||||
if s.blobs == nil {
|
||||
return Asset{}, errors.New("blob store is unavailable")
|
||||
}
|
||||
kind := cmd.Kind
|
||||
if kind == "" {
|
||||
kind = KindImage
|
||||
}
|
||||
name, contentType, content := mockOutput(cmd.Name, kind, cmd.JobID)
|
||||
key := path.Join("generated-results", s.now().UTC().Format("2006-01-02"), s.id("file")+"-"+sanitizeFileName(name))
|
||||
stored, err := s.blobs.Put(ctx, key, bytes.NewReader(content), int64(len(content)), contentType)
|
||||
if err != nil {
|
||||
return Asset{}, err
|
||||
}
|
||||
now := s.now().UTC()
|
||||
metadata := cloneMetadata(cmd.Metadata)
|
||||
metadata["contentType"] = contentType
|
||||
metadata["size"] = len(content)
|
||||
metadata["capability"] = cmd.Capability
|
||||
metadata["jobId"] = cmd.JobID
|
||||
metadata["mock"] = true
|
||||
asset := Asset{ID: s.id("asset"), OwnerID: scope.ownerID, Kind: kind, Name: name, URL: stored.URL, StoragePath: stored.Key, Source: SourceGenerated, Tags: cloneStrings(cmd.Tags), Metadata: metadata, CreatedAt: now, UpdatedAt: now}
|
||||
created, err := s.catalog.Create(ctx, asset)
|
||||
if err != nil {
|
||||
_ = s.blobs.Delete(context.WithoutCancel(ctx), stored.Key)
|
||||
return Asset{}, err
|
||||
}
|
||||
return created, nil
|
||||
}
|
||||
|
||||
func mockOutput(name string, kind Kind, jobID string) (string, string, []byte) {
|
||||
if kind == KindVideo {
|
||||
return defaultString(name, "mock-video.mp4"), "video/mp4", []byte("mock video result for " + jobID + "\n")
|
||||
}
|
||||
name = defaultString(name, "mock-image.svg")
|
||||
content := `<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024"><rect width="1024" height="1024" fill="#111827"/><text x="512" y="492" text-anchor="middle" fill="#f9fafb" font-family="sans-serif" font-size="64">Mock image</text><text x="512" y="558" text-anchor="middle" fill="#9ca3af" font-family="sans-serif" font-size="28">` + html.EscapeString(jobID) + `</text></svg>`
|
||||
return name, "image/svg+xml", []byte(content)
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, scope Scope, id string) (Asset, error) {
|
||||
a, err := s.Get(ctx, scope, id)
|
||||
if err != nil {
|
||||
|
||||
@@ -104,28 +104,6 @@ func TestImportGeneratedCompensatesBlobWhenCatalogFails(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportMockStoresAccessibleGeneratedAssetWithoutRemoteFetch(t *testing.T) {
|
||||
cat := &memoryCatalog{}
|
||||
blobs := &memoryBlobs{}
|
||||
remote := &memoryRemote{}
|
||||
ids := []string{"file-1", "asset-1"}
|
||||
svc := NewService(cat, blobs, remote, func() time.Time { return time.Date(2026, 8, 13, 8, 0, 0, 0, time.UTC) }, func(string) string {
|
||||
id := ids[0]
|
||||
ids = ids[1:]
|
||||
return id
|
||||
})
|
||||
created, err := svc.ImportMock(context.Background(), PlatformScope("owner-a"), ImportMockCommand{Capability: "image.generate", JobID: "job-1", Kind: KindImage, Tags: []string{"generated", "job:job-1"}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if created.ID != "asset-1" || created.StoragePath != "generated-results/2026-08-13/file-1-mock-image.svg" || created.URL != "https://app.test/generated-results/2026-08-13/file-1-mock-image.svg" || created.Metadata["mock"] != true || remote.called {
|
||||
t.Fatalf("created = %#v remoteCalled=%v", created, remote.called)
|
||||
}
|
||||
if blobs.putContentType != "image/svg+xml" || !bytes.Contains(blobs.putBody, []byte("job-1")) {
|
||||
t.Fatalf("stored contentType=%q body=%q", blobs.putContentType, blobs.putBody)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteLeavesCatalogWhenBlobDeletionFails(t *testing.T) {
|
||||
cat := &memoryCatalog{assets: []Asset{{ID: "a", OwnerID: "o", StoragePath: "uploads/a"}}}
|
||||
blobs := &memoryBlobs{deleteErr: errors.New("storage down")}
|
||||
|
||||
Reference in new issue
Block a user