Skip to content

Commit

Permalink
Cache CreateStorageSpace calls for personal spaces (#3596)
Browse files Browse the repository at this point in the history
* Cache CreateStorageSpace responses for personal spaces

* Add changelog
  • Loading branch information
aduffeck authored Jan 11, 2023
1 parent adc4ad5 commit 580641d
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 22 deletions.
5 changes: 5 additions & 0 deletions changelog/unreleased/cache-create-home.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Bugfix: Cache CreateHome calls

We restored the caching of CreateHome calls getting rid of a lot of internal calls.

https://github.com/cs3org/reva/pull/3596
26 changes: 14 additions & 12 deletions internal/grpc/services/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,13 @@ func (c *config) init() {
}

type svc struct {
c *config
dataGatewayURL url.URL
tokenmgr token.Manager
statCache cache.StatCache
providerCache cache.ProviderCache
createHomeCache cache.CreateHomeCache
c *config
dataGatewayURL url.URL
tokenmgr token.Manager
statCache cache.StatCache
providerCache cache.ProviderCache
createHomeCache cache.CreateHomeCache
createPersonalSpaceCache cache.CreatePersonalSpaceCache
}

// New creates a new gateway svc that acts as a proxy for any grpc operation.
Expand All @@ -162,12 +163,13 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) {
}

s := &svc{
c: c,
dataGatewayURL: *u,
tokenmgr: tokenManager,
statCache: cache.GetStatCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "stat", time.Duration(c.StatCacheTTL)*time.Second),
providerCache: cache.GetProviderCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "provider", time.Duration(c.ProviderCacheTTL)*time.Second),
createHomeCache: cache.GetCreateHomeCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "createHome", time.Duration(c.CreateHomeCacheTTL)*time.Second),
c: c,
dataGatewayURL: *u,
tokenmgr: tokenManager,
statCache: cache.GetStatCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "stat", time.Duration(c.StatCacheTTL)*time.Second),
providerCache: cache.GetProviderCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "provider", time.Duration(c.ProviderCacheTTL)*time.Second),
createHomeCache: cache.GetCreateHomeCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "createHome", time.Duration(c.CreateHomeCacheTTL)*time.Second),
createPersonalSpaceCache: cache.GetCreatePersonalSpaceCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "createPersonalSpace", time.Duration(c.CreateHomeCacheTTL)*time.Second),
}

return s, nil
Expand Down
7 changes: 4 additions & 3 deletions internal/grpc/services/gateway/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1090,9 +1090,10 @@ func (s *svc) getStorageProviderClient(_ context.Context, p *registry.ProviderIn
}

return &cachedAPIClient{
c: c,
statCache: s.statCache,
createHomeCache: s.createHomeCache,
c: c,
statCache: s.statCache,
createHomeCache: s.createHomeCache,
createPersonalSpaceCache: s.createPersonalSpaceCache,
}, nil
}

