KVStore: Extend kvstore to retrieve all items (#50848)

* Extend kvstore to retrieve all items

* Fix comment

* Fix tests

* Change test order

* Move test outside to avoid order conditions

* Update Items to GetAll function and return a map

* Add explanation of map result

* Add description comment

Co-authored-by: Tania B <yalyna.ts@gmail.com>
This commit is contained in:
Selene 2022-06-23 11:12:07 +02:00 committed by GitHub
parent 496c2e26f4
commit ecc15a2f71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 0 deletions

View File

@ -25,6 +25,7 @@ type KVStore interface {
Set(ctx context.Context, orgId int64, namespace string, key string, value string) error
Del(ctx context.Context, orgId int64, namespace string, key string) error
Keys(ctx context.Context, orgId int64, namespace string, keyPrefix string) ([]Key, error)
GetAll(ctx context.Context, orgId int64, namespace string) (map[int64]map[string]string, error)
}
// WithNamespace returns a kvstore wrapper with fixed orgId and namespace.
@ -58,3 +59,8 @@ func (kv *NamespacedKVStore) Del(ctx context.Context, key string) error {
func (kv *NamespacedKVStore) Keys(ctx context.Context, keyPrefix string) ([]Key, error) {
return kv.kvStore.Keys(ctx, kv.orgId, kv.namespace, keyPrefix)
}
// GetAll returns all the keys and values stored per organization. It returns a map of org -> key -> value.
func (kv *NamespacedKVStore) GetAll(ctx context.Context) (map[int64]map[string]string, error) {
return kv.kvStore.GetAll(ctx, kv.orgId, kv.namespace)
}

View File

@ -242,3 +242,48 @@ func TestIntegrationKVStore(t *testing.T) {
require.Len(t, keys, 0, "querying a not existing namespace and key should return an empty slice")
})
}
func TestGetItems(t *testing.T) {
kv := createTestableKVStore(t)
ctx := context.Background()
testCases := []*TestCase{
{
OrgId: 1,
Namespace: "testing1",
Key: "key1",
},
{
OrgId: 2,
Namespace: "testing1",
Key: "key1",
},
{
OrgId: 2,
Namespace: "testing1",
Key: "key2",
},
}
for _, tc := range testCases {
err := kv.Set(ctx, tc.OrgId, tc.Namespace, tc.Key, tc.Value())
require.NoError(t, err)
}
t.Run("Get all values per org", func(t *testing.T) {
for _, tc := range testCases {
items, err := kv.GetAll(ctx, tc.OrgId, tc.Namespace)
require.NoError(t, err)
require.Equal(t, items[tc.OrgId][tc.Key], tc.Value())
}
})
t.Run("Get all values for all orgs", func(t *testing.T) {
items, err := kv.GetAll(ctx, AllOrganizations, "testing1")
require.NoError(t, err)
for _, tc := range testCases {
require.Equal(t, items[tc.OrgId][tc.Key], tc.Value())
}
})
}

View File

@ -109,3 +109,28 @@ func (kv *kvStoreSQL) Keys(ctx context.Context, orgId int64, namespace string, k
})
return keys, err
}
// GetAll get all items a given namespace and org. To query for all
// organizations the constant 'kvstore.AllOrganizations' can be passed as orgId.
// The map result is like map[orgId]map[key]value
func (kv *kvStoreSQL) GetAll(ctx context.Context, orgId int64, namespace string) (map[int64]map[string]string, error) {
var results []Item
err := kv.sqlStore.WithDbSession(ctx, func(dbSession *sqlstore.DBSession) error {
query := dbSession.Where("namespace = ?", namespace)
if orgId != AllOrganizations {
query.And("org_id = ?", orgId)
}
return query.Find(&results)
})
items := map[int64]map[string]string{}
for _, r := range results {
if _, ok := items[*r.OrgId]; !ok {
items[*r.OrgId] = map[string]string{}
}
items[*r.OrgId][*r.Key] = r.Value
}
return items, err
}

View File

@ -201,6 +201,10 @@ func (fkv *FakeKVStore) Keys(ctx context.Context, orgID int64, namespace string,
return keys, nil
}
func (fkv *FakeKVStore) GetAll(ctx context.Context, orgId int64, namespace string) (map[int64]map[string]string, error) {
return nil, nil
}
type fakeState struct {
data string
}