pull out of old example

This commit is contained in:
Risotto Bias 2025-01-12 02:51:51 -07:00
parent 86d27d152a
commit 9564d5656a
17 changed files with 228 additions and 3 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
file.gob

21
LICENSE Normal file
View 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
View file

@ -1 +0,0 @@
package gobstore

8
all.go Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View file

@ -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
View 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
}

View file

@ -1 +0,0 @@
package gobstore

View file

@ -1 +0,0 @@
package gobstore

12
set.go Normal file
View 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
View 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
View 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...")
}