Compare commits

...

3 Commits

3 changed files with 123 additions and 4 deletions

View File

@ -2,6 +2,7 @@ package entry
import (
"context"
"errors"
"source.toby3d.me/toby3d/pub/internal/domain"
)
@ -10,10 +11,15 @@ type (
UpdateFunc func(ctx context.Context, input *domain.Entry) (*domain.Entry, error)
Repository interface {
Create(ctx context.Context, path string, e domain.Entry) (*domain.Entry, error)
Create(ctx context.Context, path string, e domain.Entry) error
Get(ctx context.Context, path string) (*domain.Entry, error)
Fetch(ctx context.Context, path string) ([]domain.Entry, int, error)
Update(ctx context.Context, path string, update UpdateFunc) (*domain.Entry, error)
Delete(ctx context.Context, path string) (bool, error)
}
)
var (
ErrExist error = errors.New("this entry already exist")
ErrNotExist error = errors.New("this entry is not exist")
)

View File

@ -0,0 +1,109 @@
package memory
import (
"context"
"errors"
"fmt"
"path"
"strings"
"sync"
"source.toby3d.me/toby3d/pub/internal/domain"
"source.toby3d.me/toby3d/pub/internal/entry"
)
type memoryEntryRepository struct {
mutex *sync.RWMutex
entries map[string]domain.Entry
}
func NewMemoryEntryRepository() entry.Repository {
return &memoryEntryRepository{
mutex: new(sync.RWMutex),
entries: make(map[string]domain.Entry),
}
}
func (repo *memoryEntryRepository) Create(ctx context.Context, p string, e domain.Entry) error {
p = path.Clean(strings.ToLower(p))
_, err := repo.Get(ctx, p)
if err != nil && !errors.Is(err, entry.ErrNotExist) {
return fmt.Errorf("cannot save a new entry: %w", err)
}
if err == nil {
return entry.ErrExist
}
repo.mutex.Lock()
defer repo.mutex.Unlock()
repo.entries[p] = e
return nil
}
func (repo *memoryEntryRepository) Get(ctx context.Context, p string) (*domain.Entry, error) {
repo.mutex.RLock()
defer repo.mutex.RUnlock()
if out, ok := repo.entries[path.Clean(strings.ToLower(p))]; ok {
return &out, nil
}
return nil, entry.ErrNotExist
}
func (repo *memoryEntryRepository) Fetch(ctx context.Context, p string) ([]domain.Entry, int, error) {
repo.mutex.RLock()
defer repo.mutex.RUnlock()
out := make([]domain.Entry, 0)
for entryPath, e := range repo.entries {
if matched, err := path.Match(p+"*", entryPath); err != nil || !matched {
continue
}
out = append(out, e)
}
return out, len(out), nil
}
func (repo *memoryEntryRepository) Update(ctx context.Context, p string, update entry.UpdateFunc) (*domain.Entry, error) {
p = path.Clean(strings.ToLower(p))
repo.mutex.Lock()
defer repo.mutex.Unlock()
if in, ok := repo.entries[p]; ok {
out, err := update(ctx, &in)
if err != nil {
return nil, fmt.Errorf("cannot update entry: %w", err)
}
repo.entries[p] = *out
return out, err
}
return nil, fmt.Errorf("cannot update entry: %w", entry.ErrNotExist)
}
func (repo *memoryEntryRepository) Delete(ctx context.Context, p string) (bool, error) {
if _, err := repo.Get(ctx, p); err != nil {
if errors.Is(err, entry.ErrNotExist) {
return false, nil
}
return false, fmt.Errorf("cannot find entry to delete: %w", err)
}
repo.mutex.Lock()
defer repo.mutex.Unlock()
delete(repo.entries, path.Clean(strings.ToLower(p)))
return true, nil
}

View File

@ -16,9 +16,13 @@ type entryUseCase struct {
// Create implements entry.UseCase.
func (ucase *entryUseCase) Create(ctx context.Context, e domain.Entry) (*domain.Entry, error) {
result, err := ucase.entries.Create(ctx, e.URL.RequestURI(), e)
if err := ucase.entries.Create(ctx, e.URL.RequestURI(), e); err != nil {
return nil, fmt.Errorf("cannot create entry: %w", err)
}
result, err := ucase.entries.Get(ctx, e.URL.RequestURI())
if err != nil {
return nil, fmt.Errorf("cannot source entry: %w", err)
return nil, fmt.Errorf("cannot source created entry: %w", err)
}
return result, nil
@ -79,7 +83,7 @@ func (ucase *entryUseCase) Update(ctx context.Context, u *url.URL, e domain.Entr
return nil, nil
})
if err != nil {
return nil, fmt.Errorf("cannot undelete entry: %w", err)
return nil, fmt.Errorf("cannot update entry: %w", err)
}
return result, nil