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

Request add a keyPrefix option for the cacheable.wrap function #861

Closed
edwdch opened this issue Oct 24, 2024 · 1 comment
Closed

Request add a keyPrefix option for the cacheable.wrap function #861

edwdch opened this issue Oct 24, 2024 · 1 comment

Comments

@edwdch
Copy link

edwdch commented Oct 24, 2024

Is your feature request related to a problem? Please describe.

I am using the Wrap / Memoization for Sync and Async Functions of cacheable.

When I try to use the same cacheable instance to wrap two functions with the same type of parameters, this situation occurs.

import { describe, expect, it } from 'vitest'
import { Cacheable } from 'cacheable'

describe('cache', () => {
  it('wrap async function', async () => {
    const cache = new Cacheable()

    const plus = async (a: number, b: number) => a + b
    const plusCached = cache.wrap(plus, { ttl: 5 * 60 * 1000 })

    const multiply = async (a: number, b: number) => a * b
    const multiplyCached = cache.wrap(multiply, { ttl: 5 * 60 * 1000 })

    const res1 = await plusCached(1, 2)
    const res2 = await multiplyCached(1, 2)

    expect(res1).toBe(3)  // OK
    expect(res2).toBe(2)  // Failed: Expected 2 but received 3
  })
})

I checked the source code and found that in this line, I could only use a static key or the hash value of the parameters, which does not allow me to distinguish between different functions.

I currently have two solutions. But I don't know if these are the best practices.

  1. Use two different instances.
import { describe, expect, it } from 'vitest'
import { Cacheable } from 'cacheable'

describe('cache', () => {
  it('wrap async function', async () => {
    const cache1 = new Cacheable()
    const plus = async (a: number, b: number) => a + b
    const plusCached = cache1.wrap(plus, { ttl: 5 * 60 * 1000 })

    const cache2 = new Cacheable()
    const multiply = async (a: number, b: number) => a * b
    const multiplyCached = cache2.wrap(multiply, { ttl: 5 * 60 * 1000 })

    const res1 = await plusCached(1, 2)
    const res2 = await multiplyCached(1, 2)

    expect(res1).toBe(3)  // OK
    expect(res2).toBe(2)  // OK now
  })
})
  1. Use a custom wrapper function. Distinguish different functions by passing an additional string-type parameter prefix.
import { describe, expect, it } from 'vitest'
import { Cacheable } from 'cacheable'

describe('cache', () => {
  it('wrap async function with prefix', async () => {
    const cache = new Cacheable()

    function myWrap(prefix: string, fn: (...args: any[]) => any, options: { ttl?: number, key?: string }) {
      const wrapFn = cache.wrap(async (_, ...args) => {
        return await fn(...args)
      }, options)
      return async (...args: any[]) => {
        return await wrapFn(prefix, ...args)
      }
    }

    const plus = async (a: number, b: number) => a + b
    const plusCached = myWrap('plus', plus, { ttl: 5 * 60 * 1000 })

    const multiply = async (a: number, b: number) => a * b
    const multiplyCached = myWrap('multiply', multiply, { ttl: 5 * 60 * 1000 })

    const res1 = await plusCached(1, 2)
    const res2 = await multiplyCached(1, 2)

    expect(res1).toBe(3) // OK
    expect(res2).toBe(2) // OK now
  })
})

Describe the solution you'd like

Can an additional keyPrefix parameter be added, which will be prefixed to the actual cacheKey to distinguish between different functions?

wrap<T>(function_: (...arguments_: any[]) => T, options?: {
        ttl?: number;
        key?: string;
        keyPrefix?: string
    }): (...arguments_: any[]) => T;
@jaredwray
Copy link
Owner

@edwdch - this should be fixed now as the plan was to use the Key parameter as the prefix. Sorry about that. It will be released soon. 🎉

Here is the test that you built and it is passing now:

test('wrap async function', async () => {

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

No branches or pull requests

2 participants