replace wrappers with hooks
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
package store
|
||||
package memory
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -6,13 +6,15 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/patrickmn/go-cache"
|
||||
cache "github.com/patrickmn/go-cache"
|
||||
"go.unistack.org/micro/v3/options"
|
||||
"go.unistack.org/micro/v3/store"
|
||||
)
|
||||
|
||||
// NewStore returns a memory store
|
||||
func NewStore(opts ...Option) Store {
|
||||
func NewStore(opts ...store.Option) store.Store {
|
||||
return &memoryStore{
|
||||
opts: NewOptions(opts...),
|
||||
opts: store.NewOptions(opts...),
|
||||
store: cache.New(cache.NoExpiration, 5*time.Minute),
|
||||
}
|
||||
}
|
||||
@@ -27,8 +29,13 @@ func (m *memoryStore) Disconnect(ctx context.Context) error {
|
||||
}
|
||||
|
||||
type memoryStore struct {
|
||||
store *cache.Cache
|
||||
opts Options
|
||||
funcRead store.FuncRead
|
||||
funcWrite store.FuncWrite
|
||||
funcExists store.FuncExists
|
||||
funcList store.FuncList
|
||||
funcDelete store.FuncDelete
|
||||
store *cache.Cache
|
||||
opts store.Options
|
||||
}
|
||||
|
||||
func (m *memoryStore) key(prefix, key string) string {
|
||||
@@ -39,7 +46,7 @@ func (m *memoryStore) exists(prefix, key string) error {
|
||||
key = m.key(prefix, key)
|
||||
_, found := m.store.Get(key)
|
||||
if !found {
|
||||
return ErrNotFound
|
||||
return store.ErrNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -50,12 +57,12 @@ func (m *memoryStore) get(prefix, key string, val interface{}) error {
|
||||
|
||||
r, found := m.store.Get(key)
|
||||
if !found {
|
||||
return ErrNotFound
|
||||
return store.ErrNotFound
|
||||
}
|
||||
|
||||
buf, ok := r.([]byte)
|
||||
if !ok {
|
||||
return ErrNotFound
|
||||
return store.ErrNotFound
|
||||
}
|
||||
|
||||
return m.opts.Codec.Unmarshal(buf, val)
|
||||
@@ -100,10 +107,32 @@ func (m *memoryStore) list(prefix string, limit, offset uint) []string {
|
||||
return allKeys
|
||||
}
|
||||
|
||||
func (m *memoryStore) Init(opts ...Option) error {
|
||||
func (m *memoryStore) Init(opts ...store.Option) error {
|
||||
for _, o := range opts {
|
||||
o(&m.opts)
|
||||
}
|
||||
|
||||
m.funcRead = m.fnRead
|
||||
m.funcWrite = m.fnWrite
|
||||
m.funcExists = m.fnExists
|
||||
m.funcList = m.fnList
|
||||
m.funcDelete = m.fnDelete
|
||||
|
||||
m.opts.Hooks.EachNext(func(hook options.Hook) {
|
||||
switch h := hook.(type) {
|
||||
case store.HookRead:
|
||||
m.funcRead = h(m.funcRead)
|
||||
case store.HookWrite:
|
||||
m.funcWrite = h(m.funcWrite)
|
||||
case store.HookExists:
|
||||
m.funcExists = h(m.funcExists)
|
||||
case store.HookList:
|
||||
m.funcList = h(m.funcList)
|
||||
case store.HookDelete:
|
||||
m.funcDelete = h(m.funcDelete)
|
||||
}
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -115,24 +144,36 @@ func (m *memoryStore) Name() string {
|
||||
return m.opts.Name
|
||||
}
|
||||
|
||||
func (m *memoryStore) Exists(ctx context.Context, key string, opts ...ExistsOption) error {
|
||||
options := NewExistsOptions(opts...)
|
||||
func (m *memoryStore) Exists(ctx context.Context, key string, opts ...store.ExistsOption) error {
|
||||
return m.funcExists(ctx, key, opts...)
|
||||
}
|
||||
|
||||
func (m *memoryStore) fnExists(ctx context.Context, key string, opts ...store.ExistsOption) error {
|
||||
options := store.NewExistsOptions(opts...)
|
||||
if options.Namespace == "" {
|
||||
options.Namespace = m.opts.Namespace
|
||||
}
|
||||
return m.exists(options.Namespace, key)
|
||||
}
|
||||
|
||||
func (m *memoryStore) Read(ctx context.Context, key string, val interface{}, opts ...ReadOption) error {
|
||||
options := NewReadOptions(opts...)
|
||||
func (m *memoryStore) Read(ctx context.Context, key string, val interface{}, opts ...store.ReadOption) error {
|
||||
return m.funcRead(ctx, key, val, opts...)
|
||||
}
|
||||
|
||||
func (m *memoryStore) fnRead(ctx context.Context, key string, val interface{}, opts ...store.ReadOption) error {
|
||||
options := store.NewReadOptions(opts...)
|
||||
if options.Namespace == "" {
|
||||
options.Namespace = m.opts.Namespace
|
||||
}
|
||||
return m.get(options.Namespace, key, val)
|
||||
}
|
||||
|
||||
func (m *memoryStore) Write(ctx context.Context, key string, val interface{}, opts ...WriteOption) error {
|
||||
options := NewWriteOptions(opts...)
|
||||
func (m *memoryStore) Write(ctx context.Context, key string, val interface{}, opts ...store.WriteOption) error {
|
||||
return m.funcWrite(ctx, key, val, opts...)
|
||||
}
|
||||
|
||||
func (m *memoryStore) fnWrite(ctx context.Context, key string, val interface{}, opts ...store.WriteOption) error {
|
||||
options := store.NewWriteOptions(opts...)
|
||||
if options.Namespace == "" {
|
||||
options.Namespace = m.opts.Namespace
|
||||
}
|
||||
@@ -151,8 +192,12 @@ func (m *memoryStore) Write(ctx context.Context, key string, val interface{}, op
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *memoryStore) Delete(ctx context.Context, key string, opts ...DeleteOption) error {
|
||||
options := NewDeleteOptions(opts...)
|
||||
func (m *memoryStore) Delete(ctx context.Context, key string, opts ...store.DeleteOption) error {
|
||||
return m.funcDelete(ctx, key, opts...)
|
||||
}
|
||||
|
||||
func (m *memoryStore) fnDelete(ctx context.Context, key string, opts ...store.DeleteOption) error {
|
||||
options := store.NewDeleteOptions(opts...)
|
||||
if options.Namespace == "" {
|
||||
options.Namespace = m.opts.Namespace
|
||||
}
|
||||
@@ -161,12 +206,16 @@ func (m *memoryStore) Delete(ctx context.Context, key string, opts ...DeleteOpti
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *memoryStore) Options() Options {
|
||||
func (m *memoryStore) Options() store.Options {
|
||||
return m.opts
|
||||
}
|
||||
|
||||
func (m *memoryStore) List(ctx context.Context, opts ...ListOption) ([]string, error) {
|
||||
options := NewListOptions(opts...)
|
||||
func (m *memoryStore) List(ctx context.Context, opts ...store.ListOption) ([]string, error) {
|
||||
return m.funcList(ctx, opts...)
|
||||
}
|
||||
|
||||
func (m *memoryStore) fnList(ctx context.Context, opts ...store.ListOption) ([]string, error) {
|
||||
options := store.NewListOptions(opts...)
|
||||
if options.Namespace == "" {
|
||||
options.Namespace = m.opts.Namespace
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package store_test
|
||||
package memory
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,8 +8,41 @@ import (
|
||||
"go.unistack.org/micro/v3/store"
|
||||
)
|
||||
|
||||
type testHook struct {
|
||||
f bool
|
||||
}
|
||||
|
||||
func (t *testHook) Exists(fn store.FuncExists) store.FuncExists {
|
||||
return func(ctx context.Context, key string, opts ...store.ExistsOption) error {
|
||||
t.f = true
|
||||
return fn(ctx, key, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHook(t *testing.T) {
|
||||
h := &testHook{}
|
||||
|
||||
s := NewStore(store.Hooks(store.HookExists(h.Exists)))
|
||||
|
||||
if err := s.Init(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := s.Write(context.TODO(), "test", nil); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if err := s.Exists(context.TODO(), "test"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !h.f {
|
||||
t.Fatal("hook not works")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMemoryReInit(t *testing.T) {
|
||||
s := store.NewStore(store.Namespace("aaa"))
|
||||
s := NewStore(store.Namespace("aaa"))
|
||||
if err := s.Init(store.Namespace("")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -19,7 +52,7 @@ func TestMemoryReInit(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMemoryBasic(t *testing.T) {
|
||||
s := store.NewStore()
|
||||
s := NewStore()
|
||||
if err := s.Init(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -27,7 +60,7 @@ func TestMemoryBasic(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMemoryPrefix(t *testing.T) {
|
||||
s := store.NewStore()
|
||||
s := NewStore()
|
||||
if err := s.Init(store.Namespace("some-prefix")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -35,7 +68,7 @@ func TestMemoryPrefix(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMemoryNamespace(t *testing.T) {
|
||||
s := store.NewStore()
|
||||
s := NewStore()
|
||||
if err := s.Init(store.Namespace("some-namespace")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -43,7 +76,7 @@ func TestMemoryNamespace(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMemoryNamespacePrefix(t *testing.T) {
|
||||
s := store.NewStore()
|
||||
s := NewStore()
|
||||
if err := s.Init(store.Namespace("some-namespace")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
147
store/noop.go
Normal file
147
store/noop.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.unistack.org/micro/v3/options"
|
||||
)
|
||||
|
||||
var _ Store = (*noopStore)(nil)
|
||||
|
||||
type noopStore struct {
|
||||
funcRead FuncRead
|
||||
funcWrite FuncWrite
|
||||
funcExists FuncExists
|
||||
funcList FuncList
|
||||
funcDelete FuncDelete
|
||||
opts Options
|
||||
}
|
||||
|
||||
func NewStore(opts ...Option) *noopStore {
|
||||
options := NewOptions(opts...)
|
||||
return &noopStore{opts: options}
|
||||
}
|
||||
|
||||
func (n *noopStore) Init(opts ...Option) error {
|
||||
for _, o := range opts {
|
||||
o(&n.opts)
|
||||
}
|
||||
|
||||
n.funcRead = n.fnRead
|
||||
n.funcWrite = n.fnWrite
|
||||
n.funcExists = n.fnExists
|
||||
n.funcList = n.fnList
|
||||
n.funcDelete = n.fnDelete
|
||||
|
||||
n.opts.Hooks.EachNext(func(hook options.Hook) {
|
||||
switch h := hook.(type) {
|
||||
case HookRead:
|
||||
n.funcRead = h(n.funcRead)
|
||||
case HookWrite:
|
||||
n.funcWrite = h(n.funcWrite)
|
||||
case HookExists:
|
||||
n.funcExists = h(n.funcExists)
|
||||
case HookList:
|
||||
n.funcList = h(n.funcList)
|
||||
case HookDelete:
|
||||
n.funcDelete = h(n.funcDelete)
|
||||
}
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *noopStore) Connect(ctx context.Context) error {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *noopStore) Disconnect(ctx context.Context) error {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *noopStore) Read(ctx context.Context, key string, val interface{}, opts ...ReadOption) error {
|
||||
return n.funcRead(ctx, key, val, opts...)
|
||||
}
|
||||
|
||||
func (n *noopStore) fnRead(ctx context.Context, key string, val interface{}, opts ...ReadOption) error {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *noopStore) Delete(ctx context.Context, key string, opts ...DeleteOption) error {
|
||||
return n.funcDelete(ctx, key, opts...)
|
||||
}
|
||||
|
||||
func (n *noopStore) fnDelete(ctx context.Context, key string, opts ...DeleteOption) error {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *noopStore) Exists(ctx context.Context, key string, opts ...ExistsOption) error {
|
||||
return n.funcExists(ctx, key, opts...)
|
||||
}
|
||||
|
||||
func (n *noopStore) fnExists(ctx context.Context, key string, opts ...ExistsOption) error {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *noopStore) Write(ctx context.Context, key string, val interface{}, opts ...WriteOption) error {
|
||||
return n.funcWrite(ctx, key, val, opts...)
|
||||
}
|
||||
|
||||
func (n *noopStore) fnWrite(ctx context.Context, key string, val interface{}, opts ...WriteOption) error {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *noopStore) List(ctx context.Context, opts ...ListOption) ([]string, error) {
|
||||
return n.funcList(ctx, opts...)
|
||||
}
|
||||
|
||||
func (n *noopStore) fnList(ctx context.Context, opts ...ListOption) ([]string, error) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
default:
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (n *noopStore) Name() string {
|
||||
return n.opts.Name
|
||||
}
|
||||
|
||||
func (n *noopStore) String() string {
|
||||
return "noop"
|
||||
}
|
||||
|
||||
func (n *noopStore) Options() Options {
|
||||
return n.opts
|
||||
}
|
||||
35
store/noop_test.go
Normal file
35
store/noop_test.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testHook struct {
|
||||
f bool
|
||||
}
|
||||
|
||||
func (t *testHook) Exists(fn FuncExists) FuncExists {
|
||||
return func(ctx context.Context, key string, opts ...ExistsOption) error {
|
||||
t.f = true
|
||||
return fn(ctx, key, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHook(t *testing.T) {
|
||||
h := &testHook{}
|
||||
|
||||
s := NewStore(Hooks(HookExists(h.Exists)))
|
||||
|
||||
if err := s.Init(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := s.Exists(context.TODO(), "test"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !h.f {
|
||||
t.Fatal("hook not works")
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"go.unistack.org/micro/v3/logger"
|
||||
"go.unistack.org/micro/v3/metadata"
|
||||
"go.unistack.org/micro/v3/meter"
|
||||
"go.unistack.org/micro/v3/options"
|
||||
"go.unistack.org/micro/v3/tracer"
|
||||
)
|
||||
|
||||
@@ -38,6 +39,8 @@ type Options struct {
|
||||
// Wrappers []Wrapper
|
||||
// Timeout specifies timeout duration for all operations
|
||||
Timeout time.Duration
|
||||
// Hooks can be run before/after store Read/List/Write/Exists/Delete
|
||||
Hooks options.Hooks
|
||||
}
|
||||
|
||||
// NewOptions creates options struct
|
||||
@@ -441,11 +444,9 @@ func ExistsTimeout(td time.Duration) ExistsOption {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// WrapStore adds a store Wrapper to a list of options passed into the store
|
||||
func WrapStore(w Wrapper) Option {
|
||||
// Hooks sets hook runs before action
|
||||
func Hooks(h ...options.Hook) Option {
|
||||
return func(o *Options) {
|
||||
o.Wrappers = append(o.Wrappers, w)
|
||||
o.Hooks = append(o.Hooks, h...)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,7 @@ var (
|
||||
|
||||
// Store is a data storage interface
|
||||
type Store interface {
|
||||
// Name returns store name
|
||||
Name() string
|
||||
// Init initialises the store
|
||||
Init(opts ...Option) error
|
||||
@@ -41,3 +42,16 @@ type Store interface {
|
||||
// String returns the name of the implementation.
|
||||
String() string
|
||||
}
|
||||
|
||||
type (
|
||||
FuncExists func(ctx context.Context, key string, opts ...ExistsOption) error
|
||||
HookExists func(next FuncExists) FuncExists
|
||||
FuncRead func(ctx context.Context, key string, val interface{}, opts ...ReadOption) error
|
||||
HookRead func(next FuncRead) FuncRead
|
||||
FuncWrite func(ctx context.Context, key string, val interface{}, opts ...WriteOption) error
|
||||
HookWrite func(next FuncWrite) FuncWrite
|
||||
FuncDelete func(ctx context.Context, key string, opts ...DeleteOption) error
|
||||
HookDelete func(next FuncDelete) FuncDelete
|
||||
FuncList func(ctx context.Context, opts ...ListOption) ([]string, error)
|
||||
HookList func(next FuncList) FuncList
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user