swayok / alternative-laravel-cache Goto Github PK
View Code? Open in Web Editor NEWReplacements for Laravel's redis and file cache stores that properly implement tagging idea
License: MIT License
Replacements for Laravel's redis and file cache stores that properly implement tagging idea
License: MIT License
Hi,
I went into trouble installing your packet.
I updated my Laravel 10 project (laravel/framework v10.24.0)
$ composer update
Loading composer repositories with package information
Updating dependencies
Nothing to modify in lock file
Installing dependencies from lock file (including require-dev)
Nothing to install, update or remove
Generating autoload files
83 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found.
and tried to install your package
$ composer require swayok/alternative-laravel-cache:*
./composer.json has been updated
Running composer update swayok/alternative-laravel-cache
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
- swayok/alternative-laravel-cache[5.3.1, ..., 5.4.7] require cache/predis-adapter ^0.4.0 -> satisfiable by cache/predis-adapter[0.4.0, 0.4.1, 0.4.2].
- swayok/alternative-laravel-cache[5.4.10, ..., 5.4.12] require cache/predis-adapter ^1.0.0 -> satisfiable by cache/predis-adapter[1.0.0, 1.1.0, 1.2.0].
- swayok/alternative-laravel-cache[6.1.5, ..., 6.1.12] require cache/adapter-common ^1.0.0 -> satisfiable by cache/adapter-common[1.0.0, 1.1.0, 1.2.0, 1.3.0].
- cache/predis-adapter 0.4.0 requires php ^5.5|^7.0 -> your php version (8.1.2) does not satisfy that requirement.
- cache/predis-adapter[0.4.1, ..., 0.4.2] require php ^5.5 || ^7.0 -> your php version (8.1.2) does not satisfy that requirement.
- swayok/alternative-laravel-cache[5.4.8, ..., 5.4.9] require laravel/framework 5.2.*|5.3.*|5.4.*|5.5.*|5.6.*|5.7.*|5.8.*|^6.0 -> found laravel/framework[v5.2.0, ..., v5.8.38, v6.0.0, ..., v6.20.44] but it conflicts with your root composer.json require (^10).
- cache/predis-adapter 1.0.0 requires php ^5.6 || ^7.0 -> your php version (8.1.2) does not satisfy that requirement.
- swayok/alternative-laravel-cache 5.4.13 requires php ^5.6 || ^7.0 -> your php version (8.1.2) does not satisfy that requirement.
- cache/adapter-common[1.0.0, ..., 1.1.0] require php ^5.6 || ^7.0 -> your php version (8.1.2) does not satisfy that requirement.
- cache/predis-adapter[1.1.0, ..., 1.2.0] require psr/simple-cache ^1.0 -> found psr/simple-cache[1.0.0, 1.0.1] but the package is fixed to 3.0.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- cache/adapter-common 1.3.0 require psr/simple-cache ^1.0 -> found psr/simple-cache[1.0.0, 1.0.1] but the package is fixed to 3.0.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- swayok/alternative-laravel-cache[6.0.0, ..., 6.1.4] require psr/simple-cache ^1.0.0 -> found psr/simple-cache[1.0.0, 1.0.1] but the package is fixed to 3.0.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- cache/adapter-common 1.2.0 requires psr/log ^1.0 -> found psr/log[1.0.0, ..., 1.1.4] but the package is fixed to 3.0.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- Root composer.json requires swayok/alternative-laravel-cache * -> satisfiable by swayok/alternative-laravel-cache[5.3.1, ..., 5.4.13, 6.0.0, ..., 6.1.12].
Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.
Installation failed, reverting ./composer.json and ./composer.lock to their original content.
but it is not possible because of conflicting requirements.
Is this something I would have do deal with after every other update if I manage to install this into my project?
Don't get me wrong. The original implementation does not make sense. I just have to take responsibility in my company for each additional dependency I bring in...
Cheers
Henning
Today after composer update, the laravel frmework upgraded from 7.27 to 7.28. After that, the application started to give me an error exception like below,
"Class 'Cache\Adapter\Filesystem\FilesystemCachePool' not found" error.
when I change the driver type from file to redis this time gives me "Class 'Cache\Adapter\Redis\RedisCachePool' not found".
Deeply inspection shows some adapters (file and redis ) removed by composer,
` - Removing cache/redis-adapter (1.0.0)
The package stores it's cache files in the storage/framework/cache/data/cache
folder. The cache
folder inside the data
folder does not have the write permissions when created. The following error occurs.
This is a serious problem on my ubuntu servers wich are auto deployed. I have to log in and set the permissions for the cache folder when i empty the cache using the php artisan cache:clear
command.
cache folder
set the permissions to be writable.storage/framework/cache/data
folder like laravel does. It don't understand why another folder is created to store the data in.I really really like this package with the tags solution. But this is not workable if i have to set the permissions every time i deploy a new update.
Hi, what would be involved in switching away from using cache/redis-adapter
to symfony/cache
with it's Redis Adapter?
https://symfony.com/doc/current/components/cache/adapters/redis_adapter.html
The reason is, cache/redis-adapter
looks like it's not going to support psr/cache ^3.0
which is slowly becoming a problem as time moves on, and I'd love to keep using this package because it's so much better than the default Laravel tagging.
php-cache/redis-adapter@558fd52#commitcomment-105598873
Thanks!
Hello,
First off, thanks for this package! We've been making use of this at my workplace, as we also expected Laravel's tagging to work as this package makes it work and were very disappointed to discover how Laravel actually implements it.
One issue I've ran into with this package, however, is caused by a combination of laravel/framework#34873
and the $this->setPrefix($prefix);
call over here: https://github.com/swayok/alternative-laravel-cache/blob/master/AlternativeLaravelCache/Core/AlternativeCacheStore.php#L67
The setPrefix
calls $this->getHierarchySeparator()
, which in turn calls $this->getWrappedConnection
, thereby instantiating the connection to the cache.
The Laravel issue linked above causes any artisan command to fully construct laravel commands, including the queue:restat command, which insantiates the cache itself:
https://github.com/laravel/framework/blob/259e0dcfd1bcdf5160ed789ee631921441e1fbe5/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php#L602-L607.
These two issues paired together make it problematic in CI for example, when running artisan commands, as the cache is instantiated, and this package attempts to connect to the cache server, which results in an error.
Laravel seems to have somewhat alleviated the issue, by allowing you to declare a static default signature in all commands starting with Laravel 9.x, but it hardly fixes the problem when adding custom commands to a Laravel project, unless you know exactly what he issue is.
To remove the problem entirely, I would like to raise a PR which fixes the issue within this package by somehow delaying the setPrefix call so that no connection is created during the constructor (haven't decided exactly how, suggestions are welcome).
Before I invest time into this, I'd like to know if you're interested in this contribution.
Thanks!
Hi, thank you for your work!
I use laravel 7 and memcached.
After installation, I got error Trait 'Illuminate\Cache\HasCacheLock' not found
Google says that the trait appeared in laravel 8. There are options to use on laravel 7?
Hi
Im using this library along with a local Redis cache.
However - After installing this library, my cron scheduler broke, so nothing is getting executed.
All api endpoints, commands, etc works, but cron broke.
Outputting cron to a file, I discovered Laravel saying 'Skipping command (has already run on another server)'.
Well, weird.
Almost all our jobs are executed within the Laravel scheduler in this form:
$schedule->command('job:import:something')
->everyMinute()
->withoutOverlapping()
->onOneServer()
->runInBackground()
->environments(['production']);
Digging through the scheduler and cache, I found that when using ->onOneServer(), cron puts a key into the cache store (for that moment in time it needs to be executed), and returns the value of it.
After switching to this library, that broke because ->put() method (and more) now returns void, and not the same as their parents within Laravel.
Effectively this causes the scheduler to die, as it doesnt get the right values back from the cache stores.
It was easily fixed, by finding all methods in the cache store that exists in Laravel cache store, and make sure they return the same values too though ...
Hi, can you update it to Laravel 8?
Is giving me this error after installation:
Uncaught Error: Class "Cache\Adapter\Redis\RedisCachePool" not found in /vendor/swayok/alternative-laravel-cache/AlternativeLaravelCache/Store/AlternativeRedisCacheStore.php:34
Thanks!
As of v1.1 the cache/array-adapter
supports hierarchal mode.
Test suites often use the array
driver since tests don't need a persistent cache and it's considerably faster than Redis. For example, our overall test suite is ~2x faster, which means a lot in CI minutes.
@swayok thanks for your consideration and this great lib! Was really banging my head against the wall until I found this.
Expected behavior
When you create a key with a tag:
Cache::tags('a')->rememberForever('x', fn () => 1)
You can remove this key by tag:
Cache::tags('a')->flush()
Bug
Because of race condition, the following code: Cache::tags('a')->flush()
sometimes won't remove the key 'x'.
How to reproduce
Race conditions are kinda tricky to catch. So there's chance involved. But I think I created a test to prove the problem.
I used Laravel Tinker and two terminals. In the first one I typed:
collect(range(0,100000))->each(fn()=> Cache::tags('a')->flush())
In the second one I typed:
collect(range(0,100000))->each(fn()=> Cache::tags('a')->rememberForever('x', fn () => 1))
I ran the first one and the second one as fast as I could for them to run simultaneously. We test an extreme conditions with many concurrent requests to redis.
Expected results of the test
I'm using Redis Commander to see the results in Redis. I expect two possible results:
flush()
ran in the end.rememberForever()
ran in the end.Actual results
Key x
with the information is present. But tag list a
isn't present. It means:
Cache::get('x')
Cache::tags('a')->flush()
. The information will be still there.Why it happens (possibly)
When you add information, the code: "creates a tag list" -> "creates a key".
When you remove information, the code: "deletes a tag list" -> "deletes a key".
With race condition when there are two concurrent requests, the code sometimes inserts "remove" operation into the "add" operation: "creates a tag list" -> ("removes a tag list" -> "removes a key") -> "adds a key". Which results in no tag list, but key is present.
Does it make sense? I don't know how to fix it, but I encountered this bug and I wanted to create an issue about it.
In this commit: e3aa7c2
You changed this part of code:
protected function getDefaultDuration() {
return 525600 * ($this->isDurationInSeconds() ? 60 : 1);
}
To this part of code:
protected function getDefaultDuration(): int {
return 525600;
}
You said in the release:
Removed outdated code related to Laravel <= 5.6 (cache expected minutes for ttl, since 5.7 it expects seconds);
Unfortunately, you left minutes in the getDefaultDuration
, not seconds. It means that forever
function in Laravel saves for 6 days (525600 seconds), not a year (525600 * 60 seconds).
The correct version would be:
protected function getDefaultDuration(): int {
return 525600 * 60;
}
Or
protected function getDefaultDuration(): int {
return 31536000;
}
In short, when using this package with Redis, and the php-redis extension, the Laravel Telescope RedisWatcher will no longer register/log any events.
While this package itself works fine, it is of concern that this is happening, as the Telescope watcher only works by listening to Redis events being fire, so if it isn't logging anything, I am concerned it means the events aren't being fired.
Details:
PHP: v7.4
Laravel: v6.20.26
Telescope: v3.5.1
I have also tested this all the way up to Laravel 8 and Telescope 5, with the same outcome... when using this package in combination with the cache/redis-adapter), Redis events are no longer logged.
I haver done a good amount of digging around, but sadly not found the cause yet, so felt logging here might invoke the hive mind :)
composer require swayok/alternative-laravel-cache:*
./composer.json has been updated
Running composer update swayok/alternative-laravel-cache
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
- lcobucci/jwt 3.4.6 requires php ^5.6 || ^7.0 -> your php version (8.0.13) does not satisfy that requirement.
- vonage/client 2.4.0 requires vonage/client-core ^2.0 -> satisfiable by vonage/client-core[2.9.3].
- vonage/client-core 2.9.3 requires lcobucci/jwt ^3.4|^4.0 -> satisfiable by lcobucci/jwt[3.4.6].
- vonage/client is locked to version 2.4.0 and an update of this package was not requested.
Laravel 11 was just released, and this is the only package that has not been updated yet.
Laravel ^7.30.1
Alternative Cache ^5.4
Steps to reproduce (using tinker):
// Put key with colons
Cache::put('cache-key:something:something-else', 'blah', now()->addHours(6));
// Put key with pipes
Cache::put('cache-key|something|something-else', 'blah', now()->addHours(6));
// Get key with colons
Cache::get('cache-key:something:something-else');
"blah"
// Get key with pipes
Cache::get('cache-key|something|something-else');
"blah"
// Forget call
Cache::forget('cache-key');
// Get key with colons
Cache::get('cache-key:something:something-else');
"blah"
// Get key with pipes
Cache::get('cache-key|something|something-else');
null
The call to Cache::get('cache-key|something|something-else');
should not return null
as it wasn't the whole correct key used in the forget
command.
Have tested this on a Laravel 8 install without Alternative Cache installed, and it's not a problem.
Either it's been fixed in Laravel 8 (couldn't find any mention) or this package seems to be clearing based on a partial match with pipes?
Hello.
I have multiply cache drivers. File and redis.
I have error when I set default cache driver to redis and try to put data to file store after redis store.
For example.
Cache::store('redis')->put('bar', 'baz', 10);
Cache::store('file')->put('bar', 'baz', 10);
On the first call AlternativeCacheStore::$hierarchySeparator
defined as '|' according to redis
store.
And this value is invalid for file store.
In my opinion, this is a bug, and hierarchySeparator must be related to current cache store (wrappedConnection).
Thanks.
Current release of Alternative Laravel Cache
PHP 8.1
Laravel 9.42
Octane
When doing combinations of Puts and Forgets on the same key name within the same call, different key hashes are generated resulting in unpredictable results.
It also appears that when requesting the keys different versions of the key are returned.
Hi!
When cache was small all work fine.
now cache contains 100k files and tag files become big.
when i try clear cache by tag or remove cache by name
and it exist in tag file
i get errors
[2021-05-26 08:23:40] prod.ERROR: unserialize(): Error at offset 147440 of 147456 bytes {"exception":"[object] (ErrorException(code: 0): unserialize(): Error at offset 147440 of 147456 bytes at /vendor/cache/filesystem-adapter/FilesystemCachePool.php:162)
[stacktrace]
our base contain 1kk elements each has own detail page - 1kk cached items with different tags will be..
This line tries to setLogger but what it does is also trying to connect to the redis instance.
That is problematic for obvious reasons (phpstan that runs native while project being in Docker trying to connect every time I make a change in the code), but also unnecessary connects when it doesn't need to.
I moved the setLogger call into getWrappedConnection() and it is working flawlesly now.
Hi
This is not an issue, just to appreciate the effort and to say this is exactly how tags should behave. I have no idea why Laravel is not adopting this already. I hope they will change the implementation soon.
When trying to use this package with PHPRedis:
'client' => 'phpredis'
I get the error:
Argument 1 passed to Cache\Adapter\Predis\PredisCachePool::__construct() must be an instance of Predis\ClientInterface, instance of Redis given, called in /vagrant/vendor/swayok/alternative-laravel-cache/src/AlternativeLaravelCache/Store/AlternativeRedisCacheStore.php on line 27
Does this package support using PHPRedis, and if so, what's the correct configuration?
In the readme.md file is an example on passing the permissions-configuration for file-based cache drivers in config/cache.php
I did literally copy the example code and change both public permissions to 0777, but files and directories are still being created with 644 etc.
I recreated the config, so it is not a cached config.
Also looked at #9 but that did not provide a solution.
Any clue? Any info I should provide?
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache/data'),
'permissions' => [
'file' => [
'private' => 0777,
'public' => 0777,
],
'dir' => [
'private' => 0777,
'public' => 0777,
],
]
],
When I dump $cacheConfig
in makeFileCacheAdapter from AlternativeCacheStoresServiceProvider.php, I do get the right values:
array:2 [▼
"file" => array:2 [▼
"private" => 511
"public" => 511
]
"dir" => array:2 [▼
"private" => 511
"public" => 511
]
]
Also in vendor/league/flysystem/src/Adapter/Local.php::__construct I get the right values
Steps to reproduce:
Clear your redis database and run this code:
Cache::tags(['tag1', 'tag2'])->put('test1', 'test1');
Cache::tags(['tag1', 'tag2'])->put('test1', 'test1');
Cache::tags(['tag1', 'tag2'])->put('test1', 'test1');
Cache::tags(['tag1', 'tag2'])->put('test1', 'test1');
Cache::tags(['tag1', 'tag2'])->put('test1', 'test1');
You will see two main lists for each tag, which seems correct:
But within each list, entries are duplicating:
This shouldn`t happen since the keys are the same.
Is it expected soon or waiting for this request ?
Hello,
I use this library to be able to run tests without relying on a redis connection.
Now I am facing a situation where I have to use atomic locks.
It would be nice to implement the LockProvider interface on AlternativeLaravelCache and use a filesystem lock strategy to implement Lock methods.
I can work on a PR if you find this useful.
Hi there.
Thanks for this library, it does exactly how I expected the default functionality to work. I'm having some issues with Laravel 5.8 though, as the cache TTL has changed from minutes to seconds.
See https://laravel.com/docs/5.8/releases#laravel-5.8 under PSR-16 Cache Compliance.
Are there any plans for an update?
Thanks.
https://laravel.com/docs/10.x/cache#pruning-stale-cache-tags
run cache:prune-stale-tags will get this message
ERROR Pruning cache tags is only necessary when using Redis.
Greetings,
This is indeed the wanted behavior of cache tags.
Unfortunately, your package does not seam to support latest stable Laravel 5.4
Here is the error :
Type error: Argument 1 passed to Cache\Adapter\Predis\PredisCachePool::__construct() must implement interface Predis\ClientInterface, instance of Illuminate\Redis\Connections\PredisConnection given, called in C:\XAMPP\htdocs\projects\konek-core\vendor\swayok\alternative-laravel-cache\src\AlternativeLaravelCache\Store\AlternativeRedisCacheStore.php on line 23
Hope you'll be able to fix this.
Thanks a bunch !
I'm not in a particular hurry to upgrade to Laravel 10, which was released yesterday. At a glance, I expect most cache drivers to just work. However, I did spot that there were changes to Redis cache tags: https://laravel.com/docs/10.x/upgrade#redis-cache-tags.
Do those changes impact this package, and should we be running the new command when using the alternative Redis cache?
in description you say use Cache::forget('tag-test1') instead
this mean what
Cache::tag('tag_1')->put('cache_key', $data, $time);
was overwritten by
Cache::tag('tag_2')->put('cache_key', $data, $time);
or will only be purge together? by
Cache::forget('cache_key')
and
Cache::tag('tag_1')->forget('cache_key') - leave alive tag_2 cache?
Hi,
I just installed the package for Laravel 8 - Laravel Framework 8.40.0
and composer dump is giving error :-
Error
Class 'Cache\Adapter\Filesystem\FilesystemCachePool' not found
at D:\dev\laravel\covid-data-analysis\vendor\swayok\alternative-laravel-cache\AlternativeLaravelCache\Store\AlternativeFileCacheStore.php:26
22▕ *
23▕ * @return AbstractCachePool|TaggableCacheItemPoolInterface
24▕ */
25▕ public function wrapConnection() {
➜ 26▕ return new FilesystemCachePool($this->getDb());
27▕ }
28▕
29▕ public function setPrefix($prefix) {
30▕ // allowed chars: "a-zA-Z0-9_.! "
1 D:\dev\laravel\covid-data-analysis\vendor\swayok\alternative-laravel-cache\AlternativeLaravelCache\Core\AlternativeCacheStore.php:105
AlternativeLaravelCache\Store\AlternativeFileCacheStore::wrapConnection()
2 D:\dev\laravel\covid-data-analysis\vendor\swayok\alternative-laravel-cache\AlternativeLaravelCache\Core\AlternativeCacheStore.php:115
AlternativeLaravelCache\Core\AlternativeCacheStore::getWrappedConnection()
Script @php artisan package:discover --ansi handling the post-autoload-dump event returned with error code 1
i tried to redump the composer but its giving same error
i dont think there is need but i still added \AlternativeLaravelCache\Provider\AlternativeCacheStoresServiceProvider::class,
to config\app.php
and cache.php looks like
'stores' => [
'apc' => [
'driver' => 'apc',
],
'array' => [
'driver' => 'array',
'serialize' => false,
],
'database' => [
'driver' => 'database',
'table' => 'cache',
'connection' => null,
'lock_connection' => null,
],
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache/data'),
'permissions' => [
'file' => [
'public' => 0644,
],
'dir' => [
'public' => 0755,
],
]
],
'memcached' => [
'driver' => 'memcached',
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
'sasl' => [
env('MEMCACHED_USERNAME'),
env('MEMCACHED_PASSWORD'),
],
'options' => [
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
],
'servers' => [
[
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
'port' => env('MEMCACHED_PORT', 11211),
'weight' => 100,
],
],
],
'redis' => [
'driver' => 'redis',
'connection' => 'cache',
'lock_connection' => 'default',
],
'dynamodb' => [
'driver' => 'dynamodb',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
'endpoint' => env('DYNAMODB_ENDPOINT'),
],
],
in composer.json it seems i am using "swayok/alternative-laravel-cache": "^6.1",
am i missing something ?
Hello,
Can not we put dependencies in composer suggest (https://getcomposer.org/doc/04-schema.md#suggest ) ?
If i use the driver file, I do not need the dependencies for redis, right ?
Thanks a lot ;)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.