Renamed module
This commit is contained in:
parent
76af0f8db2
commit
3fed61059b
@ -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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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()
|
||||||
|
10
File_test.go
10
File_test.go
@ -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")
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package ocean
|
package data
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
|
20
README.md
20
README.md
@ -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.
|
||||||
|
@ -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
2
go.mod
@ -1,4 +1,4 @@
|
|||||||
module git.akyoto.dev/go/ocean
|
module git.akyoto.dev/go/data
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package ocean
|
package data
|
||||||
|
|
||||||
type keyValue struct {
|
type keyValue struct {
|
||||||
key string
|
key string
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package ocean
|
package data
|
||||||
|
|
||||||
import "sync"
|
import "sync"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user