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

Getting a key that is not in the store doesn't automatically save it after the LoadFunction fetches value from data source #255

Closed
Michael-Girma opened this issue Jul 10, 2024 · 2 comments

Comments

@Michael-Girma
Copy link

I used gocache from github.com/patrickmn/go-cache and created a store. I then created a new loadable from that store with a LoadFunction to fetch the value if it's not in the cache already. The function seems to work fine but upon retrieval of the data element, it is not automatically stored in the store. Here is a small snippet for further investigation:

package main

import (
	"fmt"
	"time"

	"github.com/eko/gocache/cache"
	"github.com/eko/gocache/store"
	gocache "github.com/patrickmn/go-cache"
)

func main() {
	cacheClient := gocache.New(6*time.Hour, 12*time.Hour)
	cacheStore := store.NewGoCache(cacheClient, &store.Options{Expiration: 6 * time.Hour})

	mockCache := cache.NewLoadable(
		func(cacheApiKey interface{}) (interface{}, error) {
			fmt.Printf("Not in cache. Going to Datasource")
			// mock database response
			return "value", nil
		},
		cacheStore)

	mockCache.Get("Key")
	mockCache.Get("Key")
}

Steps for Reproduction

  1. Run the following snippet to cache unstored key
  2. View output

Expected behavior:
Expected output would only have a single log

Not in cache. Going to Datasource

Actual behavior:
Multiple logs indicating that fetched value isn't saved

Not in cache. Going to Datasource
Not in cache. Going to Datasource

Platforms:
uname -a:
Linux 6.8.0-36-generic #36-Ubuntu SMP PREEMPT_DYNAMIC Mon Jun 10 10:49:14 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

Include browser, operating system and respective versions

Versions:

  • github.com/eko/gocache v1.2.0
  • github.com/patrickmn/go-cache v2.1.0
@semihbkgr
Copy link
Contributor

semihbkgr commented Jul 13, 2024

The values returned from the loadFunc are sent to the setChannel instead of being directly set in the cache. The values in setChannel are iterated over in a separate goroutine and then set to the cache.

// Unable to find in cache, try to load it from load function
object, err = c.loadFunc(key)
if err != nil {
  return object, err
}

// Then, put it back in cache
c.setChannel <- &loadableKeyValue{key, object}

Therefore, you need to wait a bit before calling the second Get operation.

cacheClient := gocache.New(6*time.Hour, 12*time.Hour)
cacheStore := store.NewGoCache(cacheClient, &store.Options{Expiration: 6 * time.Hour})

mockCache := cache.NewLoadable(
  func(cacheApiKey interface{}) (interface{}, error) {
	  fmt.Printf("Not in cache. Going to Datasource")
	  // mock database response
	  return "value", nil
  },
  cacheStore)

mockCache.Get("Key")
time.Sleep(time.Second / 10)
mockCache.Get("Key")

@johnwook
Copy link

johnwook commented Aug 5, 2024

Thank you for clarifying! time.Sleep made it work!

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

3 participants