skip to Main Content

Problem

I need to setup Symfony framework.yaml parameter framework.lock with 2+ memcached servers using .env. But when I’m try to do so, it not recognize 2 servers, but only one and with glitch.

Symfony lock docs: https://symfony.com/doc/current/lock.html

What I have tried (with code snippets):

Passing via .env

  • I have .env file with following content:
MEMCACHE_SERVERS='memcached://m1.docker:11211,memcached://m2.docker:11211'
  • Have framework.yaml file with following content:
framework:
    lock: '%env(MEMCACHE_SERVERS)%'
  • Have following controller method to see a created lock object as debug
    /**
     * @Route("/example")
     */
    public function exampleAction(LockFactory $lockFactory): JsonResponse
    {
        dd($lockFactory->createLock('testing-lock', 2));
    }
  • It returns me following. The host recognized as m1.docker:11211,memcached", the second even not detected.
-store: SymfonyComponentLockStoreMemcachedStore {#22171 ▼
    -memcached: Memcached {#23004 ▼
      servers: array:1 [▼
        0 => array:3 [▼
          "host" => "m1.docker:11211,memcached"
          "port" => 11211
          "type" => "TCP"
        ]
      ]
      options: {▶}
    }
    -initialTtl: 300
    -useExtendedReturn: null
  }

Passing directly to lock parameter

  • If I’m passing the values directly to framework.lock, without using .env. It works.
lock: ['memcached://m1.docker:11211','memcached://m2.docker:11211']
  • Result:
  -store: SymfonyComponentLockStoreCombinedStore {#22386 ▼
    -stores: array:2 [▼
      0 => SymfonyComponentLockStoreMemcachedStore {#23199 ▼
        -memcached: Memcached {#22471 ▼
          servers: array:1 [▼
            0 => array:3 [▼
              "host" => "m1.docker"
              "port" => 11211
              "type" => "TCP"
            ]
          ]
          options: {▶}
        }
        -initialTtl: 300
        -useExtendedReturn: null
      }
      1 => SymfonyComponentLockStoreMemcachedStore {#22514 ▼
        -memcached: Memcached {#22625 ▼
          servers: array:1 [▼
            0 => array:3 [▼
              "host" => "m2.docker"
              "port" => 11211
              "type" => "TCP"
            ]
          ]
          options: {▶}
        }
        -initialTtl: 300
        -useExtendedReturn: null
      }
    ]

Question

The question. How I can pass the 2+ memcached servers to framework.lock using .env?

2

Answers


  1. Chosen as BEST ANSWER

    From answers

    Nico Haase gave the answer. It's known issue http://github.com/symfony/symfony/issues/40906.

    Summary of github thread on problem:

    "This issue is about a bug in Symfony where an environment variable cannot be parsed into an array. The bug is caused by the logic in the Configuration class. There are a few proposed solutions, but no consensus has been reached."

    Custom solution 1. Extension approach

    I have tried to invent the workaround with AppExtension and it works.

        public function prepend(ContainerBuilder $container): void
        {
            $envName = 'MEMCACHE_SERVERS';
    
            $serversAsCsv = getenv($envName);
            
            if (empty($serversAsCsv)) {
                throw new LogicException(sprintf('Check that %s env is set and not empty', $envName));
            }
    
            $hostsList = str_getcsv($serversAsCsv, ',', '"', PHP_VERSION_ID >= 70400 ? '' : '\');
    
            $container->setParameter('cache.memcached.servers', $hostsList);
        }
    

    Custom solution 2 framework.php:

    use SymfonyConfigFrameworkConfig;
    
    return static function (FrameworkConfig $framework): void {
        $framework->lock()
            ->resource('default', explode(',', getenv('MEMCACHE_SERVERS_2')))
        ;
    };
    

  2. lock: '%env(MEMCACHE_SERVERS)%' and lock: ['memcached://m1.docker:11211','memcached://m2.docker:11211'] looks pretty different to me – I would assume that the array makes the difference here.

    Please try to set the env variable such that it contains an array:

    MEMCACHE_SERVERS='["memcached://m1.docker:11211","memcached://m2.docker:11211"]'

    Afterwards, configure the lock such that it parses the given array:

    framework:
       lock: '%env(json:MEMCACHE_SERVERS)%'
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search