Coder Social home page Coder Social logo

Comments (9)

cihangir avatar cihangir commented on June 1, 2024

Hi @jimlindeman, Thanks for opening an issue before sending a PR

Do you have a fixed place for your tenant-id? (as prefix or suffix) If you have a similar architecture you can use the tenant id while constructing caches on the fly and assign the values to the sharded cache, by this way you could eliminate the need for a Keys() method.

I think a simple code could explain better

package cache

type ShardedNoTS struct {
    cache       map[string]Cache
    itemCount   map[string]int
    constructor func() Cache
}

func NewShardedNoTS(c func() Cache) *ShardedNoTS {
    return &ShardedNoTS{
        constructor: c,
        cache:       make(map[string]Cache),
        itemCount:   make(map[string]int),
    }
}

func (l *ShardedNoTS) Get(tenantId, key string) (interface{}, error) {
    cache, ok := l.cache[tenantId]
    if !ok {
        return nil, ErrNotFound
    }

    return cache.Get(key)
}

func (l *ShardedNoTS) Set(tenantId, key string, val interface{}) error {
    _, ok := l.cache[tenantId]
    if !ok {
        l.cache[tenantId] = l.constructor()
        l.itemCount[tenantId] = 0
    }

    l.itemCount[tenantId]++
    return l.cache[tenantId].Set(key, val)
}

func (l *ShardedNoTS) Delete(tenantId, key string) error {
    _, ok := l.cache[tenantId]
    if !ok {
        return nil
    }

    l.itemCount[tenantId]--

    if l.itemCount[tenantId] == 0 {
        return l.DeleteShard(tenantId)
    }

    return l.cache[tenantId].Delete(key)
}

func (l *ShardedNoTS) DeleteShard(tenantId string) error {
    delete(l.cache, tenantId)
    delete(l.itemCount, tenantId)

    return nil
}

This does not satisfy the Cache interface but just wanted to give the idea. If interface is important for you, you can pass a delimiter in the constructor of ShardedNoTS and split the tenant id and the key in the interface function implementations while satisfying the interface
smth like http://play.golang.org/p/FtMVzmY8AC

from cache.

jimlindeman avatar jimlindeman commented on June 1, 2024

The problem is that we have an indeterminate # of tenants when we scale to production (1 to 30000+), what you described above would just create leftovers with the l.cache[tenantId] when a tenant no longer uses the system (i.e. need a TTL on that layer too) and hundreds of GC threads needing to be run. That's why I'd prefer to just keep one cache layer with a single GC thread and just be able to query the current keys in the cache.

from cache.

jimlindeman avatar jimlindeman commented on June 1, 2024

Just realized if the GC method just iterated all the tenant indexed caches and used the regular Delete method, that should cleanup the cache fine with a single GC thread. I'd probably have to make one with the TTL logic like MemoryTTL too.

from cache.

cihangir avatar cihangir commented on June 1, 2024

So if understand you correctly, you want to modify StartGC function. I would be open to change the signature of it
func (r *MemoryTTL) StartGC(gcInterval time.Duration) {

to

type TTLFilter func(key string) bool
func (r *MemoryTTL) StartGC(gcInterval time.Duration, filters ...TTLFilter) {
// if len(filters) is 0 then set filters[0] to isValid

So we will be bakward compatible, wont add anything to interface and your problem will be solved.

What do you think?

from cache.

jimlindeman avatar jimlindeman commented on June 1, 2024

I ended up taking your original code sniplet and building a basic ShardedNoTS class with it, and then building a ShardedTTL class on top of it similar to how you built MemoryTTL on top of MemoryNoTS. The GC method only had to be in the higher level ShardedTTL class, and I was able to let that layer manage iteration of keys for GC and DeleteShard methods, as it could iterate the keys from its setAts structure:
// setAts holds the time that related item's set at, indexed by tenantId
setAts map[string]map[string]time.Time

I would just check it in and point you to it as I think it follows your original design, but I need to get management approval before putting it out there.

from cache.

cihangir avatar cihangir commented on June 1, 2024

Ok thanks for the update @jimlindeman

from cache.

jimlindeman avatar jimlindeman commented on June 1, 2024

Sorry for the long delay, but I finally got the approval to give our sharded cache changes back. The changes can be viewed at jimlindeman@17fd0d6 . I can create a PR if you're interested.

from cache.

cihangir avatar cihangir commented on June 1, 2024

Hi @jimlindeman Yes i would like to see your changes in this repo. I have small comments on some parts, we can talk about them when you open the PR.

from cache.

cihangir avatar cihangir commented on June 1, 2024

fixed with #5

from cache.

Related Issues (6)

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.