Giter Club home page Giter Club logo

Comments (4)

eli-darkly avatar eli-darkly commented on July 23, 2024

Here's an example of what I mean. Let's say I have a cache and some kind of database, both stored in global variables. I want to load and cache the result of a database query whenever there's a cache miss. Using Fetch as it is now, I would do something like this:

func getCachedValueOrLoadValue(key string) (interface{}, error) {
   return myCache.Fetch(key, cacheTTL, func() (interface{}, error) {
      return myDatabase.Query(buildQueryForKey(key))
   }
}

That looks straightforward, but what happens internally is more like this (not exactly, but close enough):

type queryClosureParams struct {
    key string
}

func newQueryClosureParams(key string) *queryClosureParams {
   return &queryClosureParams{key}
}

func queryClosure(params *queryClosureParams) {
   return myDatabase.Query(buildQueryForKey(params.key))
}

func getCachedValueOrLoadValue(key string) (interface{}, error) {
   params := newQueryClosureParams(key)
   return myCache.Fetch(key, cacheTTL, func() (interface{}, error) {
      return queryClosure(params)
   }
}

What would avoid this is if there were an alternate Fetch (better name TBD, let's call it Fetch2 for now) that worked like so:

func loadValue(key string) (interface{}, error) {
   return myDatabase.Query(buildQueryForKey(key))
}

func getCachedValueOrLoadValue(key string) (interface{}, error) {
   return myCache.Fetch2(key, cacheTTL, loadValue)
}

There it doesn't have to create a closure— the function reference is just a simple function value, with no other state.

(This can be a bit tricky to get right because, if loadValue were a method of some component (like, func (c *MyComponent) loadValue(key string) (interface{}, error), it would still behave like a closure because the value of c is an implicit parameter. The workaround for that is that the MyComponent type would declare a field like loadValueFn func(string) (interface{}, error) and then its constructor would do c.loadValueFn := c.loadValue, which would create a closure that represents the instance method as a simple function— but it would only create it once, not once per query. Again, this is the kind of stuff that won't matter to many people but, since Go is a popular solution for high-traffic services, it makes sense to allow people to leverage Go's flexibility for best performance if they want to.)

from ccache.

karlseguin avatar karlseguin commented on July 23, 2024

Sorry to repeat my last answer, but I think having your own app-specific fetch makes sense. I think they're both good features, but the permutations of features people might want with fetch makes it hard to manage.

I think adding a section in the readme about 'custom fetches' might be useful.

Thoughts?

from ccache.

eli-darkly avatar eli-darkly commented on July 23, 2024

Well, I wasn't thinking about this just as an extra feature specific to Fetch, but also a basic design principle that I'd prefer for things to follow in the future even if the API of the existing things can't be changed now. In general, using a stateless function is preferable over using a stateful function (in regard to the state of an individual operation, that is; there might of course be some implicit state in the form of a database connection or whatever)— the latter will usually have some kind of disadvantage on any platform in either efficiency or other areas, I just mentioned the ones it happens to have in Go.

If you want to add some further docs about alternatives to Fetch, that's fine, although I would suggest putting that content in the doc comment for Fetch (at least, to clarify that it's not doing anything you can't already do via other public APIs) rather than in the readme.

from ccache.

eli-darkly avatar eli-darkly commented on July 23, 2024

Heh— I just realized that in my particular use case, where I'm also using singleflight, there's no way to completely get rid of this issue because singleflight.Group.Do also takes a nullary function. Ah well.

from ccache.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.