cachingf#suave

Failing to use LazyCache with Suave's WebPart


I'm trying to use LazyCache (https://github.com/alastairtree/LazyCache) to cache some API requests.

The code goes as this:

let private cache = CachingService()
let doAPIStuff some parameters : WebPart = ...

let result = cache.GetOrAdd(hashedRequest, (fun _ -> doAPIStuff))

but I get this compile error:

  WebAPI.fs(59, 17): [FS0041] No overloads match for method 'GetOrAdd'.
Known types of arguments: string * ('a -> WebPart)
Available overloads:
 - (extension) IAppCache.GetOrAdd<'T>(key: string, addItemFactory: Func<'T>) : 'T // Argument 'addItemFactory' doesn't match
 - CachingService.GetOrAdd<'T>(key: string, addItemFactory: Func<Extensions.Caching.Memory.ICacheEntry,'T>) : 'T // Argument 'addItemFactory' doesn't match

These are the types available:

enter image description here

so I can do:

let doAPIStuff some parameters : Object = ...

and box my WebPart and it works fine. I understand that WebPart is a function (thanks for Fyodor in another question), but I don't understand why the function itself can't be in the cache as an object.


Solution

  • I think you need to explicitly create Func delegate in this case, otherwise F# compiler cannot distinguish between the two overloads.

    The type of the second argument (in the basic case) is Func<'T> i.e. a function taking unit and returning the value to be cached. This also means that, inside this function, you should call doAPIStuff with the parameters as arguments.

    Assuming this is in some actualRequest handler that takes some, parameters, the following should work:

    let cache = CachingService()
    
    let doAPIStuff some parameters : WebPart = 
      failwith "!"
    
    let actualRequest some parameters = 
      let hashedRequest = some + parameters
      let result = 
        cache.GetOrAdd(hashedRequest, 
          Func<_>(fun () -> doAPIStuff some parameters))
      result