next-drupal icon indicating copy to clipboard operation
next-drupal copied to clipboard

Cache key expiration time

Open Jussiles opened this issue 3 years ago • 5 comments

Hi, thanks for great work with Next-drupal!

I’m implementing Redis caching for our project and was wondering could it be possible to have support for setting cache key expiration time? Is the any cache related enhancements coming in the near future?

Jussiles avatar Aug 08 '22 06:08 Jussiles

Hi.

We have started working on cache implementation. You can provide a custom cache via the cache option.

import { DrupalClient, DataCache } from "next-drupal"
import Redis from "ioredis"

const redis = new Redis(process.env.REDIS_URL)

export const redisCache: DataCache = {
  async set(key, value) {
    return await redis.set(key, value)
  },

  async get(key) {
    return await redis.get(key)
  },
}

export const drupal = new DrupalClient(
  process.env.NEXT_PUBLIC_DRUPAL_BASE_URL,
  {
    cache: redisCache,
  }
)

See also https://github.com/chapter-three/next-drupal/tree/main/examples/example-custom-cache

Can you elaborate the cache key expiration time please?

shadcn avatar Aug 08 '22 06:08 shadcn

I believe I’m familiar with the code above. Now it seems for me that e.g. getMenu caches the menu only on build time. I would like to be able to cache menu also in run time because it can be that content editors change the menu. Using Redis cache expiration time would be enough to keep it updated frequently.

With ioredis it could be done like this: redis.set("mykey", "hello", "EX", 10);

If you have better ideas I'm more that happy to know!

Jussiles avatar Aug 08 '22 07:08 Jussiles

I think it depends how you're handling the menus. If getMenu is called in getStaticProps, the only way to update the menu at runtime would be using on-demand ISR to revalidate the page.

This does not work as expected though because a menu expands several (if not all) pages on the site, so you end up having to revalidate everything.

The way we're handling this right now (for sites with menus that change all the time) is using client-side rendering for menu.

Untitled-2022-03-23-1048

  1. The page is built at build time (SSG)
  2. On load, the menu component makes a request to /api/menus/[name].ts
  3. /api/menus/[name].ts fetches and caches the menu tree on Redis.
  4. We use useQuery from react-query to cache the menu in the browser to prevent hitting the API on route change.

This way the getMenu call is cached on Redis and we invalidate the cache only when it changes on Drupal.

An example api/menus/[name].ts would look like this:

export default async function handler(req, res) {
  const name = req.query.name

  // 1. Check redis for cached menu

  // 2. Return if found.

  // 3. Otherwise fetch the menu from Drupal.
  const { tree } = await drupal.getMenu(req.query.name)

  // 4. Cache it.

  // 5. Return.
}

shadcn avatar Aug 08 '22 07:08 shadcn

Thanks for the info and ideas! This far I was just using ISR but now I started to think about implementing on-demand ISR. It is still experimental but will it be not experimental anymore in the future?

Jussiles avatar Aug 08 '22 08:08 Jussiles

Next.js 12.2 announced stable revalidation API. We're working on the Drupal end now to make it stable in the next release.

shadcn avatar Aug 08 '22 10:08 shadcn