refac: decouple persistence and image storage behind driver registries
This commit is contained in:
1 parent
421cfafec3
commit
81e299f09a
46 files changed
+1036
-374
No files matched your search
+82
-19
@@ -21,6 +21,55 @@ var mockImageExtensions = map[string]string{
|
||||
"image/svg+xml": ".svg",
|
||||
}
|
||||
|
||||
type mockImageStorage struct {
|
||||
blobs map[string][]byte
|
||||
putCalls int
|
||||
nextName int
|
||||
lastContent []byte
|
||||
deleted []string
|
||||
failPut error
|
||||
failDelete error
|
||||
}
|
||||
|
||||
func newMockImageStorage() *mockImageStorage {
|
||||
return &mockImageStorage{blobs: map[string][]byte{}}
|
||||
}
|
||||
|
||||
func (m *mockImageStorage) Put(contentType string, content io.Reader) (string, error) {
|
||||
m.putCalls++
|
||||
if m.failPut != nil {
|
||||
return "", m.failPut
|
||||
}
|
||||
data, err := io.ReadAll(content)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
m.nextName++
|
||||
name := "stored-" + strconv.Itoa(m.nextName) + mockImageExtensions[contentType]
|
||||
m.blobs[name] = data
|
||||
m.lastContent = data
|
||||
return name, nil
|
||||
}
|
||||
|
||||
func (m *mockImageStorage) Open(name string) (imageDomain.Blob, error) {
|
||||
data, ok := m.blobs[name]
|
||||
if !ok {
|
||||
return imageDomain.Blob{}, imageDomain.ErrBlobNotFound
|
||||
}
|
||||
return imageDomain.Blob{Content: io.NopCloser(strings.NewReader(string(data))), Size: int64(len(data))}, nil
|
||||
}
|
||||
|
||||
func (m *mockImageStorage) Delete(name string) error {
|
||||
m.deleted = append(m.deleted, name)
|
||||
if m.failDelete != nil {
|
||||
return m.failDelete
|
||||
}
|
||||
delete(m.blobs, name)
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ imageDomain.Storage = &mockImageStorage{}
|
||||
|
||||
type mockImageRepo struct {
|
||||
images map[uint32]imageDomain.Image
|
||||
nextID uint32
|
||||
@@ -28,7 +77,6 @@ type mockImageRepo struct {
|
||||
failDeleteFor map[uint32]error
|
||||
deleteCalls []uint32
|
||||
createCalls int
|
||||
lastContent []byte
|
||||
onDelete func(id uint32)
|
||||
}
|
||||
|
||||
@@ -45,34 +93,49 @@ func (m *mockImageRepo) sortedImages() []imageDomain.Image {
|
||||
return result
|
||||
}
|
||||
|
||||
func (m *mockImageRepo) Create(input imageDomain.ImageInput) (imageDomain.Image, error) {
|
||||
func (m *mockImageRepo) Create(input imageDomain.Image) (imageDomain.Image, error) {
|
||||
m.createCalls++
|
||||
if err := m.fail.trigger("Create"); err != nil {
|
||||
return imageDomain.Image{}, err
|
||||
}
|
||||
if input.Content != nil {
|
||||
m.lastContent, _ = io.ReadAll(input.Content)
|
||||
}
|
||||
for m.images[m.nextID+1].ID != 0 {
|
||||
m.nextID++
|
||||
}
|
||||
m.nextID++
|
||||
img := imageDomain.Image{
|
||||
ID: m.nextID,
|
||||
Path: "/static/uploadedImages/" + strconv.Itoa(int(m.nextID)) + mockImageExtensions[input.ContentType],
|
||||
Filename: input.Filename,
|
||||
Size: input.Size,
|
||||
ContentType: input.ContentType,
|
||||
Width: input.Width,
|
||||
Height: input.Height,
|
||||
SHA256: input.SHA256,
|
||||
UploadedByID: input.UploadedByID,
|
||||
CreatedAt: mockImageEpoch.Add(time.Duration(m.nextID) * time.Minute),
|
||||
}
|
||||
img := input
|
||||
img.ID = m.nextID
|
||||
img.CreatedAt = mockImageEpoch.Add(time.Duration(m.nextID) * time.Minute)
|
||||
m.images[img.ID] = img
|
||||
return img, nil
|
||||
}
|
||||
|
||||
func (m *mockImageRepo) ListMissingMetadata() ([]imageDomain.Image, error) {
|
||||
if err := m.fail.trigger("ListMissingMetadata"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pending := []imageDomain.Image{}
|
||||
for _, img := range m.sortedImages() {
|
||||
if img.Filename == "" {
|
||||
pending = append(pending, img)
|
||||
}
|
||||
}
|
||||
return pending, nil
|
||||
}
|
||||
|
||||
func (m *mockImageRepo) UpdateMetadata(id uint32, metadata imageDomain.Metadata) error {
|
||||
if err := m.fail.trigger("UpdateMetadata"); err != nil {
|
||||
return err
|
||||
}
|
||||
img, ok := m.images[id]
|
||||
if !ok {
|
||||
return imageDomain.ErrImageNotFound
|
||||
}
|
||||
img.Filename, img.Size, img.ContentType = metadata.Filename, metadata.Size, metadata.ContentType
|
||||
img.Width, img.Height, img.SHA256 = metadata.Width, metadata.Height, metadata.SHA256
|
||||
m.images[id] = img
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockImageRepo) Get(id uint32) (imageDomain.Image, error) {
|
||||
if err := m.fail.trigger("Get"); err != nil {
|
||||
return imageDomain.Image{}, err
|
||||
@@ -186,8 +249,8 @@ var _ imageDomain.Repository = &mockImageRepo{}
|
||||
|
||||
func TestImageUseCases(t *testing.T) {
|
||||
repo := newMockImageRepo()
|
||||
createUc := useCases.NewCreateImageUseCase(repo)
|
||||
deleteUc := useCases.NewDeleteMediaUseCase(repo)
|
||||
createUc := useCases.NewCreateImageUseCase(repo, newMockImageStorage())
|
||||
deleteUc := useCases.NewDeleteMediaUseCase(repo, newMockImageStorage())
|
||||
|
||||
t.Run("Create Image", func(t *testing.T) {
|
||||
input := imageDomain.ImageInput{
|
||||
|
||||
Reference in new issue
Block a user