Skip to content

Commit

Permalink
Added Caching KeyStore. Releasing v0.11.0
Browse files Browse the repository at this point in the history
  • Loading branch information
pdt256 committed May 14, 2021
1 parent 2da610b commit 05a8892
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 1 deletion.
49 changes: 49 additions & 0 deletions pkg/crypto/provider/cachekeystore/cache_keystore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package cachekeystore

import (
"github.com/inklabs/rangedb/pkg/crypto"
)

type cacheKeyStore struct {
first crypto.KeyStore

This comment has been minimized.

Copy link
@fmontada

fmontada May 14, 2021

@pdt256 wonder if cache is a better name than first? so that in the implementation is more clear that we always look on the "cache" first

second crypto.KeyStore
}

func New(first crypto.KeyStore, second crypto.KeyStore) *cacheKeyStore {
return &cacheKeyStore{
first: first,
second: second,
}
}

func (c *cacheKeyStore) Get(subjectID string) (string, error) {
key, err := c.first.Get(subjectID)
if err != nil {
secondKey, secondErr := c.second.Get(subjectID)
if secondErr != nil {
return "", secondErr
}

return secondKey, c.first.Set(subjectID, secondKey)
}

return key, nil
}

func (c *cacheKeyStore) Set(subjectID, key string) error {
err := c.second.Set(subjectID, key)
if err != nil {
return err
}

return c.first.Set(subjectID, key)

This comment has been minimized.

Copy link
@tomParty

tomParty May 14, 2021

Contributor

curious what happens if second passes and first fails?

This comment has been minimized.

Copy link
@pdt256

pdt256 May 14, 2021

Author Member

a subsequent call to first.Get() would not find a value, then lookup in second.Get(), then save to first.Set(). See the Get() method above.

This comment has been minimized.

Copy link
@tomParty

tomParty May 14, 2021

Contributor

I see, makes sense.. might be worth a test case?

This comment has been minimized.

Copy link
@tomParty

tomParty May 14, 2021

Contributor

I guess get not found in first, gets from second, and saves to first testcase kinda covers that

}

func (c *cacheKeyStore) Delete(subjectID string) error {
err := c.second.Delete(subjectID)
if err != nil {
return err
}

return c.first.Delete(subjectID)
}
96 changes: 96 additions & 0 deletions pkg/crypto/provider/cachekeystore/cache_keystore_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package cachekeystore_test

import (
"testing"

"github.com/inklabs/rangedb/pkg/crypto"
"github.com/inklabs/rangedb/pkg/crypto/cryptotest"
"github.com/inklabs/rangedb/pkg/crypto/provider/cachekeystore"
"github.com/inklabs/rangedb/pkg/crypto/provider/inmemorykeystore"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestInMemoryCrypto_VerifyKeyStoreInterface(t *testing.T) {
cryptotest.VerifyKeyStore(t, func(t *testing.T) crypto.KeyStore {
return cachekeystore.New(inmemorykeystore.New(), inmemorykeystore.New())
})
}

func TestCacheKeyStore(t *testing.T) {
const (
subjectID = "6bf99d62af77440498b852e0c03e1d87"
key = "0d8497df9be04a02be691b14de9319e6"
)

t.Run("get found in first", func(t *testing.T) {
// Given
first := inmemorykeystore.New()
require.NoError(t, first.Set(subjectID, key))
second := inmemorykeystore.New()
cacheKeyStore := cachekeystore.New(first, second)

// When
actualKey, err := cacheKeyStore.Get(subjectID)

// Then
require.NoError(t, err)
assert.Equal(t, key, actualKey)
})

t.Run("get not found in first, gets from second, and saves to first", func(t *testing.T) {
// Given
first := inmemorykeystore.New()
second := inmemorykeystore.New()
require.NoError(t, second.Set(subjectID, key))
cacheKeyStore := cachekeystore.New(first, second)

// When
actualKey, err := cacheKeyStore.Get(subjectID)

// Then
require.NoError(t, err)
assert.Equal(t, key, actualKey)
actualFirstKey, err := first.Get(subjectID)
require.NoError(t, err)
assert.Equal(t, key, actualFirstKey)
})

t.Run("set saves to both first and second", func(t *testing.T) {
// Given
first := inmemorykeystore.New()
second := inmemorykeystore.New()
cacheKeyStore := cachekeystore.New(first, second)

// When
err := cacheKeyStore.Set(subjectID, key)

// Then
require.NoError(t, err)
actualFirstKey, err := first.Get(subjectID)
require.NoError(t, err)
actualSecondKey, err := second.Get(subjectID)
require.NoError(t, err)
assert.Equal(t, key, actualFirstKey)
assert.Equal(t, key, actualSecondKey)
})

t.Run("delete from both first and second", func(t *testing.T) {
// Given
first := inmemorykeystore.New()
require.NoError(t, first.Set(subjectID, key))
second := inmemorykeystore.New()
require.NoError(t, second.Set(subjectID, key))
cacheKeyStore := cachekeystore.New(first, second)

// When
err := cacheKeyStore.Delete(subjectID)

// Then
require.NoError(t, err)
_, err = first.Get(subjectID)
require.Equal(t, crypto.ErrKeyWasDeleted, err)
_, err = second.Get(subjectID)
require.Equal(t, crypto.ErrKeyWasDeleted, err)
})
}
2 changes: 1 addition & 1 deletion store.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

// Version for RangeDB.
const Version = "0.10.1-dev"
const Version = "0.11.0"

// Record contains event data and metadata.
type Record struct {
Expand Down

0 comments on commit 05a8892

Please sign in to comment.