mikebronner / laravel-model-caching

Eloquent model-caching made easy.
MIT License
2.25k stars 212 forks source link

Cache not expiring #312

Closed liepumartins closed 4 years ago

liepumartins commented 4 years ago

Describe the bug Some records are persisted and not updated/expired in the cache despite a timeout being set.

Eloquent Query With necessary information about the models.

class Item extends Model { 
// not cacheable itself
    public function properties(): HasMany { 
        return $this->hasMany(Property::class);
    }
}

class Property extends Model {
    use Cacheable;
    protected $cacheCooldownSeconds = 300;
    public function value(): BelongsTo {
        return $this->belongsTo(Value::class);
    }
}

@property string name // the database field that keeps getting old values from cache
class Value extends Model {
    use Cacheable;
    protected $cacheCooldownSeconds = 300;
}

// returns $items with old property values. Older than a day or so.
$item->with('properties.value')->find(1);
App\Item { #3132 
  id: 1,
  name: "t3h Item",
  properties: Illuminate\Database\Eloquent\Collection { #3203
    all: [
      App\Value {#3141
        id: 5
        name: "Still old value shown"
      },
     App\Value {#3224
        id: 9
        name: "Another old value"
      },
  }
}

I had this problem with more than one model. In one case I disabled caching of Value model (removed Cacheable trait). In the other case I flushed the cache manually only for the Value model with php artisan modelCache:clear --model=App\\Value

Environment

Yes #307 and #308 seem to be related.

mikebronner commented 4 years ago

Using cachecooldown means that you are preventing the cache from automatically invalidating itself. Is that what you truly wanted to do?

liepumartins commented 4 years ago

I see that I have misunderstood the meaning of cachecooldown.

The thing is, these tables are (frequently) updated in the database directly via other means. Laravel only reads the data. I do not know, why I was led to believe that cachecooldown would be expiration/invalidation time. :man_facepalming:

So the real question is - how to make cached data invalid every X seconds, to force refresh from database?

EDIT: I do not see. Is there a way to invoke php artisan modelCache:clear --model=App\\Value from the program (without artisan)? Something like Value::clearModelCache()? I would create an API that could clear cache upon request. Since the frequency of each table update varies and it would not make sense to expire cache for unchanged data.

mikebronner commented 4 years ago

@liepumartins If you need to perform custom cache flushing, don't do it on a timer. Instead, clear the model cache for a specific model when something happens. You can trigger any artisan command from within code: https://laravel.com/docs/6.x/artisan#programmatically-executing-commands. Good luck. :)

liepumartins commented 4 years ago

I see that there is option to flush cache manually, I was looking for static method :man_facepalming: https://github.com/GeneaLabs/laravel-model-caching/blob/aa0253e3a5a6dfc5482b68cb177f50a746c30661/src/Console/Commands/Clear.php#L52

I created options for data updater to call flush, and will monitor how it goes.

EDIT: wow, did not see your reply. Was checking every day :D