101 lines
2.6 KiB
Markdown
Raw Normal View History

2023-07-19 09:52:13 +00:00
# data
2023-07-04 21:35:20 +00:00
2023-07-08 17:28:57 +00:00
In-memory key value store that saves your data to disk using JSON.
2023-07-05 20:07:43 +00:00
2023-07-06 12:41:36 +00:00
## Installation
2023-07-06 12:34:22 +00:00
2023-07-06 12:42:25 +00:00
```shell
2023-07-19 09:52:13 +00:00
go get git.akyoto.dev/go/data
2023-07-06 12:34:22 +00:00
```
2023-07-06 12:31:23 +00:00
2024-06-26 12:02:08 +00:00
## Usage
2023-07-06 12:34:22 +00:00
```go
2023-07-17 19:57:14 +00:00
// User type
2023-07-08 17:28:57 +00:00
type User struct { Name string }
2023-07-06 12:41:36 +00:00
2023-07-19 09:52:13 +00:00
// Create ~/.data/myapp/User.dat
users := data.NewFile[User]("myapp")
2023-07-06 12:31:23 +00:00
2023-07-17 19:57:14 +00:00
// Write
2023-07-06 12:10:12 +00:00
users.Set("1", &User{Name: "User 1"})
2023-07-08 17:28:57 +00:00
users.Set("2", &User{Name: "User 2"})
users.Set("3", &User{Name: "User 3"})
2023-07-06 12:48:29 +00:00
2023-07-17 19:57:14 +00:00
// Read
a, err := users.Get("1")
b, err := users.Get("2")
c, err := users.Get("3")
2023-07-06 13:15:51 +00:00
2023-07-17 19:57:14 +00:00
// Iterate
2023-07-06 13:15:51 +00:00
for user := range users.All() {
fmt.Println(user.Name)
}
2023-07-06 12:10:12 +00:00
```
2023-07-06 12:27:48 +00:00
2023-07-17 19:57:14 +00:00
## Format
2023-07-06 12:27:48 +00:00
2023-07-08 20:10:02 +00:00
```json
2023-07-08 17:28:57 +00:00
1
{"name":"User 1"}
2
{"name":"User 2"}
3
{"name":"User 3"}
```
2023-07-06 13:12:29 +00:00
2024-06-26 12:02:08 +00:00
## 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
```
2023-07-12 14:16:27 +00:00
## 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
```
2023-07-12 11:28:15 +00:00
## Storage systems
2023-07-19 09:52:13 +00:00
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.
2023-07-18 07:40:58 +00:00
2023-07-12 14:05:09 +00:00
### nil
You can specify `nil` as the storage system which will keep data in RAM only.
2023-07-19 09:52:13 +00:00
### data.File
2023-07-12 11:28:15 +00:00
2023-07-19 09:52:13 +00:00
`data.File` uses a single file to store all records.
2023-07-12 11:28:15 +00:00
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.
2023-07-19 09:52:13 +00:00
The biggest advantage of `data.File` is that it scales well with the number of requests:
2023-07-12 11:28:15 +00:00
2024-06-26 12:02:08 +00:00
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`.
2023-07-12 11:28:15 +00:00
2023-07-19 09:52:13 +00:00
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.
2023-07-12 11:28:15 +00:00
Make sure you `defer collection.Sync()` to ensure that queued writes will be handled when the process ends.
2024-06-26 12:02:08 +00:00
## License
Please see the [license documentation](https://akyoto.dev/license).
## Copyright
© 2023 Eduard Urbach