Cache driver switch in Laravel while failing connection
Tags: redis, laravel, cache, storage
Published: 2023-03-02 14:27:36

## Common Usage of Cache Driver
While working with small projects ex. SPA(Single Page Application), Module based feature(Payment Gateway), Small service provider etc. no need to deal with big sets of data while rendering. But while working with large scale application with proper scalability, Less rendering time and faster data loading we often face with loading issue and database connection issue.

To mitigate those issues, We often use cache driver to store data for certain time to process data faster and there no need to fetch from database or query from there. 

Laravel [cache driver](https://laravel.com/docs/8.x/cache) is used in some large-scale application to maintain data readability, faster execution and data filtering. But when comes the worst scenario mentioned below what we have to do is to deal with some exceptions with bare hand:

- Cache driver failed to connect ex. **Redis**

- Cache driver stop responding or shut down for some issue.

- Data storing or data fetching unknown exception raised.

For those, Application falls and client disappointment is raised too high. To prevent this kind of situation, We have to switch immediately from one cache driver to another without delay and not manually.

In Laravel, There is a tricky but much efficient to do switch cache drivers.

## Switch cache driver in Laravel
Suppose, We set **Redis** as cache driver but we have file driver for cache storing as well. If **Redis** shut down accidently, We have to switch to file driver by using below operation:

```
class CacheConnectionValidator // Cache connection checker
{
    /**
     * @return void
     */
    public static function checkAndUpdateCacheDriver() : void
    {
        $redis_host = env("REDIS_HOST"); // primary set cache host
        $redis_port = env("REDIS_PORT"); // primary set cache host port
        if(!self::checkPortConnection($redis_host,$redis_port)){
            config(['cache.default' => 'file']);
        }
    }

    /**
     * @param string $redis_host
     * @param string $redis_port
     *
     * @return bool
     */
    private static function checkPortConnection($redis_host,$redis_port) // check host return response
    {
        try{
            $connection = fsockopen($redis_host, $redis_port, $errno, $errstr, 20);
            if( !$connection ){
                return false;
            } else {
                return true;
            }
        } catch(Exception $e){
            return false;
        }
    }
}
```
Here, **CacheConnectionValidator** class will check, validate and set the storage for default cache driver for data processing.

[fsockopen()](https://www.php.net/manual/en/function.fsockopen.php) is used here to open the external source socket connection to check connection establishment during any application runtime. We can use [pfsockopen()](https://www.php.net/manual/en/function.pfsockopen.php) which is identical to fsockopen() but fsockopen() is closing after script finishing but pfsockopen() is running even after script finishing.
If connection returns true, It means the host is responding but if the connection returns false immediately set the file as default cache driver.

```
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        // While boot the class will be called
        CacheConnectionValidator::checkAndUpdateCacheDriver();
    }
```
The **CacheConnectionValidator** class should be registered in boot function in **AppServiceProvider** to load the script.

The whole process is sketched in following:


![Cache storage switch journey](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eefxf2hum4g36bon5ehp.png)

**There are lot more packages ex. Predis, PhpRedis to catch the Redis connection exception but they sometimes unable to catch exception while falling in runtime. So, It will be secure and safe to use php built in functions to catch the exception and take immediate action**

Have a good lara-day 😎