mikebronner / laravel-model-caching

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

Stale cached value returned where(...)->first() #453

Open aaroncameron opened 11 months ago

aaroncameron commented 11 months ago

Describe the bug Requesting the first (and unique) result with Model::where(...)->first() returns an old, incorrect result,

Eloquent Query

MyModel::where(['a'=>1,'b'=>2])->first();  // returns an old result

MyModel::where(['a'=>1,'b'=>2])->get()->first(); // returns the correct result.

Environment

Additional context That the result in my test case is unique may or may not be relevant. Have not constructed a test where it is not to confirm.

There is in the above a unique key across a,b. The result is not simply coincidentally unique, but is by definition.

aaroncameron commented 9 months ago

Just to update with another case discovered, for non-unique result sets, different symptom and way to trigger:

MyModel::where('cond', true)->first(); // returns no results
MyModel::where('cond', true)->get()->first(); // returns the correct result
MyModel::where('cond', true)->limit(1)->get()->first(); // also returns no results.
mikebronner commented 9 months ago

thanks for the added details Aaron. These should not be happening. I will take a look at the tests later today and see what's going on.

mikebronner commented 9 months ago

I've been doing some testing and have found the following:

Could you send me the full query you are having issues with? Perhaps that will give me some additional clues to look for.

aaroncameron commented 9 months ago

Sure thing. I don't recall the code that was the source of my original case any longer, but the example I sent here was contrived anyway. Confirmed, but contrived. The version of the issue I found earlier today I still have though. TL;DR is it looks like the limit causes the cache to fail in some way.

Looks to me like the conditions don't even matter (other than the issue you found).

In all cases I confirmed the working/not working with the cache turned on, then turned the cache off with the query logging on to get the exact query generated.

Working:

DND5ECharacterSheet::where('is_premade', true)->get()->first();
select * from `dnd5e_character_sheets` where `is_premade` = ?
-- {"bindings":[true],"time":14.59} 

Not working:

DND5ECharacterSheet::where('is_premade', true)->limit(1)->get()->first();
select * from `dnd5e_character_sheets` where `is_premade` = ? limit 1
-- {"bindings":[true],"time":9.35} 

Not working:

DND5ECharacterSheet::where('is_premade', true)->first();
select * from `dnd5e_character_sheets` where `is_premade` = ? limit 1
-- {"bindings":[true],"time":6.52}