pull out of old example
This commit is contained in:
parent
86d27d152a
commit
9564d5656a
17 changed files with 228 additions and 3 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
file.gob
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
1
add.go
1
add.go
|
@ -1 +0,0 @@
|
||||||
package gobstore
|
|
8
all.go
Normal file
8
all.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package gobstore
|
||||||
|
|
||||||
|
// All returns the entire map
|
||||||
|
func (j *GobStore[T]) All() map[string]T {
|
||||||
|
j.Lock()
|
||||||
|
defer j.Unlock()
|
||||||
|
return j.values
|
||||||
|
}
|
8
count.go
Normal file
8
count.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package gobstore
|
||||||
|
|
||||||
|
// Count returns the length of the dictionary
|
||||||
|
func (j *GobStore[T]) Count() int {
|
||||||
|
j.Lock()
|
||||||
|
defer j.Unlock()
|
||||||
|
return len(j.values)
|
||||||
|
}
|
10
delete.go
Normal file
10
delete.go
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package gobstore
|
||||||
|
|
||||||
|
// Delete removes a key if it exists
|
||||||
|
func (j *GobStore[T]) Delete(key string) {
|
||||||
|
j.Lock()
|
||||||
|
defer j.Unlock()
|
||||||
|
j.dirty = true
|
||||||
|
delete(j.values, key)
|
||||||
|
// j.save()
|
||||||
|
}
|
22
example_test.go
Normal file
22
example_test.go
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package gobstore_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.bivouac.wiki/use/gobstore"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleStore() {
|
||||||
|
type FooBar struct{ Greeting string }
|
||||||
|
A := gobstore.NewStore[FooBar]("./", "file.gob")
|
||||||
|
A.Load()
|
||||||
|
A.Hidden_save()
|
||||||
|
//go A.WatchFlush()
|
||||||
|
A.Set("foobar", FooBar{Greeting: "Hello"})
|
||||||
|
resp, ok := A.Get("foobar")
|
||||||
|
if !ok {
|
||||||
|
fmt.Println("missing!")
|
||||||
|
}
|
||||||
|
fmt.Println(resp.Greeting)
|
||||||
|
// Output: Hello
|
||||||
|
}
|
16
filter.go
Normal file
16
filter.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package gobstore
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// Filter performs a prefix match against all key values.
|
||||||
|
func (j *GobStore[T]) Filter(prefix string) []T {
|
||||||
|
j.Lock()
|
||||||
|
defer j.Unlock()
|
||||||
|
res := make([]T, 0)
|
||||||
|
for k, v := range j.values {
|
||||||
|
if strings.HasPrefix(k, prefix) {
|
||||||
|
res = append(res, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
11
get.go
Normal file
11
get.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package gobstore
|
||||||
|
|
||||||
|
// Get returns a value from the store if it exists
|
||||||
|
func (j *GobStore[T]) Get(key string) (T, bool) {
|
||||||
|
j.Lock()
|
||||||
|
defer j.Unlock()
|
||||||
|
// res := j.load()
|
||||||
|
v, ok := j.values[key]
|
||||||
|
// v, ok := res[key]
|
||||||
|
return v, ok
|
||||||
|
}
|
25
hidden_save.go
Normal file
25
hidden_save.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package gobstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/gob"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (j *GobStore[T]) Hidden_save() { // exporting.... on close
|
||||||
|
// no lock
|
||||||
|
defer timer("GobStore save")()
|
||||||
|
file, err := os.Create(j.ROOT_DATA_PATH + j.path)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
fmt.Println("save " + j.path)
|
||||||
|
fmt.Println(len(j.values))
|
||||||
|
enc := gob.NewEncoder(file)
|
||||||
|
err = enc.Encode(j.values)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
j.dirty = false
|
||||||
|
}
|
21
init.go
21
init.go
|
@ -1 +1,22 @@
|
||||||
package gobstore
|
package gobstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// parent type
|
||||||
|
type GobStore[T any] struct {
|
||||||
|
sync.Mutex
|
||||||
|
path string
|
||||||
|
values map[string]T
|
||||||
|
dirty bool
|
||||||
|
ROOT_DATA_PATH string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStore creates a new object
|
||||||
|
func NewStore[T any](ROOT_DATA_PATH string, path string) GobStore[T] {
|
||||||
|
return GobStore[T]{
|
||||||
|
path: path,
|
||||||
|
ROOT_DATA_PATH: ROOT_DATA_PATH,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
31
load.go
Normal file
31
load.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package gobstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/gob"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Load initializes the data from disk
|
||||||
|
func (j *GobStore[T]) Load() {
|
||||||
|
// no lock
|
||||||
|
fmt.Println(j.ROOT_DATA_PATH + j.path)
|
||||||
|
file, err := os.Open(j.ROOT_DATA_PATH + j.path)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
fmt.Printf("Gob file does not exist: %s\n", j.path)
|
||||||
|
j.values = map[string]T{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
var res map[string]T
|
||||||
|
dec := gob.NewDecoder(file)
|
||||||
|
dec.Decode(&res)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
j.values = res
|
||||||
|
j.dirty = false
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
package gobstore
|
|
1
save.go
1
save.go
|
@ -1 +0,0 @@
|
||||||
package gobstore
|
|
12
set.go
Normal file
12
set.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package gobstore
|
||||||
|
|
||||||
|
// Set adds or updates a value.
|
||||||
|
func (j *GobStore[T]) Set(key string, value T) {
|
||||||
|
j.Lock()
|
||||||
|
defer j.Unlock()
|
||||||
|
j.dirty = true
|
||||||
|
j.values[key] = value
|
||||||
|
// todo := j.load()
|
||||||
|
// todo[key] = value
|
||||||
|
// j.save()
|
||||||
|
}
|
14
timer.go
Normal file
14
timer.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package gobstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// timer is a helper function
|
||||||
|
func timer(name string) func() {
|
||||||
|
start := time.Now()
|
||||||
|
return func() {
|
||||||
|
fmt.Printf("%s took %v\n", name, time.Since(start))
|
||||||
|
}
|
||||||
|
}
|
28
watchflush.go
Normal file
28
watchflush.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package gobstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WatchFlush checks every 5 minutes to save file to disk.
|
||||||
|
func (j *GobStore[T]) WatchFlush() {
|
||||||
|
fmt.Println("Watching to flush " + j.path + "...")
|
||||||
|
defer j.Unlock() // try this if it panics...
|
||||||
|
ticker := time.NewTicker(time.Minute * 5)
|
||||||
|
defer ticker.Stop()
|
||||||
|
for range ticker.C {
|
||||||
|
j.Lock()
|
||||||
|
t := timer("flushwatch")
|
||||||
|
if j.dirty {
|
||||||
|
fmt.Println("dirty, saving: " + j.path)
|
||||||
|
j.Hidden_save()
|
||||||
|
} else {
|
||||||
|
fmt.Println("clean, skipping: " + j.path)
|
||||||
|
}
|
||||||
|
t()
|
||||||
|
j.Unlock() // force unlock in loop
|
||||||
|
}
|
||||||
|
fmt.Println("finished...")
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue