From 22391ed0362aa0b57bcf5584e11d51fcb71f3d4c Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Wed, 12 Jul 2023 16:05:09 +0200 Subject: [PATCH] Improved directory storage --- README.md | 8 +++++ storage/Directory.go | 6 ++-- storage/Directory_test.go | 42 +++++++++++++++++++++++ storage/{storage_test.go => File_test.go} | 9 ++--- 4 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 storage/Directory_test.go rename storage/{storage_test.go => File_test.go} (81%) diff --git a/README.md b/README.md index 48dad46..64c6d9c 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,10 @@ for user := range users.All() { ## Storage systems +### nil + +You can specify `nil` as the storage system which will keep data in RAM only. + ### storage.File `storage.File` uses a single file to store all records. @@ -59,6 +63,10 @@ You should use `storage.File` if you have a permanently running process such as Make sure you `defer collection.Sync()` to ensure that queued writes will be handled when the process ends. +### storage.Directory + +`storage.Directory` creates a directory for your records and saves each record in a separate file. The performance of this method heavily depends on the file system you are using. + ## Benchmarks ``` diff --git a/storage/Directory.go b/storage/Directory.go index c1a40b1..208f963 100644 --- a/storage/Directory.go +++ b/storage/Directory.go @@ -20,7 +20,7 @@ func (ds *Directory[T]) Init(c ocean.StorageData) error { ds.directory = filepath.Join(c.Root(), c.Name()) err := os.Mkdir(ds.directory, 0700) - if err != nil { + if err != nil && !os.IsExist(err) { return err } @@ -70,8 +70,8 @@ func (ds *Directory[T]) read() error { // readFile loads a single file from the disk. func (ds *Directory[T]) readFile(fileName string) error { - fileName = filepath.Join(ds.directory, fileName) - file, err := os.Open(fileName) + filePath := filepath.Join(ds.directory, fileName) + file, err := os.Open(filePath) if err != nil { return err diff --git a/storage/Directory_test.go b/storage/Directory_test.go new file mode 100644 index 0000000..5a39344 --- /dev/null +++ b/storage/Directory_test.go @@ -0,0 +1,42 @@ +package storage_test + +import ( + "testing" + + "git.akyoto.dev/go/assert" + "git.akyoto.dev/go/ocean" + "git.akyoto.dev/go/ocean/storage" +) + +var _ ocean.Storage[string] = (*storage.Directory[string])(nil) + +func TestDirectoryPersistence(t *testing.T) { + users, err := ocean.New[User]("test", &storage.Directory[User]{}) + assert.Nil(t, err) + + defer users.Sync() + defer users.Clear() + + users.Set("1", &User{Name: "User 1"}) + users.Set("2", &User{Name: "User 2"}) + users.Set("3", &User{Name: "User 3"}) + users.Sync() + + reload, err := ocean.New[User]("test", &storage.Directory[User]{}) + assert.Nil(t, err) + + user, err := reload.Get("1") + assert.Nil(t, err) + assert.NotNil(t, user) + assert.Equal(t, user.Name, "User 1") + + user, err = reload.Get("2") + assert.Nil(t, err) + assert.NotNil(t, user) + assert.Equal(t, user.Name, "User 2") + + user, err = reload.Get("3") + assert.Nil(t, err) + assert.NotNil(t, user) + assert.Equal(t, user.Name, "User 3") +} diff --git a/storage/storage_test.go b/storage/File_test.go similarity index 81% rename from storage/storage_test.go rename to storage/File_test.go index 8bf7528..7e7ae95 100644 --- a/storage/storage_test.go +++ b/storage/File_test.go @@ -8,16 +8,13 @@ import ( "git.akyoto.dev/go/ocean/storage" ) +var _ ocean.Storage[string] = (*storage.File[string])(nil) + type User struct { Name string `json:"name"` } -func TestInterface(t *testing.T) { - var _ ocean.Storage[string] = (*storage.File[string])(nil) - var _ ocean.Storage[string] = (*storage.Directory[string])(nil) -} - -func TestPersistence(t *testing.T) { +func TestFilePersistence(t *testing.T) { users, err := ocean.New[User]("test", &storage.File[User]{}) assert.Nil(t, err)