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
|
||||
|
||||
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