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

How to deal with missing values with createBatch? #43

Closed
rosswarren opened this issue Apr 12, 2023 · 2 comments
Closed

How to deal with missing values with createBatch? #43

rosswarren opened this issue Apr 12, 2023 · 2 comments

Comments

@rosswarren
Copy link

Hi, thanks for creating this very useful library!

In the following example:

import type { CacheEntry } from 'cachified';
import LRUCache from 'lru-cache';
import { cachified, createBatch } from 'cachified';

type Entry = any;
const lru = new LRUCache<string, CacheEntry<string>>({ max: 1000 });

function getEntries(ids: number[]): Promise<Entry[]> {
  const batch = createBatch(getFreshValues);

  return Promise.all(
    ids.map((id) =>
      cachified({
        key: `entry-${id}`,
        cache: lru,
        getFreshValue: batch.add(id),
      }),
    ),
  );
}

async function getFreshValues(idsThatAreNotInCache: number[]): Entry[] {
  const res = await fetch(
    `https://example.org/api?ids=${idsThatAreNotInCache.join(',')}`,
  );
  const data = await res.json();

  return data as Entry[];
}

Imagine a scenario where some of the IDs that were requested in the fetch request do not return any result and are therefore missing from the data array. How should we deal with these missing values? Should we add null to the array or perhaps undefined?

Thanks!

@Xiphe
Copy link
Collaborator

Xiphe commented Apr 13, 2023

That's an interesting question! And I would like to take some time for discussion and to think about this before presenting a possible "goto" solution.


Here's whats coming to mind. (I don't have time to fully validate this right now, will do in the coming days)

Adding null or undefined as option for the Entry is definitely the way to go. But currently that would also store these values in cache and only revalidate them once their TTL is over. If that's what you intend you're good to go 👍

A scenario that is not possible right now (I think) would be when you want to NOT store the missing null in cache and have getFreshValues try to get them again asap.

@Xiphe Xiphe closed this as completed in 9ee69b0 Apr 14, 2023
@Xiphe
Copy link
Collaborator

Xiphe commented Apr 14, 2023

I've added/updated two sections about this to the readme and added the functionality to fine-tune cache-metadata in batch requests in the latest release v3.2.0.

see Fine-tuning cache metadata based on fresh values (This was already possible but not well documented, though this does not use createBatch the concept will also apply there)

I've also updated Batch requesting values to show the new onValue callback.


With this in mind here's what I'd do.

  • First and foremost, yes you want to add null, undefined or similar to the array you're expecting from the Promise.all
  • If you want to cache the information that you received an empty values exactly the same as the non-empty values, you don't need anything else.

If you want to not cache empty values or cache them for a much shorter time do something like this:

const batch = createBatch((ids): Promise<(string | null)[]> => {
  /* ... */
});

const values: (string | null)[] = await Promise.all(
  ids.map((id) =>
    cachified({
      /* cache and other options... */
      key: `entry-${id}`,
      ttl: 60_000,
      getFreshValue: batch.add(id, ({ value, metadata }) => {
        if (value === null) {
          /* -1 disables caching, you could also just set to a shorter time */
          metadata.ttl = -1;
        }
      }),
    })
  )
);

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

No branches or pull requests

2 participants