Skip to content

Commit

Permalink
Updated cached response to include headers
Browse files Browse the repository at this point in the history
  • Loading branch information
aalexand committed Aug 2, 2024
1 parent 5c62314 commit fbf3732
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 28 deletions.
2 changes: 1 addition & 1 deletion local/.env.local
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export SQS_AWS_REGION="sqs-aws-region"
export SQS_QUEUE_NAME="cluster-registry-local"
export SQS_BATCH_SIZE="10"
export SQS_WAIT_SECONDS="5"
export SQS_RUN_INTERVAL="30"
export SQS_RUN_INTERVAL="10"
export SET_CA_CERT="true"
export CONTAINER_DB="dynamodb"
export IMAGE_DB="amazon/dynamodb-local:2.2.1"
Expand Down
44 changes: 40 additions & 4 deletions pkg/apiserver/web/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package web
import (
"bufio"
"bytes"
"encoding/gob"
"github.com/adobe/cluster-registry/pkg/config"
"github.com/eko/gocache/lib/v4/cache"
"github.com/eko/gocache/lib/v4/store"
Expand All @@ -26,25 +27,56 @@ import (
"net/url"
"sort"
"strconv"
"strings"
)

type Response struct {
// Value is the cached response value.
Value []byte

// Header is the cached response header.
Header http.Header
}

func StringToResponse(s string) Response {
var r Response
dec := gob.NewDecoder(strings.NewReader(s))
_ = dec.Decode(&r)

return r
}

func (r Response) String() string {
var b bytes.Buffer
enc := gob.NewEncoder(&b)
_ = enc.Encode(r)

return b.String()
}

func HTTPCache(client *cache.Cache[string], appConfig *config.AppConfig, tags []string) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
if c.Request().Method == http.MethodGet {
sortURLParams(c.Request().URL)
key := GenerateKey(c.Request().URL.String())

value, err := client.Get(c.Request().Context(), key)
cachedResponse, err := client.Get(c.Request().Context(), key)
response := StringToResponse(cachedResponse)
if err != nil {
c.Logger().Errorf("Error getting key from cache: %s", err.Error())
c.Error(err)
}

// if key in cache
if value != "" {
if cachedResponse != "" {
// return body from cache
_, _ = c.Response().Write([]byte(value))
for k, v := range response.Header {
c.Response().Header().Set(k, strings.Join(v, ","))
}
c.Response().WriteHeader(http.StatusOK)
_, _ = c.Response().Write(response.Value)

return nil
}

Expand All @@ -57,7 +89,11 @@ func HTTPCache(client *cache.Cache[string], appConfig *config.AppConfig, tags []
c.Error(err)
}
if writer.statusCode < 400 {
err := client.Set(c.Request().Context(), key, resBody.String(), store.WithExpiration(appConfig.ApiCacheTTL), store.WithTags(tags))
newResponse := Response{
Value: resBody.Bytes(),
Header: writer.Header(),
}
err := client.Set(c.Request().Context(), key, newResponse.String(), store.WithExpiration(appConfig.ApiCacheTTL), store.WithTags(tags))
if err != nil {
c.Logger().Errorf("Error setting cache key: %s", err.Error())
c.Error(err)
Expand Down
28 changes: 21 additions & 7 deletions pkg/apiserver/web/handler/v1/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,15 +309,22 @@ func TestListClustersWithEmptyCache(t *testing.T) {
rec := httptest.NewRecorder()
ctx := r.NewContext(req, rec)

expectedResponse := newClusterListResponse(expectedClusters, len(expectedClusters), 0, 200, false)
expectedBody, err := json.Marshal(expectedResponse)
expectedClusterListResponse := newClusterListResponse(expectedClusters, len(expectedClusters), 0, 200, false)
expectedBody, err := json.Marshal(expectedClusterListResponse)
test.NoError(err)

expectedBody = append(expectedBody, "\n"...)

expectedResponse := web.Response{
Value: expectedBody,
Header: http.Header{"Content-Type": []string{echo.MIMEApplicationJSON}},
}

key := web.GenerateKey(ctx.Request().URL.String())

redisMock.ExpectGet(key).SetVal("")

redisMock.ExpectSet(key, string(expectedBody)+"\n", appConfig.ApiCacheTTL).SetVal("OK")
redisMock.ExpectSet(key, expectedResponse.String(), appConfig.ApiCacheTTL).SetVal("OK")

err = web.HTTPCache(cacheManager, appConfig, []string{"clusters"})(h.ListClusters)(ctx)
test.NoError(err)
Expand Down Expand Up @@ -365,14 +372,21 @@ func TestListClustersWithCache(t *testing.T) {
rec := httptest.NewRecorder()
ctx := r.NewContext(req, rec)

expectedResponse := newClusterListResponse(expectedClusters, len(expectedClusters), 0, 200, false)
expectedBody, err := json.Marshal(expectedResponse)
expectedClusterListResponse := newClusterListResponse(expectedClusters, len(expectedClusters), 0, 200, false)
expectedBody, err := json.Marshal(expectedClusterListResponse)
test.NoError(err)

expectedBody = append(expectedBody, "\n"...)

expectedResponse := web.Response{
Value: expectedBody,
Header: http.Header{"Content-Type": []string{echo.MIMEApplicationJSON}},
}

key := web.GenerateKey(ctx.Request().URL.String())

redisMock.ExpectSet(key, string(expectedBody), appConfig.ApiCacheTTL).SetVal("")
err = redisStore.Set(context.Background(), key, string(expectedBody), store.WithExpiration(appConfig.ApiCacheTTL))
redisMock.ExpectSet(key, expectedResponse.String(), appConfig.ApiCacheTTL).SetVal("")
err = redisStore.Set(context.Background(), key, expectedResponse.String(), store.WithExpiration(appConfig.ApiCacheTTL))
test.NoError(err)

redisMock.ExpectGet(key).SetVal(string(expectedBody))
Expand Down
31 changes: 22 additions & 9 deletions pkg/apiserver/web/handler/v2/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,15 +478,21 @@ func TestListClustersWithEmptyCache(t *testing.T) {
rec := httptest.NewRecorder()
ctx := r.NewContext(req, rec)

expectedResponse := newClusterListResponse(expectedClusters, len(expectedClusters), 0, 200, false)
expectedBody, err := json.Marshal(expectedResponse)
test.NoError(err)
expectedClusterListResponse := newClusterListResponse(expectedClusters, len(expectedClusters), 0, 200, false)
expectedBody, err := json.Marshal(expectedClusterListResponse)

Check failure on line 482 in pkg/apiserver/web/handler/v2/handler_test.go

View workflow job for this annotation

GitHub Actions / CI tests

ineffectual assignment to err (ineffassign)

expectedBody = append(expectedBody, "\n"...)

expectedResponse := web.Response{
Value: expectedBody,
Header: http.Header{"Content-Type": []string{echo.MIMEApplicationJSON}},
}

key := web.GenerateKey(ctx.Request().URL.String())

redisMock.ExpectGet(key).SetVal("")

redisMock.ExpectSet(key, string(expectedBody)+"\n", appConfig.ApiCacheTTL).SetVal("OK")
redisMock.ExpectSet(key, expectedResponse.String(), appConfig.ApiCacheTTL).SetVal("OK")

err = web.HTTPCache(cacheManager, appConfig, []string{"clusters"})(h.ListClusters)(ctx)
test.NoError(err)
Expand Down Expand Up @@ -534,17 +540,24 @@ func TestListClustersWithCache(t *testing.T) {
rec := httptest.NewRecorder()
ctx := r.NewContext(req, rec)

expectedResponse := newClusterListResponse(expectedClusters, len(expectedClusters), 0, 200, false)
expectedBody, err := json.Marshal(expectedResponse)
expectedClusterListResponse := newClusterListResponse(expectedClusters, len(expectedClusters), 0, 200, false)
expectedBody, err := json.Marshal(expectedClusterListResponse)
test.NoError(err)

expectedBody = append(expectedBody, "\n"...)

expectedResponse := web.Response{
Value: expectedBody,
Header: http.Header{"Content-Type": []string{echo.MIMEApplicationJSON}},
}

key := web.GenerateKey(ctx.Request().URL.String())

redisMock.ExpectSet(key, string(expectedBody), appConfig.ApiCacheTTL).SetVal("")
err = redisStore.Set(context.Background(), key, string(expectedBody), store.WithExpiration(appConfig.ApiCacheTTL))
redisMock.ExpectSet(key, expectedResponse.String(), appConfig.ApiCacheTTL).SetVal("")
err = redisStore.Set(context.Background(), key, expectedResponse.String(), store.WithExpiration(appConfig.ApiCacheTTL))
test.NoError(err)

redisMock.ExpectGet(key).SetVal(string(expectedBody))
redisMock.ExpectGet(key).SetVal(expectedResponse.String())

err = web.HTTPCache(cacheManager, appConfig, []string{"clusters"})(h.ListClusters)(ctx)
test.NoError(err)
Expand Down
14 changes: 7 additions & 7 deletions test/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (s *e2eTestSuite) Test_EndToEnd_GetClusters() {
jwtToken := jwt.GenerateDefaultSignedToken(appConfig)
bearer := "Bearer " + jwtToken

req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://localhost:%d/api/v1/clusters", s.apiPort), nil)
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://localhost:%d/api/v2/clusters", s.apiPort), nil)
if err != nil {
s.T().Fatalf("Cannot build http request: %v", err.Error())
}
Expand All @@ -96,7 +96,7 @@ func (s *e2eTestSuite) Test_EndToEnd_GetClusters() {
s.T().Fatalf("Cannot read response body: %v", err.Error())
}

err = json.Unmarshal([]byte(body), &clusters)
err = json.Unmarshal(body, &clusters)
if err != nil {
s.T().Fatalf("Failed to unmarshal data: %v", err.Error())
}
Expand All @@ -115,7 +115,7 @@ func (s *e2eTestSuite) Test_EndToEnd_CreateCluster() {
s.T().Fatalf("Failed to read data from file %s.", input_file)
}

err = json.Unmarshal([]byte(data), &inputCluster)
err = json.Unmarshal(data, &inputCluster)
if err != nil {
s.T().Fatalf("Failed to unmarshal data: %v", err.Error())
}
Expand Down Expand Up @@ -176,7 +176,7 @@ func (s *e2eTestSuite) Test_EndToEnd_CreateCluster() {
s.T().Fatalf("Failed read response body: %v", err.Error())
}

err = json.Unmarshal([]byte(body), &outputCluster)
err = json.Unmarshal(body, &outputCluster)

s.Assert().Equal(http.StatusOK, resp.StatusCode)

Expand Down Expand Up @@ -227,7 +227,7 @@ func (s *e2eTestSuite) TBD_Test_EndToEnd_UpdateCluster() {
log.Fatal(err.Error())
}

err = json.Unmarshal([]byte(data), &inputCluster)
err = json.Unmarshal(data, &inputCluster)
if err != nil {
log.Fatal(err.Error())
}
Expand Down Expand Up @@ -281,7 +281,7 @@ func (s *e2eTestSuite) TBD_Test_EndToEnd_UpdateCluster() {
log.Fatal(err)
}

err = json.Unmarshal([]byte(body), &outputCluster)
err = json.Unmarshal(body, &outputCluster)
if err != nil {
log.Fatal(err)
}
Expand Down Expand Up @@ -318,7 +318,6 @@ func (s *e2eTestSuite) Test_EndToEnd_RateLimiter() {
if err != nil {
s.T().Fatalf("Cannot make http request: %v", err.Error())
}
defer resp.Body.Close()

s.NoError(err)

Expand All @@ -329,6 +328,7 @@ func (s *e2eTestSuite) Test_EndToEnd_RateLimiter() {
} else {
s.T().Errorf("Unexpected status code: %d", resp.StatusCode)
}
_ = resp.Body.Close()
}

s.Assert().LessOrEqual(statusOK, expectedMaxStatusOK)
Expand Down

0 comments on commit fbf3732

Please sign in to comment.