diff --git a/store/file.go b/store/file/file.go similarity index 87% rename from store/file.go rename to store/file/file.go index 48ce626e..c1159622 100644 --- a/store/file.go +++ b/store/file/file.go @@ -1,4 +1,4 @@ -package store +package file import ( "context" @@ -10,6 +10,7 @@ import ( "sync" "time" + "go-micro.dev/v5/store" bolt "go.etcd.io/bbolt" ) @@ -26,7 +27,7 @@ var ( dataBucket = "data" ) -func NewFileStore(opts ...Option) Store { +func NewStore(opts ...store.Option) store.Store { s := &fileStore{ handles: make(map[string]*fileHandle), } @@ -35,7 +36,7 @@ func NewFileStore(opts ...Option) Store { } type fileStore struct { - options Options + options store.Options dir string // the database handle @@ -70,7 +71,7 @@ func (m *fileStore) delete(fd *fileHandle, key string) error { }) } -func (m *fileStore) init(opts ...Option) error { +func (m *fileStore) init(opts ...store.Option) error { for _, o := range opts { o(&m.options) } @@ -206,7 +207,7 @@ func (m *fileStore) list(fd *fileHandle, limit, offset uint) []string { return allKeys } -func (m *fileStore) get(fd *fileHandle, k string) (*Record, error) { +func (m *fileStore) get(fd *fileHandle, k string) (*store.Record, error) { var value []byte fd.db.View(func(tx *bolt.Tx) error { @@ -221,7 +222,7 @@ func (m *fileStore) get(fd *fileHandle, k string) (*Record, error) { }) if value == nil { - return nil, ErrNotFound + return nil, store.ErrNotFound } storedRecord := &record{} @@ -230,7 +231,7 @@ func (m *fileStore) get(fd *fileHandle, k string) (*Record, error) { return nil, err } - newRecord := &Record{} + newRecord := &store.Record{} newRecord.Key = storedRecord.Key newRecord.Value = storedRecord.Value newRecord.Metadata = make(map[string]interface{}) @@ -241,7 +242,7 @@ func (m *fileStore) get(fd *fileHandle, k string) (*Record, error) { if !storedRecord.ExpiresAt.IsZero() { if storedRecord.ExpiresAt.Before(time.Now()) { - return nil, ErrNotFound + return nil, store.ErrNotFound } newRecord.Expiry = time.Until(storedRecord.ExpiresAt) } @@ -249,7 +250,7 @@ func (m *fileStore) get(fd *fileHandle, k string) (*Record, error) { return newRecord, nil } -func (m *fileStore) set(fd *fileHandle, r *Record) error { +func (m *fileStore) set(fd *fileHandle, r *store.Record) error { // copy the incoming record and then // convert the expiry in to a hard timestamp item := &record{} @@ -291,12 +292,12 @@ func (f *fileStore) Close() error { return nil } -func (f *fileStore) Init(opts ...Option) error { +func (f *fileStore) Init(opts ...store.Option) error { return f.init(opts...) } -func (m *fileStore) Delete(key string, opts ...DeleteOption) error { - var deleteOptions DeleteOptions +func (m *fileStore) Delete(key string, opts ...store.DeleteOption) error { + var deleteOptions store.DeleteOptions for _, o := range opts { o(&deleteOptions) } @@ -309,8 +310,8 @@ func (m *fileStore) Delete(key string, opts ...DeleteOption) error { return m.delete(fd, key) } -func (m *fileStore) Read(key string, opts ...ReadOption) ([]*Record, error) { - var readOpts ReadOptions +func (m *fileStore) Read(key string, opts ...store.ReadOption) ([]*store.Record, error) { + var readOpts store.ReadOptions for _, o := range opts { o(&readOpts) } @@ -342,7 +343,7 @@ func (m *fileStore) Read(key string, opts ...ReadOption) ([]*Record, error) { keys = []string{key} } - var results []*Record + var results []*store.Record for _, k := range keys { r, err := m.get(fd, k) @@ -355,8 +356,8 @@ func (m *fileStore) Read(key string, opts ...ReadOption) ([]*Record, error) { return results, nil } -func (m *fileStore) Write(r *Record, opts ...WriteOption) error { - var writeOpts WriteOptions +func (m *fileStore) Write(r *store.Record, opts ...store.WriteOption) error { + var writeOpts store.WriteOptions for _, o := range opts { o(&writeOpts) } @@ -368,7 +369,7 @@ func (m *fileStore) Write(r *Record, opts ...WriteOption) error { if len(opts) > 0 { // Copy the record before applying options, or the incoming record will be mutated - newRecord := Record{} + newRecord := store.Record{} newRecord.Key = r.Key newRecord.Value = r.Value newRecord.Metadata = make(map[string]interface{}) @@ -391,12 +392,12 @@ func (m *fileStore) Write(r *Record, opts ...WriteOption) error { return m.set(fd, r) } -func (m *fileStore) Options() Options { +func (m *fileStore) Options() store.Options { return m.options } -func (m *fileStore) List(opts ...ListOption) ([]string, error) { - var listOptions ListOptions +func (m *fileStore) List(opts ...store.ListOption) ([]string, error) { + var listOptions store.ListOptions for _, o := range opts { o(&listOptions) @@ -439,9 +440,9 @@ func (m *fileStore) String() string { type dirOptionKey struct{} -// DirOption is a file store Option to set the directory for the file -func DirOption(dir string) Option { - return func(o *Options) { +// DirOption is a file store store.Option to set the directory for the file +func DirOption(dir string) store.Option { + return func(o *store.Options) { if o.Context == nil { o.Context = context.Background() } diff --git a/store/file_test.go b/store/file/file_test.go similarity index 70% rename from store/file_test.go rename to store/file/file_test.go index 7e689628..b4f42b58 100644 --- a/store/file_test.go +++ b/store/file/file_test.go @@ -1,4 +1,4 @@ -package store +package file import ( "fmt" @@ -10,18 +10,19 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/kr/pretty" + "go-micro.dev/v5/store" ) -func cleanup(db string, s Store) { +func cleanup(db string, s store.Store) { s.Close() dir := filepath.Join(DefaultDir, db+"/") os.RemoveAll(dir) } func TestFileStoreReInit(t *testing.T) { - s := NewStore(Table("aaa")) + s := NewStore(store.Table("aaa")) defer cleanup(DefaultDatabase, s) - s.Init(Table("bbb")) + s.Init(store.Table("bbb")) if s.Options().Table != "bbb" { t.Error("Init didn't reinitialise the store") } @@ -34,29 +35,29 @@ func TestFileStoreBasic(t *testing.T) { } func TestFileStoreTable(t *testing.T) { - s := NewStore(Table("testTable")) + s := NewStore(store.Table("teststore.Table")) defer cleanup(DefaultDatabase, s) fileTest(s, t) } func TestFileStoreDatabase(t *testing.T) { - s := NewStore(Database("testdb")) + s := NewStore(store.Database("testdb")) defer cleanup("testdb", s) fileTest(s, t) } func TestFileStoreDatabaseTable(t *testing.T) { - s := NewStore(Table("testTable"), Database("testdb")) + s := NewStore(store.Table("teststore.Table"), store.Database("testdb")) defer cleanup("testdb", s) fileTest(s, t) } -func fileTest(s Store, t *testing.T) { +func fileTest(s store.Store, t *testing.T) { if len(os.Getenv("IN_TRAVIS_CI")) == 0 { t.Logf("Options %s %v\n", s.String(), s.Options()) } // Read and Write an expiring Record - if err := s.Write(&Record{ + if err := s.Write(&store.Record{ Key: "Hello", Value: []byte("World"), Expiry: time.Millisecond * 150, @@ -81,12 +82,12 @@ func fileTest(s Store, t *testing.T) { // wait for expiry time.Sleep(time.Millisecond * 200) - if _, err := s.Read("Hello"); err != ErrNotFound { - t.Errorf("Expected %# v, got %# v", ErrNotFound, err) + if _, err := s.Read("Hello"); err != store.ErrNotFound { + t.Errorf("Expected %# v, got %# v", store.ErrNotFound, err) } - // Write 3 records with various expiry and get with Table - records := []*Record{ + // Write 3 records with various expiry and get with store.Table + records := []*store.Record{ { Key: "foo", Value: []byte("foofoo"), @@ -104,30 +105,30 @@ func fileTest(s Store, t *testing.T) { } } - if results, err := s.Read("foo", ReadPrefix()); err != nil { + if results, err := s.Read("foo", store.ReadPrefix()); err != nil { t.Errorf("Couldn't read all \"foo\" keys, got %# v (%s)", spew.Sdump(results), err) } else { if len(results) != 2 { t.Errorf("Expected 2 items, got %d", len(results)) - // t.Logf("Table test: %v\n", spew.Sdump(results)) + // t.Logf("store.Table test: %v\n", spew.Sdump(results)) } } // wait for the expiry time.Sleep(time.Millisecond * 200) - if results, err := s.Read("foo", ReadPrefix()); err != nil { + if results, err := s.Read("foo", store.ReadPrefix()); err != nil { t.Errorf("Couldn't read all \"foo\" keys, got %# v (%s)", spew.Sdump(results), err) } else if len(results) != 1 { t.Errorf("Expected 1 item, got %d", len(results)) - // t.Logf("Table test: %v\n", spew.Sdump(results)) + // t.Logf("store.Table test: %v\n", spew.Sdump(results)) } if err := s.Delete("foo"); err != nil { t.Errorf("Delete failed (%v)", err) } - if results, err := s.Read("foo"); err != ErrNotFound { + if results, err := s.Read("foo"); err != store.ErrNotFound { t.Errorf("Expected read failure read all \"foo\" keys, got %# v (%s)", spew.Sdump(results), err) } else { if len(results) != 0 { @@ -136,7 +137,7 @@ func fileTest(s Store, t *testing.T) { } // Write 3 records with various expiry and get with Suffix - records = []*Record{ + records = []*store.Record{ { Key: "foo", Value: []byte("foofoo"), @@ -158,36 +159,36 @@ func fileTest(s Store, t *testing.T) { t.Errorf("Couldn't write k: %s, v: %# v (%s)", r.Key, pretty.Formatter(r.Value), err) } } - if results, err := s.Read("foo", ReadSuffix()); err != nil { + if results, err := s.Read("foo", store.ReadSuffix()); err != nil { t.Errorf("Couldn't read all \"foo\" keys, got %# v (%s)", spew.Sdump(results), err) } else { if len(results) != 3 { t.Errorf("Expected 3 items, got %d", len(results)) - // t.Logf("Table test: %v\n", spew.Sdump(results)) + // t.Logf("store.Table test: %v\n", spew.Sdump(results)) } } time.Sleep(time.Millisecond * 100) - if results, err := s.Read("foo", ReadSuffix()); err != nil { + if results, err := s.Read("foo", store.ReadSuffix()); err != nil { t.Errorf("Couldn't read all \"foo\" keys, got %# v (%s)", spew.Sdump(results), err) } else { if len(results) != 2 { t.Errorf("Expected 2 items, got %d", len(results)) - // t.Logf("Table test: %v\n", spew.Sdump(results)) + // t.Logf("store.Table test: %v\n", spew.Sdump(results)) } } time.Sleep(time.Millisecond * 100) - if results, err := s.Read("foo", ReadSuffix()); err != nil { + if results, err := s.Read("foo", store.ReadSuffix()); err != nil { t.Errorf("Couldn't read all \"foo\" keys, got %# v (%s)", spew.Sdump(results), err) } else { if len(results) != 1 { t.Errorf("Expected 1 item, got %d", len(results)) - // t.Logf("Table test: %# v\n", spew.Sdump(results)) + // t.Logf("store.Table test: %# v\n", spew.Sdump(results)) } } if err := s.Delete("foo"); err != nil { t.Errorf("Delete failed (%v)", err) } - if results, err := s.Read("foo", ReadSuffix()); err != nil { + if results, err := s.Read("foo", store.ReadSuffix()); err != nil { t.Errorf("Couldn't read all \"foo\" keys, got %# v (%s)", spew.Sdump(results), err) } else { if len(results) != 0 { @@ -195,28 +196,28 @@ func fileTest(s Store, t *testing.T) { } } - // Test Table, Suffix and WriteOptions - if err := s.Write(&Record{ + // Test store.Table, Suffix and WriteOptions + if err := s.Write(&store.Record{ Key: "foofoobarbar", Value: []byte("something"), - }, WriteTTL(time.Millisecond*100)); err != nil { + }, store.WriteTTL(time.Millisecond*100)); err != nil { t.Error(err) } - if err := s.Write(&Record{ + if err := s.Write(&store.Record{ Key: "foofoo", Value: []byte("something"), - }, WriteExpiry(time.Now().Add(time.Millisecond*100))); err != nil { + }, store.WriteExpiry(time.Now().Add(time.Millisecond*100))); err != nil { t.Error(err) } - if err := s.Write(&Record{ + if err := s.Write(&store.Record{ Key: "barbar", Value: []byte("something"), // TTL has higher precedence than expiry - }, WriteExpiry(time.Now().Add(time.Hour)), WriteTTL(time.Millisecond*100)); err != nil { + }, store.WriteExpiry(time.Now().Add(time.Hour)), store.WriteTTL(time.Millisecond*100)); err != nil { t.Error(err) } - if results, err := s.Read("foo", ReadPrefix(), ReadSuffix()); err != nil { + if results, err := s.Read("foo", store.ReadPrefix(), store.ReadSuffix()); err != nil { t.Error(err) } else { if len(results) != 1 { @@ -236,14 +237,14 @@ func fileTest(s Store, t *testing.T) { // write the following records for i := 0; i < 10; i++ { - s.Write(&Record{ + s.Write(&store.Record{ Key: fmt.Sprintf("a%d", i), Value: []byte{}, }) } // read back a few records - if results, err := s.Read("a", ReadLimit(5), ReadPrefix()); err != nil { + if results, err := s.Read("a", store.ReadLimit(5), store.ReadPrefix()); err != nil { t.Error(err) } else { if len(results) != 5 { @@ -255,7 +256,7 @@ func fileTest(s Store, t *testing.T) { } // read the rest back - if results, err := s.Read("a", ReadLimit(30), ReadOffset(5), ReadPrefix()); err != nil { + if results, err := s.Read("a", store.ReadLimit(30), store.ReadOffset(5), store.ReadPrefix()); err != nil { t.Fatal(err) } else { if len(results) != 5 { diff --git a/store/store.go b/store/store.go index ef72cb26..5911463c 100644 --- a/store/store.go +++ b/store/store.go @@ -49,7 +49,7 @@ type Record struct { } func NewStore(opts ...Option) Store { - return NewFileStore(opts...) + return NewMemoryStore(opts...) } func NewRecord(key string, val interface{}) *Record {