Allow configuration of tidy functions. Use a closure to decide what entries
to delete. The closure takes a *bolt.Bucket and returns an integer of the number of entries deleted.
This commit is contained in:
parent
d6f4920507
commit
17beaca380
77
persist.go
77
persist.go
|
@ -40,23 +40,41 @@ type Config struct {
|
||||||
configured bool
|
configured bool
|
||||||
MaxVars int
|
MaxVars int
|
||||||
DBPath string
|
DBPath string
|
||||||
|
Tidy TidyConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func Init(x ...Config) {
|
func Init(x ...Config) {
|
||||||
mux.Lock()
|
mux.Lock()
|
||||||
c := Config{MaxVars: 64, DBPath: "db"} // default config
|
c := Config {
|
||||||
|
configured: true,
|
||||||
|
MaxVars: 64, // default config
|
||||||
|
DBPath: "db",
|
||||||
|
}
|
||||||
conf = c
|
conf = c
|
||||||
if len(x) > 0 {
|
if len(x) > 0 {
|
||||||
c = x[0]
|
c = x[0]
|
||||||
}
|
}
|
||||||
if c.MaxVars != 0 {
|
if c.MaxVars != 0 {
|
||||||
conf.MaxVars = c.MaxVars
|
conf.MaxVars = c.MaxVars
|
||||||
conf.configured = true
|
|
||||||
}
|
}
|
||||||
if c.DBPath != "" {
|
if c.DBPath != "" {
|
||||||
conf.DBPath = c.DBPath
|
conf.DBPath = c.DBPath
|
||||||
conf.configured = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.Tidy.Interval == 0 {
|
||||||
|
conf.Tidy.Interval = 10 * time.Second
|
||||||
|
} else {
|
||||||
|
fmt.Println("Setting conf.Tidy.Interval to",c.Tidy.Interval)
|
||||||
|
conf.Tidy.Interval = c.Tidy.Interval
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Tidy.Func == nil {
|
||||||
|
conf.Tidy.Func = ExpireAfter(24 * time.Hour)
|
||||||
|
} else {
|
||||||
|
fmt.Println("Setting conf.Tidy.Func")
|
||||||
|
conf.Tidy.Func = c.Tidy.Func
|
||||||
|
}
|
||||||
|
|
||||||
mux.Unlock()
|
mux.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,7 +292,9 @@ func start() {
|
||||||
launched = true
|
launched = true
|
||||||
|
|
||||||
if conf.configured == false {
|
if conf.configured == false {
|
||||||
|
mux.Unlock()
|
||||||
Init()
|
Init()
|
||||||
|
mux.Lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
@ -423,6 +443,38 @@ func retrieve(name string, ts ...time.Time) ([]byte, time.Time, error) {
|
||||||
return ret, t, err
|
return ret, t, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TidyFunc func(*bolt.Bucket) int
|
||||||
|
|
||||||
|
type TidyConfig struct {
|
||||||
|
Interval time.Duration
|
||||||
|
Func TidyFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExpireAfter(exp time.Duration) TidyFunc {
|
||||||
|
if exp > 0 {
|
||||||
|
exp = -1 * exp
|
||||||
|
}
|
||||||
|
fmt.Println("ExpireAfter(",exp,")")
|
||||||
|
return func(b *bolt.Bucket) int {
|
||||||
|
stime := time.Now()
|
||||||
|
etime := stime.Add(exp)
|
||||||
|
i := 0
|
||||||
|
c := b.Cursor()
|
||||||
|
end,_ := c.Last() // always keep the most recent on
|
||||||
|
for k,_ := c.First(); time.Since(stime) < 10 * time.Millisecond; k,_ = c.Next() {
|
||||||
|
if tdecode(k).After(etime) {
|
||||||
|
return i // entry not expired
|
||||||
|
}
|
||||||
|
if reflect.DeepEqual(k,end) {
|
||||||
|
return i // always keep the most recent entry
|
||||||
|
}
|
||||||
|
b.Delete(k)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func tidyThread() {
|
func tidyThread() {
|
||||||
fmt.Println("tidyThread() starting")
|
fmt.Println("tidyThread() starting")
|
||||||
lchan := make(chan string)
|
lchan := make(chan string)
|
||||||
|
@ -442,7 +494,7 @@ func tidyThread() {
|
||||||
close(lchan)
|
close(lchan)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
tick := time.NewTicker(time.Second * 10)
|
tick := time.NewTicker(conf.Tidy.Interval)
|
||||||
for { select {
|
for { select {
|
||||||
case <-tchan:
|
case <-tchan:
|
||||||
fmt.Println("closing loaded channel")
|
fmt.Println("closing loaded channel")
|
||||||
|
@ -457,12 +509,9 @@ func tidyThread() {
|
||||||
} }
|
} }
|
||||||
}
|
}
|
||||||
|
|
||||||
const expiration time.Duration = -24 * time.Hour
|
|
||||||
|
|
||||||
// discard entries if they are too old.
|
// discard entries if they are too old.
|
||||||
func Tidy(name string) {
|
func Tidy(name string) {
|
||||||
stime := time.Now()
|
stime := time.Now()
|
||||||
etime := stime.Add(expiration)
|
|
||||||
mux.Lock()
|
mux.Lock()
|
||||||
i := 0
|
i := 0
|
||||||
db.Update(func(tx *bolt.Tx) error {
|
db.Update(func(tx *bolt.Tx) error {
|
||||||
|
@ -471,19 +520,7 @@ func Tidy(name string) {
|
||||||
fmt.Println("Can't open bucket for ",name)
|
fmt.Println("Can't open bucket for ",name)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
c := b.Cursor()
|
i = conf.Tidy.Func(b)
|
||||||
end,_ := c.Last() // always keep the most recent on
|
|
||||||
for time.Since(stime) < 10 * time.Millisecond {
|
|
||||||
k,_ := c.First()
|
|
||||||
if tdecode(k).After(etime) {
|
|
||||||
return nil // entry not expired
|
|
||||||
}
|
|
||||||
if reflect.DeepEqual(k,end) {
|
|
||||||
return nil // always keep the most recent entry
|
|
||||||
}
|
|
||||||
b.Delete(k)
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
mux.Unlock()
|
mux.Unlock()
|
||||||
|
|
27
test/tidy/main.go
Normal file
27
test/tidy/main.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
"gitlab.wow.st/gmp/persist"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
tc := persist.TidyConfig{
|
||||||
|
Interval: 2 * time.Second,
|
||||||
|
Func:persist.ExpireAfter(-5 * time.Second),
|
||||||
|
}
|
||||||
|
persist.Init(persist.Config{Tidy: tc})
|
||||||
|
|
||||||
|
x := persistInt("x",0)
|
||||||
|
persist.Commit()
|
||||||
|
x.Set(2)
|
||||||
|
persist.Commit()
|
||||||
|
x.Set(3)
|
||||||
|
persist.Commit()
|
||||||
|
fmt.Println(x.History())
|
||||||
|
time.Sleep(time.Second * 15)
|
||||||
|
fmt.Println(x.History())
|
||||||
|
persist.Shutdown()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user