Expand Down
27 changes: 24 additions & 3 deletions internal/grpc/services/gateway/storageprovidercache.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,10 @@ func (c *cachedRegistryClient) GetHome(ctx context.Context, in *registry.GetHome
*/

type cachedAPIClient struct {
c provider.ProviderAPIClient
statCache cache.StatCache
createHomeCache cache.CreateHomeCache
c provider.ProviderAPIClient
statCache cache.StatCache
createHomeCache cache.CreateHomeCache
createPersonalSpaceCache cache.CreatePersonalSpaceCache
}

// Stat looks in cache first before forwarding to storage provider
Expand Down Expand Up @@ -228,6 +229,26 @@ func (c *cachedAPIClient) GetHome(ctx context.Context, in *provider.GetHomeReque
return c.c.GetHome(ctx, in, opts...)
}
func (c *cachedAPIClient) CreateStorageSpace(ctx context.Context, in *provider.CreateStorageSpaceRequest, opts ...grpc.CallOption) (*provider.CreateStorageSpaceResponse, error) {
if in.Type == "personal" {
key := c.createPersonalSpaceCache.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId())
if key != "" {
s := &provider.CreateStorageSpaceResponse{}
if err := c.createPersonalSpaceCache.PullFromCache(key, s); err == nil {
return s, nil
}
}
resp, err := c.c.CreateStorageSpace(ctx, in, opts...)
switch {
case err != nil:
return nil, err
case resp.Status.Code != rpc.Code_CODE_OK && resp.Status.Code != rpc.Code_CODE_ALREADY_EXISTS:
return resp, nil
case key == "":
return resp, nil
default:
return resp, c.createPersonalSpaceCache.PushToCache(key, resp)
}
}
return c.c.CreateStorageSpace(ctx, in, opts...)
}
func (c *cachedAPIClient) ListStorageSpaces(ctx context.Context, in *provider.ListStorageSpacesRequest, opts ...grpc.CallOption) (*provider.ListStorageSpacesResponse, error) {
Expand Down
28 changes: 24 additions & 4 deletions pkg/storage/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ import (

var (
// DefaultStatCache is the memory store.
statCaches = make(map[string]StatCache)
providerCaches = make(map[string]ProviderCache)
createHomeCaches = make(map[string]CreateHomeCache)
mutex sync.Mutex
statCaches = make(map[string]StatCache)
providerCaches = make(map[string]ProviderCache)
createHomeCaches = make(map[string]CreateHomeCache)
createPersonalSpaceCaches = make(map[string]CreatePersonalSpaceCache)
mutex sync.Mutex
)

// Cache handles key value operations on caches
Expand Down Expand Up @@ -72,6 +73,12 @@ type CreateHomeCache interface {
GetKey(userID *userpb.UserId) string
}

// CreatePersonalSpaceCache handles removing keys from a create home cache
type CreatePersonalSpaceCache interface {
Cache
GetKey(userID *userpb.UserId) string
}

// GetStatCache will return an existing StatCache for the given store, nodes, database and table
// If it does not exist yet it will be created, different TTLs are ignored
func GetStatCache(cacheStore string, cacheNodes []string, database, table string, ttl time.Duration) StatCache {
Expand Down Expand Up @@ -111,6 +118,19 @@ func GetCreateHomeCache(cacheStore string, cacheNodes []string, database, table
return createHomeCaches[key]
}

// GetCreatePersonalSpaceCache will return an existing CreatePersonalSpaceCache for the given store, nodes, database and table
// If it does not exist yet it will be created, different TTLs are ignored
func GetCreatePersonalSpaceCache(cacheStore string, cacheNodes []string, database, table string, ttl time.Duration) CreatePersonalSpaceCache {
mutex.Lock()
defer mutex.Unlock()

key := strings.Join(append(append([]string{cacheStore}, cacheNodes...), database, table), ":")
if createPersonalSpaceCaches[key] == nil {
createPersonalSpaceCaches[key] = NewCreatePersonalSpaceCache(cacheStore, cacheNodes, database, table, ttl)
}
return createPersonalSpaceCaches[key]
}

// CacheStore holds cache store specific configuration
type cacheStore struct {
s microstore.Store
Expand Down
45 changes: 45 additions & 0 deletions pkg/storage/cache/createpersonalspace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2018-2023 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

package cache

import (
"time"

userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
)

// CreatePersonalSpaceCache can invalidate all create home related cache entries
type createPersonalSpaceCache struct {
cacheStore
}

// NewCreatePersonalSpaceCache creates a new CreatePersonalSpaceCache
func NewCreatePersonalSpaceCache(store string, nodes []string, database, table string, ttl time.Duration) CreatePersonalSpaceCache {
c := &createPersonalSpaceCache{}
c.s = getStore(store, nodes, database, table, ttl)
c.database = database
c.table = table
c.ttl = ttl

return c
}

func (c createPersonalSpaceCache) GetKey(userID *userpb.UserId) string {
return userID.GetOpaqueId()
}

0 comments on commit 580641d

Please sign in to comment.