Next.js Discord

Discord Forum

Better way of updating images using unstable_cache

Answered
American Shorthair posted this in #help-forum
Open in Discord
American ShorthairOP
I have been using unstable_cache to store URL's of images, the function updates the image. But the returned value is always the same link to the image. This feels jank, what's the better way to do this? I just am basically using the revalidate to make sure the image is staying updated, but the URL is the same so maybe unstable_cache isn't the best way?
Answered by joulev
interesting use case, then the way you did it is pretty much the best way to do, since the very data retrieval part itself is intended to have a side effect
View full answer

21 Replies

American ShorthairOP
I suppose storing the Base64 or whatever of the image would make the use case make sense, but is there really any benefit to doing that over just storing the image as a file in /public/? I feel like that may even be less efficient since you then wouldn't be able to use next/image
@joulev unstable_cache also updates the image? not a good idea to trigger an effect inside a query function
American ShorthairOP
trying to understand how that is any different than having a value update?
after revalidation, cached value updates
in my case, after revalidation, the image updates.
I suppose I could always add a ? something to the end of the URL it returns, so that the value is updated, and also makes sure the browser updates its cache with the new image.
what unstable_cache does is essentially
function unstable_cache(cb, revalidate) {
  return async (...args) => {
    const cacheKey = getCacheKey(cb, args);
    const data = cache.get(cacheKey)
    if (data && dataIsNotExpired(data))
      return data;
    const freshData = await cb(...args);
    cache.save(cacheKey, data);
    return freshData;
  }
}
unstable_cache is for functions that retrieve information, not functions that update information
@joulev what unstable_cache does is essentially tsx function unstable_cache(cb, revalidate) { return async (...args) => { const cacheKey = getCacheKey(cb, args); const data = cache.get(cacheKey) if (data && dataIsNotExpired(data)) return data; const freshData = await cb(...args); cache.save(cacheKey, data); return freshData; } }
American ShorthairOP
so then, if the cache needs to be revalidated, then it won't serve cached data it will wait until it gets the new data to serve it?
Because if so, that isn't super clear on the documentation and answers another help-forum post I have
and that's fair, I didn't think I was doing it the most proper way, but then I am wondering what would be the proper way.
@American Shorthair so then, if the cache needs to be revalidated, then it won't serve cached data it will wait until it gets the new data to serve it? Because if so, that isn't super clear on the documentation and answers another help-forum post I have
the above is just a simple reconstruction, the actual implementation is more complex. what i'm trying to say is, here the function is intended to be called for any number of times, so you should not trigger an update inside the function itself. the function should only query information
American ShorthairOP
I mean, that is why my post is phrased as the proper way of doing it. I already knew it wasn't correct.
hmm alright so what exactly are you trying to do?
American ShorthairOP
So, external API serves images. but it has limitations on how much you can use it. These images can change too, but not often.

So, I use the API to get the image, store it locally, then want to say revalidate it every 1-day or something. And this actually totally works to do that, I just know it isn't "proper"
as in you want to generate a new image URL pointing to the external API once every one day?
American ShorthairOP
Not exactly, it shouldn't point to the external API. It gets the .png from it, stores it on my server as a file. And not exactly "once per day" but more so next time it is attempted to be loaded + been 24hrs, to be more specific.
So if it doesn't get loaded, no reason to query the API for it again.
@American Shorthair Not exactly, it shouldn't point to the external API. It gets the .png from it, stores it on my server as a file. And not exactly "once per day" but more so next time it is attempted to be loaded + been 24hrs, to be more specific.
interesting use case, then the way you did it is pretty much the best way to do, since the very data retrieval part itself is intended to have a side effect
Answer
it's rare that when you run a data retrieval you would also want to trigger a side effect though, that's definitely not common
American ShorthairOP
yeah, probably the best that can be done with current next.js tooling, if I wanted something cleaner probably would have to make my own revalidation.

Im new to the idea of side-effects, what is the difference between storing an image that may change as a side-effect and also fetching data that is variable and changing, is that not a side-effect?
@American Shorthair yeah, probably the best that can be done with current next.js tooling, if I wanted something cleaner probably would have to make my own revalidation. Im new to the idea of side-effects, what is the difference between storing an image that may change as a side-effect and also fetching data that is variable and changing, is that not a side-effect?
the second way is the common way: something else changes the data (could be a user action, could be a cron job), and in the get function you only get the data

the first way where you read data and update it at the same time – this is not common
American ShorthairOP
alright, thanks for the noob-friendly explanations and your time.