101 lines
2.6 KiB
Markdown
101 lines
2.6 KiB
Markdown
# data
|
|
|
|
In-memory key value store that saves your data to disk using JSON.
|
|
|
|
## Installation
|
|
|
|
```shell
|
|
go get git.akyoto.dev/go/data
|
|
```
|
|
|
|
## Usage
|
|
|
|
```go
|
|
// User type
|
|
type User struct { Name string }
|
|
|
|
// Create ~/.data/myapp/User.dat
|
|
users := data.NewFile[User]("myapp")
|
|
|
|
// Write
|
|
users.Set("1", &User{Name: "User 1"})
|
|
users.Set("2", &User{Name: "User 2"})
|
|
users.Set("3", &User{Name: "User 3"})
|
|
|
|
// Read
|
|
a, err := users.Get("1")
|
|
b, err := users.Get("2")
|
|
c, err := users.Get("3")
|
|
|
|
// Iterate
|
|
for user := range users.All() {
|
|
fmt.Println(user.Name)
|
|
}
|
|
```
|
|
|
|
## Format
|
|
|
|
```json
|
|
1
|
|
{"name":"User 1"}
|
|
2
|
|
{"name":"User 2"}
|
|
3
|
|
{"name":"User 3"}
|
|
```
|
|
|
|
## Tests
|
|
|
|
```
|
|
PASS: TestCollection
|
|
PASS: TestCollection/All
|
|
PASS: TestCollection/Filter
|
|
PASS: TestCollection/Get
|
|
PASS: TestCollection/Exists
|
|
PASS: TestCollection/Parallel_Get_and_Set
|
|
PASS: TestCollection/Delete
|
|
PASS: TestFilePersistence
|
|
coverage: 84.1% of statements
|
|
```
|
|
|
|
## Benchmarks
|
|
|
|
```
|
|
BenchmarkGet-12 275126157 4.462 ns/op 0 B/op 0 allocs/op
|
|
BenchmarkSet-12 4796011 251.0 ns/op 32 B/op 2 allocs/op
|
|
BenchmarkDelete-12 471913158 2.530 ns/op 0 B/op 0 allocs/op
|
|
BenchmarkNew-12 48838576 22.89 ns/op 80 B/op 1 allocs/op
|
|
```
|
|
|
|
## Storage systems
|
|
|
|
When you initiate a new collection via `data.New` you can specify a storage system.
|
|
`data.NewFile` is a useful shortcut to create a collection with the `data.File` storage.
|
|
|
|
### nil
|
|
|
|
You can specify `nil` as the storage system which will keep data in RAM only.
|
|
|
|
### data.File
|
|
|
|
`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.
|
|
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.
|
|
|
|
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 `n * io` time to complete all writes but the async behavior makes it a constant `io`.
|
|
|
|
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.
|
|
|
|
## License
|
|
|
|
Please see the [license documentation](https://akyoto.dev/license).
|
|
|
|
## Copyright
|
|
|
|
© 2023 Eduard Urbach
|