Open okhowang opened 3 years ago
I faced a similar problem when trying to use Marshal with Loadable for Redis, they both do not work together.
I exteded Loadable with Marshal, but I'm not sure if it is the correct way to do that.
package cache
import (
"github.com/vmihailenco/msgpack"
)
type Marshaler struct {
LoadableCache
}
func NewMarshaler(loadFunc loadFunction, cache CacheInterface) *Marshaler {
m := Marshaler{}
loadable := &LoadableCache{
loadFunc: loadFunc,
cache: cache,
}
m.LoadableCache = *loadable
m.setChannel = make(chan *loadableKeyValue, 10000)
go m.setter()
return &m
}
func (c *Marshaler) setter() {
for item := range c.setChannel {
bytes, err := msgpack.Marshal(item.value)
if err != nil {
continue
}
c.Set(item.key, bytes, nil)
}
}
// Get obtains a value from cache and unmarshal value with given object
func (m *Marshaler) Get(key interface{}, returnObj interface{}) (interface{}, error) {
result, err := m.cache.Get(key)
if err != nil {
// Unable to find in cache, try to load it from load function
result, err = m.loadFunc(key)
if err != nil {
return nil, err
}
// Then, put it back in cache
m.setChannel <- &loadableKeyValue{key, result}
return result, nil
}
switch v := result.(type) {
case []byte:
err = msgpack.Unmarshal(v, returnObj)
case string:
err = msgpack.Unmarshal([]byte(v), returnObj)
}
if err != nil {
return nil, err
}
return returnObj, nil
}
my solution is make load function return a []byte
and wrap loadable with marshaler
bc, err := bigcache.NewBigCache(bigcache.DefaultConfig(time.Minute))
if err != nil {
panic(err)
}
return marshaler.New(cache.NewLoadable(func(key interface{}) (interface{}, error) {
value, err := loadFunction(key)
if err != nil {
return nil, err
}
return msgpack.Marshal(value)
}, cache.New(store.NewBigcache(bc, nil)))), nil
but it's depend on that marshaler
use msgpack
Now that Loadable cache support generics, I think we should make Marshaler support for generics too.
my solution is make load function return a []byte
nice workaround. Although this couples the loader function with the marshaling process, which isn't ideal. Ideally, loader function should just return (struct, error), nothing less nothing more. @okhowang
Now that Loadable cache support generics, I think we should make Marshaler support for generics too.
Any timeline we can expect this to be supported? Also can we support json
marshaler? Though we can write our own marshaler, I still think json
marshaler is a sensible battery-included solution. @eko
I had to write my own Marshaler, which works over store, not over cache interface. It should fit better also in this case
I use gocache as a cachable mysql wrapper.
but there is panic as below
Loadable
set value directly to bigcache which accept[]byte
only.make
Marshaler
asCacheInterface
may be ok.