Add caching option for database interface

This commit is contained in:
Daniel 2018-10-22 17:06:49 +02:00
parent ddc5465b08
commit 9d5a97c20b

View file

@ -3,6 +3,9 @@ package database
import ( import (
"errors" "errors"
"fmt" "fmt"
"time"
"github.com/bluele/gcache"
"github.com/Safing/portbase/database/accessor" "github.com/Safing/portbase/database/accessor"
"github.com/Safing/portbase/database/iterator" "github.com/Safing/portbase/database/iterator"
@ -17,14 +20,18 @@ const (
// Interface provides a method to access the database with attached options. // Interface provides a method to access the database with attached options.
type Interface struct { type Interface struct {
options *Options options *Options
cache gcache.Cache
} }
// Options holds options that may be set for an Interface instance. // Options holds options that may be set for an Interface instance.
type Options struct { type Options struct {
Local bool Local bool
Internal bool Internal bool
AlwaysMakeSecret bool AlwaysMakeSecret bool
AlwaysMakeCrownjewel bool AlwaysMakeCrownjewel bool
AlwaysSetRelativateExpiry int64
AlwaysSetAbsoluteExpiry int64
CacheSize int
} }
// Apply applies options to the record metadata. // Apply applies options to the record metadata.
@ -38,6 +45,11 @@ func (o *Options) Apply(r record.Record) {
if o.AlwaysMakeCrownjewel { if o.AlwaysMakeCrownjewel {
r.Meta().MakeCrownJewel() r.Meta().MakeCrownJewel()
} }
if o.AlwaysSetAbsoluteExpiry > 0 {
r.Meta().SetAbsoluteExpiry(o.AlwaysSetAbsoluteExpiry)
} else if o.AlwaysSetRelativateExpiry > 0 {
r.Meta().SetRelativateExpiry(o.AlwaysSetRelativateExpiry)
}
} }
// NewInterface returns a new Interface to the database. // NewInterface returns a new Interface to the database.
@ -46,9 +58,32 @@ func NewInterface(opts *Options) *Interface {
opts = &Options{} opts = &Options{}
} }
return &Interface{ new := &Interface{
options: opts, options: opts,
} }
if opts.CacheSize > 0 {
new.cache = gcache.New(opts.CacheSize).ARC().Expiration(time.Hour).Build()
}
return new
}
func (i *Interface) checkCache(key string) (record.Record, bool) {
if i.cache != nil {
cacheVal, err := i.cache.Get(key)
if err == nil {
r, ok := cacheVal.(record.Record)
if ok {
return r, true
}
}
}
return nil, false
}
func (i *Interface) updateCache(r record.Record) {
if i.cache != nil {
i.cache.Set(r.Key(), r)
}
} }
// Exists return whether a record with the given key exists. // Exists return whether a record with the given key exists.
@ -65,6 +100,14 @@ func (i *Interface) Exists(key string) (bool, error) {
// Get return the record with the given key. // Get return the record with the given key.
func (i *Interface) Get(key string) (record.Record, error) { func (i *Interface) Get(key string) (record.Record, error) {
r, ok := i.checkCache(key)
if ok {
if !r.Meta().CheckPermission(i.options.Local, i.options.Internal) {
return nil, ErrPermissionDenied
}
return r, nil
}
r, _, err := i.getRecord(getDBFromKey, key, true, false) r, _, err := i.getRecord(getDBFromKey, key, true, false)
return r, err return r, err
} }
@ -136,6 +179,8 @@ func (i *Interface) Put(r record.Record) error {
} }
i.options.Apply(r) i.options.Apply(r)
i.updateCache(r)
return db.Put(r) return db.Put(r)
} }
@ -146,8 +191,9 @@ func (i *Interface) PutNew(r record.Record) error {
return err return err
} }
i.options.Apply(r)
r.Meta().Reset() r.Meta().Reset()
i.options.Apply(r)
i.updateCache(r)
return db.Put(r) return db.Put(r)
} }