2019-06-12 07:46:20 +01:00
|
|
|
// Package memory is a in-memory store store
|
2019-06-11 17:49:34 +01:00
|
|
|
package memory
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2019-06-12 12:45:42 +01:00
|
|
|
"github.com/micro/go-micro/config/options"
|
2019-10-03 09:46:20 +01:00
|
|
|
"github.com/micro/go-micro/store"
|
2019-06-11 17:49:34 +01:00
|
|
|
)
|
|
|
|
|
2019-06-12 07:46:20 +01:00
|
|
|
type memoryStore struct {
|
2019-06-11 17:49:34 +01:00
|
|
|
options.Options
|
|
|
|
|
|
|
|
sync.RWMutex
|
|
|
|
values map[string]*memoryRecord
|
|
|
|
}
|
|
|
|
|
|
|
|
type memoryRecord struct {
|
2019-06-12 07:46:20 +01:00
|
|
|
r *store.Record
|
2019-06-11 17:49:34 +01:00
|
|
|
c time.Time
|
|
|
|
}
|
|
|
|
|
2019-10-23 22:05:39 +01:00
|
|
|
func (m *memoryStore) List() ([]*store.Record, error) {
|
2019-06-11 17:49:34 +01:00
|
|
|
m.RLock()
|
|
|
|
defer m.RUnlock()
|
|
|
|
|
2019-12-03 22:59:44 +03:00
|
|
|
//nolint:prealloc
|
2019-06-12 07:46:20 +01:00
|
|
|
var values []*store.Record
|
2019-06-11 17:49:34 +01:00
|
|
|
|
|
|
|
for _, v := range m.values {
|
|
|
|
// get expiry
|
|
|
|
d := v.r.Expiry
|
|
|
|
t := time.Since(v.c)
|
|
|
|
|
2019-07-11 12:58:20 +08:00
|
|
|
if d > time.Duration(0) {
|
2019-07-11 14:13:58 +08:00
|
|
|
// expired
|
|
|
|
if t > d {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// update expiry
|
2019-07-11 12:58:20 +08:00
|
|
|
v.r.Expiry -= t
|
|
|
|
v.c = time.Now()
|
|
|
|
}
|
2019-07-11 12:51:55 +08:00
|
|
|
|
2019-06-11 17:49:34 +01:00
|
|
|
values = append(values, v.r)
|
|
|
|
}
|
|
|
|
|
|
|
|
return values, nil
|
|
|
|
}
|
|
|
|
|
2019-10-11 14:08:50 +01:00
|
|
|
func (m *memoryStore) Read(keys ...string) ([]*store.Record, error) {
|
2019-06-11 17:49:34 +01:00
|
|
|
m.RLock()
|
|
|
|
defer m.RUnlock()
|
|
|
|
|
2019-12-03 22:59:44 +03:00
|
|
|
//nolint:prealloc
|
2019-10-11 14:08:50 +01:00
|
|
|
var records []*store.Record
|
2019-06-11 17:49:34 +01:00
|
|
|
|
2019-10-11 14:08:50 +01:00
|
|
|
for _, key := range keys {
|
|
|
|
v, ok := m.values[key]
|
|
|
|
if !ok {
|
2019-07-11 14:13:58 +08:00
|
|
|
return nil, store.ErrNotFound
|
|
|
|
}
|
2019-10-11 14:08:50 +01:00
|
|
|
|
|
|
|
// get expiry
|
|
|
|
d := v.r.Expiry
|
|
|
|
t := time.Since(v.c)
|
|
|
|
|
|
|
|
// expired
|
|
|
|
if d > time.Duration(0) {
|
|
|
|
if t > d {
|
|
|
|
return nil, store.ErrNotFound
|
|
|
|
}
|
|
|
|
// update expiry
|
|
|
|
v.r.Expiry -= t
|
|
|
|
v.c = time.Now()
|
|
|
|
}
|
|
|
|
|
|
|
|
records = append(records, v.r)
|
2019-07-11 12:58:20 +08:00
|
|
|
}
|
2019-07-11 12:51:55 +08:00
|
|
|
|
2019-10-11 14:08:50 +01:00
|
|
|
return records, nil
|
2019-06-11 17:49:34 +01:00
|
|
|
}
|
|
|
|
|
2019-10-11 14:08:50 +01:00
|
|
|
func (m *memoryStore) Write(records ...*store.Record) error {
|
2019-06-11 17:49:34 +01:00
|
|
|
m.Lock()
|
|
|
|
defer m.Unlock()
|
|
|
|
|
2019-10-11 14:08:50 +01:00
|
|
|
for _, r := range records {
|
|
|
|
// set the record
|
|
|
|
m.values[r.Key] = &memoryRecord{
|
|
|
|
r: r,
|
|
|
|
c: time.Now(),
|
|
|
|
}
|
2019-06-11 17:49:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-10-11 14:08:50 +01:00
|
|
|
func (m *memoryStore) Delete(keys ...string) error {
|
2019-06-11 17:49:34 +01:00
|
|
|
m.Lock()
|
|
|
|
defer m.Unlock()
|
|
|
|
|
2019-10-11 14:08:50 +01:00
|
|
|
for _, key := range keys {
|
|
|
|
// delete the value
|
|
|
|
delete(m.values, key)
|
|
|
|
}
|
2019-06-11 17:49:34 +01:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-06-12 07:46:20 +01:00
|
|
|
// NewStore returns a new store.Store
|
|
|
|
func NewStore(opts ...options.Option) store.Store {
|
2019-06-11 17:49:34 +01:00
|
|
|
options := options.NewOptions(opts...)
|
|
|
|
|
2019-06-12 07:46:20 +01:00
|
|
|
return &memoryStore{
|
2019-06-11 17:49:34 +01:00
|
|
|
Options: options,
|
|
|
|
values: make(map[string]*memoryRecord),
|
|
|
|
}
|
|
|
|
}
|