From 7bb9bf90c22861f19e449b554d9b3e10080182ac Mon Sep 17 00:00:00 2001 From: Caj Larsson Date: Tue, 3 May 2022 22:08:25 +0800 Subject: [PATCH] swampfile.Repository.DeleteOlderThan --- dataswamp/swampfile/entities.go | 1 + dataswamp/swampfile/file_contract.go | 16 ++++++++++ dataswamp/swampfile/repository.go | 9 ++++-- infrastructure/fs/swampfile/repository.go | 30 ++++++++++++++++++ infrastructure/memory/swampfile/repository.go | 31 ++++++++++++++++--- 5 files changed, 80 insertions(+), 7 deletions(-) diff --git a/dataswamp/swampfile/entities.go b/dataswamp/swampfile/entities.go index bbab94c..c597e9e 100644 --- a/dataswamp/swampfile/entities.go +++ b/dataswamp/swampfile/entities.go @@ -22,4 +22,5 @@ var ( ErrUpdateFailed = errors.New("update failed") ErrDeleteFailed = errors.New("delete failed") ErrUnacceptablePath = errors.New("unacceptable path") + ErrCorrupted = errors.New("repository contains unexpected data") ) diff --git a/dataswamp/swampfile/file_contract.go b/dataswamp/swampfile/file_contract.go index 18a50ad..c0b4e45 100644 --- a/dataswamp/swampfile/file_contract.go +++ b/dataswamp/swampfile/file_contract.go @@ -3,6 +3,7 @@ package swampfile import ( "github.com/matryer/is" "testing" + "time" ) func RepositoryContract(fac func() Repository, t *testing.T) { @@ -47,4 +48,19 @@ func basicFileOperationContract(fac func() Repository, t *testing.T) { is.Equal(err, ErrNotExists) is.True(deleted_file == nil) + + // DeleteOlderThan + + expiring_file, err := repo.Create("deep/dir/expiring.new", "ua1") + is.NoErr(err) + + expiring_file.Write([]byte(testdata)) + expiring_file.Close() + + err = repo.DeleteOlderThan("ua1", time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)) + is.NoErr(err) + + expired_file, err := repo.Open("deep/dir/expiring.new", "ua1") + is.Equal(err, ErrNotExists) + is.True(expired_file == nil) } diff --git a/dataswamp/swampfile/repository.go b/dataswamp/swampfile/repository.go index 5653a75..620b89b 100644 --- a/dataswamp/swampfile/repository.go +++ b/dataswamp/swampfile/repository.go @@ -1,7 +1,10 @@ package swampfile +import "time" + type Repository interface { - Create(filename string, user_agent_label string) (SwampInFile, error) - Open(filename string, user_agent_label string) (SwampOutFile, error) - Delete(filename string, user_agent_label string) + Create(filename string, namespace_stub string) (SwampInFile, error) + Open(filename string, namespace_stub string) (SwampOutFile, error) + Delete(filename string, namespace_stub string) + DeleteOlderThan(namespace_stub string, ts time.Time) error } diff --git a/infrastructure/fs/swampfile/repository.go b/infrastructure/fs/swampfile/repository.go index b26bf93..5ed6766 100644 --- a/infrastructure/fs/swampfile/repository.go +++ b/infrastructure/fs/swampfile/repository.go @@ -4,6 +4,8 @@ import ( "caj-larsson/bog/dataswamp/swampfile" "os" "path" + "path/filepath" + "io/fs" "time" "errors" ) @@ -122,3 +124,31 @@ func (f Repository) Delete(filename string, namespace_ns string) { abs_path := f.absPath(filename, namespace_ns) os.Remove(abs_path) } + +func (r Repository) DeleteOlderThan(namespace_stub string, ts time.Time) error { + dr := path.Join(r.Root, namespace_stub) + err := filepath.Walk(dr, func(path string, info fs.FileInfo, err error) error { + if err != nil { + return err + } + mode := info.Mode() + + if mode.IsRegular() { + if ts.Before(info.ModTime()) { + + err = os.Remove(path) + if err != nil { + panic(err) + } + } + return nil + } + + if !mode.IsDir() { + return swampfile.ErrCorrupted + } + + return nil + }) + return err +} diff --git a/infrastructure/memory/swampfile/repository.go b/infrastructure/memory/swampfile/repository.go index 614e65d..73f7bc3 100644 --- a/infrastructure/memory/swampfile/repository.go +++ b/infrastructure/memory/swampfile/repository.go @@ -4,11 +4,13 @@ import ( "os" "path" "time" - // "io" + "io/fs" "caj-larsson/bog/dataswamp/swampfile" "github.com/spf13/afero" ) + + type SwampFile struct { filename string file afero.File @@ -54,7 +56,7 @@ func NewRepository() swampfile.Repository { } func (r Repository) Create(filename string, namespace_stub string) (swampfile.SwampInFile, error) { - abs_path := path.Join(filename, namespace_stub) + abs_path := path.Join(namespace_stub, filename) dir := path.Dir(abs_path) r.fs.MkdirAll(dir, 0750) file, err := r.fs.OpenFile(abs_path, os.O_RDWR|os.O_CREATE, 0644) @@ -69,7 +71,7 @@ func (r Repository) Create(filename string, namespace_stub string) (swampfile.Sw } func (r Repository) Open(filename string, namespace_stub string) (swampfile.SwampOutFile, error) { - abs_path := path.Join(filename, namespace_stub) + abs_path := path.Join(namespace_stub, filename) dir := path.Dir(abs_path) r.fs.MkdirAll(dir, 0750) @@ -84,6 +86,27 @@ func (r Repository) Open(filename string, namespace_stub string) (swampfile.Swam } func (r Repository) Delete(filename string, namespace_stub string) { - abs_path := path.Join(filename, namespace_stub) + abs_path := path.Join(namespace_stub, filename) r.fs.Remove(abs_path) } + +func (r Repository) DeleteOlderThan(namespace_stub string, ts time.Time) error { + err := afero.Walk(r.fs, namespace_stub, func(path string, info fs.FileInfo, err error) error { + if err != nil { + return err + } + + if info.Mode().IsRegular() && ts.Before(info.ModTime()) { + r.fs.Remove(path) + return nil + } + + if !info.Mode().IsDir() { + return swampfile.ErrCorrupted + } + + return nil + }) + + return err +}