Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[apollo-datasource-rest] Feature request: expose cache status to callers #41

Open
nwalters512 opened this issue Jun 23, 2020 · 2 comments · May be fixed by #328
Open

[apollo-datasource-rest] Feature request: expose cache status to callers #41

nwalters512 opened this issue Jun 23, 2020 · 2 comments · May be fixed by #328

Comments

@nwalters512
Copy link

nwalters512 commented Jun 23, 2020

Hey folks 👋 We have an existing subclass of RESTDataSource that logs a variety of metrics for each call to fetch. We're trying to instrument our data sources to better understand how caching/memoization is used in production. However, RESTDataSource doesn't make it easy to figure out this information; the best we could do was manually querying the cache and memoizedResults to try to infer what's happening. However, in the end, we ended up forking RESTDataSource/HTTPCache to make cache status information first-class data in the return values from get/post/etc. We defined a new type, FetchResult that wraps the original response with cache metadata:

export interface FetchResult<TResult> {
  context: {
    cacheHit: boolean;
    memoized: boolean;
  };
  response: Promise<TResult>;
}

We then updated the get/post/etc. to return a FetchResult:

  protected async get<TResult = any>(
    path: string,
    params?: URLSearchParamsInit,
    init?: RequestInit
  ): Promise<FetchResult<TResult>> {
    return this.fetch<TResult>(
      Object.assign({ method: 'GET', path, params }, init)
    );
  }

Finally, we changed RESTDataSource#fetch and HTTPCache#fetch to return objects with that same context property. With this, we could update our subclass of RESTDataSource to automatically report whether particular requests were served by the cache or were memoized.

Here's our implementation in a Gist: https://gist.github.com/nwalters512/472b5fb7d4cc7d32c4cecaa69b21baf5. The important bits:

While this works, it's less than ideal to have to fork RESTDataSource and HTTPCache, since that introduces additional maintenance burden on our team. Ideally, this could be provided by the apollo-datasource-rest package itself. Does Apollo have any interest in adding this functionality? It doesn't necessarily need to use the same FetchResult interface we invented, but we'd appreciate anything that would give us more insight into how the cache is used.

@glasser glasser transferred this issue from apollographql/apollo-server Oct 11, 2022
glasser added a commit that referenced this issue Dec 14, 2022
This field is returned if you call `fetch` instead of `get` (etc) and it
tells you what the deduplication policy was and if it matched.

Also allow `this.fetch` to be called with only one argument (because we
previously made `method` optional).

Part of #41 (which also requests adding information on the other cache's
status).
glasser added a commit that referenced this issue Dec 14, 2022
This field is returned if you call `fetch` instead of `get` (etc) and it
tells you what the deduplication policy was and if it matched.

Also allow `this.fetch` to be called with only one argument (because we
previously made `method` optional).

Part of #41 (which also requests adding information on the other cache's
status).
glasser added a commit that referenced this issue Dec 14, 2022
This gives us an appropriate place to put the data desired by #41.

Also makes RESTDataSource tests actually wait on the cache writes
(perhaps they were brittle before).
glasser added a commit that referenced this issue Dec 14, 2022
This gives us an appropriate place to put the data desired by #41.

Also makes RESTDataSource tests actually wait on the cache writes
(perhaps they were brittle before).
@glasser
Copy link
Member

glasser commented Dec 15, 2022

This is a good feature suggestion and we're partway there now:

  • There's a fetch method that returns more than just the parsed body (the methods like get are convenience wrappers that fill in the method and pluck off parsedBody
  • Its return type (DataSourceFetchResult) has a requestDeduplication field that gives information similar to the memoized concept described here
  • It also has an httpCache field which for now just has a cacheWritePromise (which is mostly intended for error handling and making tests deterministic but does tell you whether or not you wrote to the HTTP cache), which is a good place to put more stuff like cacheHit

We're not going to have time to implement the rest of this as part of the development spike we're doing right now, but if somebody else wanted to add more fields to httpCache it would be a great PR for us to review. I think you'd want to be able to learn if it was a cache hit, a cache miss but we wrote the value to the cache, a cache almost-hit where it was revalidated with a 304 response, etc. Would also be interesting to return the TTL if it's writing to the cache. This should be a backwards-compatible change.

@stevengssns
Copy link

Not sure if I need to put the PR in Draft status or not, but in any case I hope to get some feedback before adding the unit tests etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants