amplify-category-api icon indicating copy to clipboard operation
amplify-category-api copied to clipboard

How to cache the query response?

Open mithun35h opened this issue 1 year ago • 7 comments

Amplify CLI Version

12.10.0

Question

I have a mode like this below

type Integration @model @searchable @auth(rules: [{allow: public}, {allow: custom}]) {
  enterpriseId: ID!
    @primaryKey(sortKeyFields: ["mode", "integrationId"])
  mode: MODE!
  integrationId: ID!
  config: AWSJSON
}

I have enabled caching in appsync, with TTL of 3600s with Full Resolver caching

I did do a getIntegration by passing enterpriseId, mode, integrationId

However for the second time, i still see the response time being same and cache miss, there are no cache hits

I did check the VTL context , but couldn't understand much Below is how the request VTL looks like

## [Start] Get Request template. **
#set( $GetRequest = {
  "version": "2018-05-29",
  "operation": "Query"
} )
#if( $ctx.stash.metadata.modelObjectKey )
  #set( $expression = "" )
  #set( $expressionNames = {} )
  #set( $expressionValues = {} )
  #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() )
    #set( $expression = "$expression#keyCount$velocityCount = :valueCount$velocityCount AND " )
    $util.qr($expressionNames.put("#keyCount$velocityCount", $item.key))
    $util.qr($expressionValues.put(":valueCount$velocityCount", $item.value))
  #end
  #set( $expression = $expression.replaceAll("AND $", "") )
  #set( $query = {
  "expression": $expression,
  "expressionNames": $expressionNames,
  "expressionValues": $expressionValues
} )
#else
  #set( $query = {
  "expression": "id = :id",
  "expressionValues": {
      ":id":     $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id))
  }
} )
#end
$util.qr($GetRequest.put("query", $query))
#if( !$util.isNullOrEmpty($ctx.stash.authFilter) )
  $util.qr($GetRequest.put("filter", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter))))
#end
$util.toJson($GetRequest)
## [End] Get Request template. **

How to make caching work with amplify? for the above scenario?

mithun35h avatar Jan 06 '24 18:01 mithun35h

I enabled Per-resolver caching by following this https://aws.amazon.com/blogs/mobile/appsync-pipeline-caching/ I was able to see the cache hits in the logs as well

However, how do i evict the cache now?

I can think of these approaches, please suggest if there is a better one, or which one is better?

  1. Per resolver, need to modify the VTL in response to evict based on the cache keys? This looks like a tedious job?
  2. Is there a custom directive, which can handle this? if we can pass the cache key? for mutations, evict can happen?

mithun35h avatar Jan 06 '24 21:01 mithun35h

After looking at the available options, i think PER_RESOLVER caching with @cache directive is the best approach to go forward

I will give it a try to create a custom cache directive, which can take ttl and cache keys - which can be set on a @model

or is there a way to extend the @model transformer itself?

mithun35h avatar Jan 08 '24 08:01 mithun35h

As you have discovered there is no native support for caching in the Amplify GraphQL API. Either of the two options you outlined would be a good option. There is no way to modify the @model transformer outside of creating a fork of the project. I think creating a custom transformer with the @cache directive is your best option.

dpilch avatar Jan 09 '24 19:01 dpilch

@dpilch Thanks

However i realised without the cache eviction flexible (support to evict based on regex) (i do understand why it cant be flexible - as it hampers the performance)

and also dynamoDB being the database, does it really make sense to have cache?

We might be saving few bugs with the read queries, apart from this, i don't see any advantage

What are your thoughts on this?

mithun35h avatar Jan 10 '24 04:01 mithun35h

I agree it might not be worth the effort. Have you considered a client side cache?

dpilch avatar Jan 12 '24 17:01 dpilch

Thanks for sharing you view

It's an event driven architecture, most of the calls are from lambda, I feel it's better to relook business logic and access patterns

Also I see, AppSync take sometime to execute queries. Is it because of the cold starts? I understand it's out of context, but I couldn't find related info (may be because I am wrong) - in X-ray even though I see dynamodb calls take 30ms, the overall app sync request take 300ms (or is it because of network latency?)

How to reduce the latency in this case? I dont see a provisioned capacity for appsync like how we have for lambda

mithun35h avatar Jan 12 '24 18:01 mithun35h

It's hard to pinpoint the source of the latency. Are you still experiencing higher than desired latency?

dpilch avatar Apr 02 '24 16:04 dpilch

Hey 👋 , This issue is being closed due to inactivity. If you are still experiencing the same problem and need further assistance, please feel free to leave a comment. This will enable us to reopen the issue and provide you with the necessary support.

AnilMaktala avatar May 13 '24 13:05 AnilMaktala

This issue is now closed. Comments on closed issues are hard for our team to see. If you need more assistance, please open a new issue that references this one.

github-actions[bot] avatar May 13 '24 13:05 github-actions[bot]