mikebronner / laravel-model-caching

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

How to control failed connections with cache in order to use the DB when it's needed? #301

Open andreshg112 opened 4 years ago

andreshg112 commented 4 years ago

Issue

I would like to connect to DB when the cache connection fails or there is a timeout. Is it possible to do it? It would be like a fallback connection.

Environment

Laravel Version: 5.6.39 Laravel Model Caching Package Version: 0.3.7 PHP Version: 7.2.13 Operating System & Version: mac OS Catalina (10.15)

mikebronner commented 4 years ago

If cache does not resolve, it should automatically pull from DB. Are you experiencing a specific issue? If so, please provide a stack trace, and any configuration information, as well as the eloquent query, so we can try to replicate the problem. Ideally this would be in a public test repo.

andreshg112 commented 4 years ago

If I create a fake connection, I get the error below. The thing is that I would like to control or avoid cache errors, so it can connect to DB.

{
  "message": "php_network_getaddresses: getaddrinfo failed: Name or service not known",
  "exception": "RedisException",
  "file": "/var/www/vendor/laravel/framework/src/Illuminate/Redis/Connectors/PhpRedisConnector.php",
  "line": 109,
  "trace": [
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Redis/Connectors/PhpRedisConnector.php",
      "line": 109,
      "function": "connect",
      "class": "Redis",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Redis/Connectors/PhpRedisConnector.php",
      "line": 66,
      "function": "establishConnection",
      "class": "Illuminate\\Redis\\Connectors\\PhpRedisConnector",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Support/helpers.php",
      "line": 1041,
      "function": "Illuminate\\Redis\\Connectors\\{closure}",
      "class": "Illuminate\\Redis\\Connectors\\PhpRedisConnector",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Redis/Connectors/PhpRedisConnector.php",
      "line": 83,
      "function": "tap"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Redis/Connectors/PhpRedisConnector.php",
      "line": 23,
      "function": "createClient",
      "class": "Illuminate\\Redis\\Connectors\\PhpRedisConnector",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Redis/RedisManager.php",
      "line": 79,
      "function": "connect",
      "class": "Illuminate\\Redis\\Connectors\\PhpRedisConnector",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Redis/RedisManager.php",
      "line": 61,
      "function": "resolve",
      "class": "Illuminate\\Redis\\RedisManager",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Cache/RedisStore.php",
      "line": 223,
      "function": "connection",
      "class": "Illuminate\\Redis\\RedisManager",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Cache/RedisStore.php",
      "line": 54,
      "function": "connection",
      "class": "Illuminate\\Cache\\RedisStore",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Cache/Repository.php",
      "line": 86,
      "function": "get",
      "class": "Illuminate\\Cache\\RedisStore",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/genealabs/laravel-model-caching/src/Traits/Caching.php",
      "line": 116,
      "function": "get",
      "class": "Illuminate\\Cache\\Repository",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/genealabs/laravel-model-caching/src/Traits/Caching.php",
      "line": 99,
      "function": "getCacheCooldownDetails",
      "class": "GeneaLabs\\LaravelModelCaching\\CachedBuilder",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/genealabs/laravel-model-caching/src/Traits/Caching.php",
      "line": 128,
      "function": "getModelCacheCooldown",
      "class": "GeneaLabs\\LaravelModelCaching\\CachedBuilder",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/genealabs/laravel-model-caching/src/CachedBuilder.php",
      "line": 278,
      "function": "checkCooldownAndRemoveIfExpired",
      "class": "GeneaLabs\\LaravelModelCaching\\CachedBuilder",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/genealabs/laravel-model-caching/src/CachedBuilder.php",
      "line": 233,
      "function": "retrieveCachedValue",
      "class": "GeneaLabs\\LaravelModelCaching\\CachedBuilder",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/genealabs/laravel-model-caching/src/CachedBuilder.php",
      "line": 162,
      "function": "cachedValue",
      "class": "GeneaLabs\\LaravelModelCaching\\CachedBuilder",
      "type": "->"
    },
    {
      "file": "/var/www/app/Http/Controllers/AltRoutesController.php",
      "line": 70,
      "function": "paginate",
      "class": "GeneaLabs\\LaravelModelCaching\\CachedBuilder",
      "type": "->"
    },
    {
      "function": "index",
      "class": "App\\Http\\Controllers\\AltRoutesController",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Controller.php",
      "line": 54,
      "function": "call_user_func_array"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php",
      "line": 45,
      "function": "callAction",
      "class": "Illuminate\\Routing\\Controller",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Route.php",
      "line": 212,
      "function": "dispatch",
      "class": "Illuminate\\Routing\\ControllerDispatcher",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Route.php",
      "line": 169,
      "function": "runController",
      "class": "Illuminate\\Routing\\Route",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
      "line": 665,
      "function": "run",
      "class": "Illuminate\\Routing\\Route",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
      "line": 30,
      "function": "Illuminate\\Routing\\{closure}",
      "class": "Illuminate\\Routing\\Router",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/barryvdh/laravel-cors/src/HandleCors.php",
      "line": 36,
      "function": "Illuminate\\Routing\\{closure}",
      "class": "Illuminate\\Routing\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
      "line": 151,
      "function": "handle",
      "class": "Barryvdh\\Cors\\HandleCors",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
      "line": 53,
      "function": "Illuminate\\Pipeline\\{closure}",
      "class": "Illuminate\\Pipeline\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php",
      "line": 41,
      "function": "Illuminate\\Routing\\{closure}",
      "class": "Illuminate\\Routing\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
      "line": 151,
      "function": "handle",
      "class": "Illuminate\\Routing\\Middleware\\SubstituteBindings",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
      "line": 53,
      "function": "Illuminate\\Pipeline\\{closure}",
      "class": "Illuminate\\Pipeline\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
      "line": 104,
      "function": "Illuminate\\Routing\\{closure}",
      "class": "Illuminate\\Routing\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
      "line": 667,
      "function": "then",
      "class": "Illuminate\\Pipeline\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
      "line": 642,
      "function": "runRouteWithinStack",
      "class": "Illuminate\\Routing\\Router",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
      "line": 608,
      "function": "runRoute",
      "class": "Illuminate\\Routing\\Router",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
      "line": 597,
      "function": "dispatchToRoute",
      "class": "Illuminate\\Routing\\Router",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
      "line": 176,
      "function": "dispatch",
      "class": "Illuminate\\Routing\\Router",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
      "line": 30,
      "function": "Illuminate\\Foundation\\Http\\{closure}",
      "class": "Illuminate\\Foundation\\Http\\Kernel",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/fideloper/proxy/src/TrustProxies.php",
      "line": 57,
      "function": "Illuminate\\Routing\\{closure}",
      "class": "Illuminate\\Routing\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
      "line": 151,
      "function": "handle",
      "class": "Fideloper\\Proxy\\TrustProxies",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
      "line": 53,
      "function": "Illuminate\\Pipeline\\{closure}",
      "class": "Illuminate\\Pipeline\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
      "line": 31,
      "function": "Illuminate\\Routing\\{closure}",
      "class": "Illuminate\\Routing\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
      "line": 151,
      "function": "handle",
      "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
      "line": 53,
      "function": "Illuminate\\Pipeline\\{closure}",
      "class": "Illuminate\\Pipeline\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
      "line": 31,
      "function": "Illuminate\\Routing\\{closure}",
      "class": "Illuminate\\Routing\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
      "line": 151,
      "function": "handle",
      "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
      "line": 53,
      "function": "Illuminate\\Pipeline\\{closure}",
      "class": "Illuminate\\Pipeline\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php",
      "line": 27,
      "function": "Illuminate\\Routing\\{closure}",
      "class": "Illuminate\\Routing\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
      "line": 151,
      "function": "handle",
      "class": "Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
      "line": 53,
      "function": "Illuminate\\Pipeline\\{closure}",
      "class": "Illuminate\\Pipeline\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php",
      "line": 62,
      "function": "Illuminate\\Routing\\{closure}",
      "class": "Illuminate\\Routing\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
      "line": 151,
      "function": "handle",
      "class": "Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
      "line": 53,
      "function": "Illuminate\\Pipeline\\{closure}",
      "class": "Illuminate\\Pipeline\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/barryvdh/laravel-cors/src/HandlePreflight.php",
      "line": 29,
      "function": "Illuminate\\Routing\\{closure}",
      "class": "Illuminate\\Routing\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
      "line": 151,
      "function": "handle",
      "class": "Barryvdh\\Cors\\HandlePreflight",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
      "line": 53,
      "function": "Illuminate\\Pipeline\\{closure}",
      "class": "Illuminate\\Pipeline\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
      "line": 104,
      "function": "Illuminate\\Routing\\{closure}",
      "class": "Illuminate\\Routing\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
      "line": 151,
      "function": "then",
      "class": "Illuminate\\Pipeline\\Pipeline",
      "type": "->"
    },
    {
      "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
      "line": 116,
      "function": "sendRequestThroughRouter",
      "class": "Illuminate\\Foundation\\Http\\Kernel",
      "type": "->"
    },
    {
      "file": "/var/www/public/index.php",
      "line": 55,
      "function": "handle",
      "class": "Illuminate\\Foundation\\Http\\Kernel",
      "type": "->"
    }
  ]
}
mikebronner commented 4 years ago

