Renamed module

This commit is contained in:
Eduard Urbach 2023-07-19 11:52:13 +02:00
parent 76af0f8db2
commit 3fed61059b
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
11 changed files with 32 additions and 32 deletions

View File

@ -1,14 +1,14 @@
package ocean_test package data_test
import ( import (
"testing" "testing"
"git.akyoto.dev/go/assert" "git.akyoto.dev/go/assert"
"git.akyoto.dev/go/ocean" "git.akyoto.dev/go/data"
) )
func BenchmarkGet(b *testing.B) { func BenchmarkGet(b *testing.B) {
users, err := ocean.New[User]("test", nil) users, err := data.New[User]("test", nil)
assert.Nil(b, err) assert.Nil(b, err)
defer users.Sync() defer users.Sync()
@ -29,7 +29,7 @@ func BenchmarkGet(b *testing.B) {
} }
func BenchmarkSet(b *testing.B) { func BenchmarkSet(b *testing.B) {
users, err := ocean.New[User]("test", nil) users, err := data.New[User]("test", nil)
assert.Nil(b, err) assert.Nil(b, err)
defer users.Sync() defer users.Sync()
@ -50,7 +50,7 @@ func BenchmarkSet(b *testing.B) {
} }
func BenchmarkDelete(b *testing.B) { func BenchmarkDelete(b *testing.B) {
users, err := ocean.New[User]("test", nil) users, err := data.New[User]("test", nil)
assert.Nil(b, err) assert.Nil(b, err)
defer users.Sync() defer users.Sync()
@ -71,7 +71,7 @@ func BenchmarkDelete(b *testing.B) {
func BenchmarkNew(b *testing.B) { func BenchmarkNew(b *testing.B) {
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {
_, _ = ocean.New[User]("test", nil) _, _ = data.New[User]("test", nil)
} }
}) })
} }

View File

@ -1,4 +1,4 @@
package ocean package data
import ( import (
"os" "os"
@ -45,7 +45,7 @@ func New[T any](namespace string, storage Storage[T]) (Collection[T], error) {
} }
c.storage = storage c.storage = storage
c.root = filepath.Join(home, ".ocean", namespace) c.root = filepath.Join(home, ".data", namespace)
err = os.MkdirAll(c.root, 0700) err = os.MkdirAll(c.root, 0700)
if err != nil { if err != nil {

View File

@ -1,11 +1,11 @@
package ocean_test package data_test
import ( import (
"sync" "sync"
"testing" "testing"
"git.akyoto.dev/go/assert" "git.akyoto.dev/go/assert"
"git.akyoto.dev/go/ocean" "git.akyoto.dev/go/data"
) )
type User struct { type User struct {
@ -13,7 +13,7 @@ type User struct {
} }
func TestCollection(t *testing.T) { func TestCollection(t *testing.T) {
users, err := ocean.New[User]("test", nil) users, err := data.New[User]("test", nil)
assert.Nil(t, err) assert.Nil(t, err)
defer users.Sync() defer users.Sync()

View File

@ -1,4 +1,4 @@
package ocean package data
import ( import (
"bufio" "bufio"

View File

@ -1,16 +1,16 @@
package ocean_test package data_test
import ( import (
"testing" "testing"
"git.akyoto.dev/go/assert" "git.akyoto.dev/go/assert"
"git.akyoto.dev/go/ocean" "git.akyoto.dev/go/data"
) )
var _ ocean.Storage[string] = (*ocean.File[string])(nil) var _ data.Storage[string] = (*data.File[string])(nil)
func TestFilePersistence(t *testing.T) { func TestFilePersistence(t *testing.T) {
users, err := ocean.NewFile[User]("test") users, err := data.NewFile[User]("test")
assert.Nil(t, err) assert.Nil(t, err)
defer users.Clear() defer users.Clear()
@ -22,7 +22,7 @@ func TestFilePersistence(t *testing.T) {
users.Sync() users.Sync()
// Reload data from disk // Reload data from disk
reload, err := ocean.NewFile[User]("test") reload, err := data.NewFile[User]("test")
assert.Nil(t, err) assert.Nil(t, err)
user, err := reload.Get("1") user, err := reload.Get("1")

View File

@ -1,4 +1,4 @@
package ocean package data
import "fmt" import "fmt"

View File

@ -1,11 +1,11 @@
# ocean # data
In-memory key value store that saves your data to disk using JSON. In-memory key value store that saves your data to disk using JSON.
## Installation ## Installation
```shell ```shell
go get git.akyoto.dev/go/ocean go get git.akyoto.dev/go/data
``` ```
## Example ## Example
@ -14,8 +14,8 @@ go get git.akyoto.dev/go/ocean
// User type // User type
type User struct { Name string } type User struct { Name string }
// Create ~/.ocean/myapp/User.dat // Create ~/.data/myapp/User.dat
users := ocean.NewFile[User]("myapp") users := data.NewFile[User]("myapp")
// Write // Write
users.Set("1", &User{Name: "User 1"}) users.Set("1", &User{Name: "User 1"})
@ -55,24 +55,24 @@ BenchmarkNew-12 48838576 22.89 ns/op 80 B/op
## Storage systems ## Storage systems
When you initiate a new collection via `ocean.New` you can specify a storage system. When you initiate a new collection via `data.New` you can specify a storage system.
`ocean.NewFile` is a useful shortcut to create a collection with the `ocean.File` storage. `data.NewFile` is a useful shortcut to create a collection with the `data.File` storage.
### nil ### nil
You can specify `nil` as the storage system which will keep data in RAM only. You can specify `nil` as the storage system which will keep data in RAM only.
### ocean.File ### data.File
`ocean.File` uses a single file to store all records. `data.File` uses a single file to store all records.
Writes using `Set(key, value)` are async and only mark the collection as "dirty" which is very quick. Writes using `Set(key, value)` are async and only mark the collection as "dirty" which is very quick.
The sync to disk happens shortly afterwards. The sync to disk happens shortly afterwards.
Every collection uses one goroutine to check the "dirty" flag, write the new contents to disk and reset the flag. Every collection uses one goroutine to check the "dirty" flag, write the new contents to disk and reset the flag.
The biggest advantage of `ocean.File` is that it scales well with the number of requests: The biggest advantage of `data.File` is that it scales well with the number of requests:
Suppose `n` is the number of write requests and `io` is the time it takes for one write. Immediate writes would require `O(n * io)` time to complete all writes but the async behavior makes it `O(n)`. Suppose `n` is the number of write requests and `io` is the time it takes for one write. Immediate writes would require `O(n * io)` time to complete all writes but the async behavior makes it `O(n)`.
You should use `ocean.File` if you have a permanently running process such as a web server where end users expect quick responses and background work can happen after the user request has already been dealt with. You should use `data.File` if you have a permanently running process such as a web server where end users expect quick responses and background work can happen after the user request has already been dealt with.
Make sure you `defer collection.Sync()` to ensure that queued writes will be handled when the process ends. Make sure you `defer collection.Sync()` to ensure that queued writes will be handled when the process ends.

View File

@ -1,4 +1,4 @@
package ocean package data
type Storage[T any] interface { type Storage[T any] interface {
Init(data storageData) error Init(data storageData) error

2
go.mod
View File

@ -1,4 +1,4 @@
module git.akyoto.dev/go/ocean module git.akyoto.dev/go/data
go 1.20 go 1.20

View File

@ -1,4 +1,4 @@
package ocean package data
type keyValue struct { type keyValue struct {
key string key string

View File

@ -1,4 +1,4 @@
package ocean package data
import "sync" import "sync"