Skip to content

Commit 4f92e2f

Browse files
authored
Merge pull request #18 from byjg/5.0
Add support for Memcached client options in MemcachedEngine
2 parents b52b5d7 + 9620942 commit 4f92e2f

File tree

4 files changed

+70
-15
lines changed

4 files changed

+70
-15
lines changed

.github/workflows/phpunit.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,6 @@ jobs:
4949
with:
5050
folder: php
5151
project: ${{ github.event.repository.name }}
52-
secrets: inherit
52+
secrets:
53+
DOC_TOKEN: ${{ secrets.DOC_TOKEN }}
5354

docs/class-memcached-engine.md

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,44 @@ This class uses the Memcached as the cache engine.
55
## Defining the Servers
66

77
The constructor expects an array of servers.
8-
Each server is an item in the array with the following format:
8+
Each server can be provided in one of the following formats:
99

1010
```php
1111
$servers = [
1212
'localhost:11211',
13-
]
13+
['host.example', 11211],
14+
];
15+
```
16+
17+
You can also pass Memcached client options (no need to pass a Memcached instance). Options can be provided as an associative array where the keys are Memcached option constants or their string names:
18+
19+
```php
20+
$options = [
21+
\Memcached::OPT_DISTRIBUTION => \Memcached::DISTRIBUTION_CONSISTENT,
22+
\Memcached::OPT_LIBKETAMA_COMPATIBLE => true,
23+
\Memcached::OPT_REMOVE_FAILED_SERVERS => true,
24+
\Memcached::OPT_CONNECT_TIMEOUT => 100, // ms
25+
// Or using string keys:
26+
'OPT_CONNECT_TIMEOUT' => 100,
27+
];
1428
```
1529

1630
## PSR-16 Constructor
1731

1832
```php
19-
$cache = new \ByJG\Cache\Psr16\MemcachedEngine($servers)
33+
$cache = new \ByJG\Cache\Psr16\MemcachedEngine($servers, null, $options);
2034
```
2135

2236
## PSR-6 Constructor
2337

2438
```php
25-
$cachePool = \ByJG\Cache\Factory::createMemcachedPool($servers)
39+
$cachePool = \ByJG\Cache\Factory::createMemcachedPool($servers, 10, null, $options)
2640
```
2741

2842
or
2943

3044
```php
31-
$cachePool = new \ByJG\Cache\Psr6\CachePool(new \ByJG\Cache\Psr16\MemcachedEngine($servers));
45+
$cachePool = new \ByJG\Cache\Psr6\CachePool(new \ByJG\Cache\Psr16\MemcachedEngine($servers, null, $options));
3246
```
3347

3448

src/Factory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ public static function createArrayPool(int $bufferSize = 10, ?LoggerInterface $l
5454
);
5555
}
5656

57-
public static function createMemcachedPool(?array $servers = null, int $bufferSize = 10, ?LoggerInterface $logger = null): CachePool
57+
public static function createMemcachedPool(?array $servers = null, int $bufferSize = 10, ?LoggerInterface $logger = null, ?array $options = null): CachePool
5858
{
5959
return new CachePool(
60-
new MemcachedEngine($servers, $logger),
60+
new MemcachedEngine($servers, $logger, $options),
6161
$bufferSize
6262
);
6363
}

src/Psr16/MemcachedEngine.php

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ class MemcachedEngine extends BaseCacheEngine implements AtomicOperationInterfac
2525

2626
protected ?array $servers = null;
2727

28-
public function __construct(?array $servers = null, $logger = null)
28+
protected ?array $options = null;
29+
30+
public function __construct(?array $servers = null, $logger = null, ?array $options = null)
2931
{
3032
$this->servers = (array)$servers;
3133
if (is_null($servers)) {
@@ -34,10 +36,12 @@ public function __construct(?array $servers = null, $logger = null)
3436
];
3537
}
3638

37-
$this->logger = $logger;
38-
if (is_null($logger)) {
39+
$this->logger = $logger instanceof LoggerInterface ? $logger : null;
40+
if (is_null($this->logger)) {
3941
$this->logger = new NullLogger();
4042
}
43+
44+
$this->options = $options;
4145
}
4246

4347
/**
@@ -58,13 +62,49 @@ protected function lazyLoadMemCachedServers(): void
5862
{
5963
if (is_null($this->memCached)) {
6064
$this->memCached = new Memcached();
65+
66+
// Apply options if provided
67+
if (is_array($this->options)) {
68+
foreach ($this->options as $opt => $val) {
69+
// Accept both numeric keys (constants) and string keys like 'OPT_CONNECT_TIMEOUT'
70+
if (is_string($opt) && defined(Memcached::class . '::' . $opt)) {
71+
$opt = constant(Memcached::class . '::' . $opt);
72+
}
73+
if (is_int($opt)) {
74+
$this->memCached->setOption($opt, $val);
75+
} else {
76+
$this->logger->warning("[Memcached] Failed to set option {$opt} with value " . json_encode($val));
77+
}
78+
}
79+
}
80+
81+
// Add servers. Accept formats:
82+
// - ['host:port', ...]
83+
// - [['host', port], ...]
6184
foreach ($this->servers as $server) {
62-
$data = explode(":", $server);
63-
$this->memCached->addServer($data[0], intval($data[1]));
85+
$host = null;
86+
$port = null;
87+
if (is_string($server)) {
88+
$data = explode(":", $server);
89+
$host = $data[0] ?? '127.0.0.1';
90+
$port = isset($data[1]) ? intval($data[1]) : 11211;
91+
} elseif (is_array($server) && isset($server[0])) {
92+
$host = (string)$server[0];
93+
$port = isset($server[1]) ? intval($server[1]) : 11211;
94+
}
95+
96+
if ($host === null || $port === null) {
97+
$this->logger->warning("[Memcached] Invalid server configuration skipped: " . json_encode($server));
98+
continue; // skip invalid entry
99+
}
100+
101+
$this->memCached->addServer($host, $port);
64102

103+
// Server health check
65104
$stats = $this->memCached->getStats();
66-
if (!isset($stats[$server]) || $stats[$server]['pid'] === -1) {
67-
throw new StorageErrorException("Memcached server $server is down");
105+
$key = $host . ':' . $port;
106+
if (!isset($stats[$key]) || (isset($stats[$key]['pid']) && $stats[$key]['pid'] === -1)) {
107+
throw new StorageErrorException("Memcached server {$key} is down");
68108
}
69109
}
70110
}

0 commit comments

Comments
 (0)