Skip to content

Commit 1f70b97

Browse files
authored
[SQL Storage indexer] Add cache for categories endpoint (#1379)
This PR adds an independent cache for the categories endpoint (/categories) following the same pattern as it was implemented for the search endpoint.
1 parent d12e4e0 commit 1f70b97

8 files changed

Lines changed: 167 additions & 76 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
* New Security subcategory "asset_inventory" [#1357](https://github.com/elastic/package-registry/pull/1357)
1515
* Update default value for the batch size used in SQL storage indexer. [#1372](https://github.com/elastic/package-registry/pull/1372)
1616
* Skip adding to cache requests containing package query parameter. [#1378](https://github.com/elastic/package-registry/pull/1378)
17+
* Added cache for categories endpoint (SQL storage indexer). [#1379](https://github.com/elastic/package-registry/1379)
18+
* Update default values for cache search and TTL settings search (SQL storage indexer). [#1379](https://github.com/elastic/package-registry/1379)
1719

1820
### Deprecated
1921

categories.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"go.uber.org/zap"
1919

2020
"github.com/Masterminds/semver/v3"
21+
"github.com/hashicorp/golang-lru/v2/expirable"
2122
"go.elastic.co/apm/module/apmzap/v2"
2223
"go.elastic.co/apm/v2"
2324

@@ -28,14 +29,22 @@ import (
2829

2930
// categoriesHandler is a dynamic handler as it will also allow filtering in the future.
3031
func categoriesHandler(logger *zap.Logger, indexer Indexer, cacheTime time.Duration) func(w http.ResponseWriter, r *http.Request) {
31-
return categoriesHandlerWithProxyMode(logger, indexer, proxymode.NoProxy(logger), cacheTime)
32+
return categoriesHandlerWithProxyMode(logger, indexer, proxymode.NoProxy(logger), cacheTime, nil)
3233
}
3334

3435
// categoriesHandler is a dynamic handler as it will also allow filtering in the future.
35-
func categoriesHandlerWithProxyMode(logger *zap.Logger, indexer Indexer, proxyMode *proxymode.ProxyMode, cacheTime time.Duration) func(w http.ResponseWriter, r *http.Request) {
36+
func categoriesHandlerWithProxyMode(logger *zap.Logger, indexer Indexer, proxyMode *proxymode.ProxyMode, cacheTime time.Duration, cache *expirable.LRU[string, []byte]) func(w http.ResponseWriter, r *http.Request) {
3637
return func(w http.ResponseWriter, r *http.Request) {
3738
logger := logger.With(apmzap.TraceContext(r.Context())...)
3839

40+
if cache != nil {
41+
if response, ok := cache.Get(r.URL.String()); ok {
42+
logger.Debug("using as response cached request", zap.String("cache.url", r.URL.String()), zap.Int("cache.size", cache.Len()))
43+
serveJSONResponse(r.Context(), w, cacheTime, response)
44+
return
45+
}
46+
}
47+
3948
query := r.URL.Query()
4049

4150
filter, err := newCategoriesFilterFromQuery(query)
@@ -93,6 +102,11 @@ func categoriesHandlerWithProxyMode(logger *zap.Logger, indexer Indexer, proxyMo
93102
}
94103

95104
serveJSONResponse(r.Context(), w, cacheTime, data)
105+
106+
if cache != nil {
107+
val := cache.Add(r.URL.String(), data)
108+
logger.Debug("added to cache request", zap.String("cache.url", r.URL.String()), zap.Int("cache.size", cache.Len()), zap.Bool("cache.eviction", val))
109+
}
96110
}
97111
}
98112

categories_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func TestCategoriesWithProxyMode(t *testing.T) {
5454
)
5555
require.NoError(t, err)
5656

57-
categoriesWithProxyHandler := categoriesHandlerWithProxyMode(testLogger, indexerProxy, proxyMode, testCacheTime)
57+
categoriesWithProxyHandler := categoriesHandlerWithProxyMode(testLogger, indexerProxy, proxyMode, testCacheTime, nil)
5858

5959
tests := []struct {
6060
endpoint string

dev/launch_epr_service_storage_indexer.sh

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ usage() {
1919
echo -e "\t\t\tIf set, the bucket name will be ignored (-b parameter) and Package Registry will use its default development bucket gs://fake-package-storage-internal"
2020
echo -e "\t-c <config_path>: Path to the configurastion file. Default: \"\""
2121
echo -e "\t-s : Enable SQL Storage indexer. By default Storage Indexer is enabled."
22-
echo -e "\t-C : Enable Search Cache. Just supported with SQL Storage indexer. By default Search Cache is disabled."
22+
echo -e "\t-C : Enable Cache for Search and Categories endpoints. Just supported with the SQL Storage indexer. By default both Caches are disabled."
2323
echo -e "\t-d: Enable debug mode. Default: false"
2424
echo -e "\t-h: Show this message"
2525
}
@@ -30,8 +30,7 @@ INDEX_PATH=""
3030
EMULATOR_HOST="localhost:4443"
3131
CONFIG_PATH="${SCRIPT_DIR}/../config.yml"
3232
ENABLE_STORAGE_SQL_INDEXER=0
33-
ENABLE_SEARCH_CACHE=0
34-
ENABLE_DEBUG_MODE=0
33+
ENABLE_CACHE=0
3534

3635
while getopts ":b:p:i:e:c:sdCh" o; do
3736
case "${o}" in
@@ -54,7 +53,7 @@ while getopts ":b:p:i:e:c:sdCh" o; do
5453
ENABLE_STORAGE_SQL_INDEXER=1
5554
;;
5655
C)
57-
ENABLE_SEARCH_CACHE=1
56+
ENABLE_CACHE=1
5857
;;
5958
d)
6059
ENABLE_DEBUG_MODE=1
@@ -101,8 +100,9 @@ else
101100
export EPR_FEATURE_STORAGE_INDEXER="false"
102101
fi
103102

104-
if [[ "${ENABLE_SEARCH_CACHE}" == 1 ]]; then
103+
if [[ "${ENABLE_CACHE}" == 1 ]]; then
105104
export EPR_FEATURE_ENABLE_SEARCH_CACHE="true"
105+
export EPR_FEATURE_ENABLE_CATEGORIES_CACHE="true"
106106
fi
107107

108108
export EPR_DISABLE_PACKAGE_VALIDATION="true"
@@ -113,8 +113,10 @@ if [[ "${ENABLE_DEBUG_MODE}" == 1 ]]; then
113113
fi
114114
export EPR_CONFIG="${CONFIG_PATH}"
115115
# export EPR_SQL_INDEXER_DATABASE_FOLDER_PATH=/tmp
116-
# export EPR_SQL_INDEXER_SEARCH_CACHE_SIZE=100
117-
# export EPR_SQL_INDEXER_SEARCH_CACHE_TTL=10m
116+
# export EPR_SQL_INDEXER_SEARCH_CACHE_SIZE=250
117+
# export EPR_SQL_INDEXER_SEARCH_CACHE_TTL=24h
118+
# export EPR_SQL_INDEXER_CATEGORIES_CACHE_SIZE=100
119+
# export EPR_SQL_INDEXER_CATEGORIES_CACHE_TTL=24h
118120
# export EPR_SQL_INDEXER_READ_PACKAGES_BATCH_SIZE=2000
119121
# export EPR_SQL_INDEXER_DB_INSERT_BATCH_SIZE=2000
120122

internal/storage/sqlindexer.go

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ import (
1616
"sync"
1717
"time"
1818

19-
"github.com/hashicorp/golang-lru/v2/expirable"
20-
2119
"cloud.google.com/go/storage"
2220

2321
"github.com/prometheus/client_golang/prometheus"
@@ -59,7 +57,7 @@ type SQLIndexer struct {
5957

6058
readPackagesBatchSize int
6159

62-
cache *expirable.LRU[string, []byte] // Cache for search results
60+
afterUpdateHook func(ctx context.Context)
6361
}
6462

6563
type IndexerOptions struct {
@@ -69,8 +67,8 @@ type IndexerOptions struct {
6967
WatchInterval time.Duration
7068
Database database.Repository
7169
SwapDatabase database.Repository
72-
Cache *expirable.LRU[string, []byte] // Cache for search results
7370
ReadPackagesBatchsize int
71+
AfterUpdateIndexHook func(ctx context.Context)
7472
}
7573

7674
func NewIndexer(logger *zap.Logger, storageClient *storage.Client, options IndexerOptions) *SQLIndexer {
@@ -86,8 +84,8 @@ func NewIndexer(logger *zap.Logger, storageClient *storage.Client, options Index
8684
swapDatabase: options.SwapDatabase,
8785
label: fmt.Sprintf("storage-%s", options.PackageStorageEndpoint),
8886
readPackagesBatchSize: defaultReadPackagesBatchSize,
89-
cache: options.Cache,
9087
cursor: "init",
88+
afterUpdateHook: options.AfterUpdateIndexHook,
9189
}
9290

9391
indexer.current = &indexer.database
@@ -302,10 +300,8 @@ func (i *SQLIndexer) swapDatabases(ctx context.Context, currentCursor string, nu
302300
i.current, i.backup = i.backup, i.current
303301
i.logger.Debug("Current database changed", zap.String("current.database.path", (*i.current).File(ctx)), zap.String("previous.database.path", (*i.backup).File(ctx)))
304302

305-
if i.cache != nil {
306-
// Clear the cache after updating the index
307-
// there could be new, updated or removed packages
308-
i.cache.Purge()
303+
if i.afterUpdateHook != nil {
304+
i.afterUpdateHook(ctx)
309305
}
310306

311307
metrics.StorageIndexerUpdateIndexSuccessTotal.Inc()

0 commit comments

Comments
 (0)