@andreshg112 Not sure how possible that is at the moment. Thanks for submitting this use-case. I can see this would come in handy if the Redis server unexpectantly was offline.

andreshg112 commented 4 years ago

What files should I change in order to achieve this? So I could create a pull requests.

mikebronner commented 4 years ago

@andreshg112 Sorry, at this time I have no idea, it would be something I have to research. My best suggestion for now would be to start playing around through trial and error, and maybe submitting a PR with your findings. :)

zlanich commented 4 years ago

I'm also curious about this, as I'm having occasional silent cache purge failures with Redis. It does not seem to throw any uncaught exception within that request, but once the page reloads, it's clear that the cache was not invalidated, and old values are showing on the screen that do not match the database. This is creating serious intermittent data integrity issues.

Does anyone have any thoughts on whether this seems odd? I would think Redis would throw a hard error if you tried to write to it and it failed, or at least allow us to intercept and retry or something.

mikebronner commented 4 years ago

@zlanich Thanks for the adding your observations! Can you think of a way we could reproduce this problem consistently?

zlanich commented 4 years ago

@mikebronner I wish I could. It was reported to us in our production environment, and we could not reproduce it, leading me to believe that the purge fails on occasion. I'm assuming it's due to a Redis connection error, but since it's not reporting anything when this happens, I can't be certain.

For now, I ended up writing custom middlewares, etc and disabling model cache in our admin UI and on write endpoints in the mobile app API just to minimize the effect. I also upgraded from predis to phpredis hoping it would help in some way.

This is tough thing, because it really needs addressed, but it's intermittent. Gah!

geniqtech commented 1 year ago

I'm facing similar issue when Redis server is down. Tested by manually stopping the Redis server.

Here's the log: Connection refused {"exception":"[object] (RedisException(code: 0): Connection refused at [path_to_web_root]/vendor/laravel/framework/src/Illuminate/Redis/Connectors/PhpRedisConnector.php:161)"}

Laravel version: 10.x (Using phpredis extension) Redis version: 6.2.7 (Standalone)