sopheos / pebble_cache
PSR-16 caches (Memcached, in-memory), token bucket rate limiter and session handler
Requires
- php: >=8.1.0
- psr/simple-cache: ^3.0
Requires (Dev)
- phpunit/phpunit: ^9.5
Suggests
- ext-memcached: Required by Pebble\Cache\MemCache
Provides
None
Conflicts
None
Replaces
None
README
Système de mise en cache compatible PSR-16 (psr/simple-cache ^3.0) pour PHP 8.1+.
La lib fournit deux caches (Memcached et en mémoire), un limiteur de débit à seau de jetons et un gestionnaire de sessions PHP adossé à un cache.
Installation
composer require sopheos/pebble_cache
MemCache nécessite l'extension ext-memcached. Les autres classes s'en passent.
Claude Code
Ce package fournit un skill Claude Code dans skills/pebble-cache/. Il documente les patterns d'usage et les pièges de la librairie : TTL 0 qui signifie « jamais » et non « expiré », DateInterval en jours converti en 0 seconde, false stocké lu comme absent, clear() qui vide tout le serveur Memcached, has() de MicroCache qui ignore le préfixe, etc.
Dans un projet qui dépend de sopheos/pebble_cache, copie-le une fois dans .claude/skills/ après composer install pour que Claude Code le charge automatiquement. Le nom du dossier doit correspondre au name déclaré dans SKILL.md :
cp -r vendor/sopheos/pebble_cache/skills/pebble-cache .claude/skills/pebble-cache
Pour la maintenance de la lib elle-même, voir CLAUDE.md. Les bugs connus sont listés dans TODO.md.
CacheInterface
\Pebble\Cache\CacheInterface étend Psr\SimpleCache\CacheInterface et ajoute deux compteurs.
Méthodes PSR-16 :
get(string $key, mixed $default = null): mixedRécupère une donnée, ou$default.set(string $key, mixed $value, null|int|DateInterval $ttl = null): boolAjoute une donnée.delete(string $key): boolSupprime une donnée.clear(): boolVide le cache.getMultiple(iterable $keys, mixed $default = null): iterableRécupère un ensemble de données, sous la forme[clé => valeur].setMultiple(iterable $values, null|int|DateInterval $ttl = null): boolAjoute un ensemble de données[clé => valeur].deleteMultiple(iterable $keys): boolSupprime un ensemble de données.has(string $key): boolIndique si la clé existe.
Ajouts :
increment(string $key, null|int|DateInterval $ttl = null, int $offset = 1): boolIncrémente une valeur. Vaut$offsetsi elle n'existe pas.decrement(string $key, null|int|DateInterval $ttl = null, int $offset = 1): boolDécrémente une valeur. Vaut-$offsetsi elle n'existe pas avecMicroCache(voirTODO.mdpourMemCache).
Préfixe, commun à MemCache et MicroCache :
setPrefix(string $prefix): staticPréfixe ajouté à toutes les clés.getKey(string $key): stringClé préfixée.
Les clés ne sont pas validées : aucune InvalidArgumentException PSR-16 n'est levée.
MemCache
Implémente CacheInterface sur un serveur Memcached.
__construct(string $host = '127.0.0.1', int $port = 11211, array $options = [])Se connecte au serveur.$options(constantesMemcached::OPT_*) complète les options par défaut (protocole binaire, compression, sérialiseur PHP…). LèveCacheException('connection failed')si le serveur ne répond pas.getStore(): MemcachedL'instanceMemcachedsous-jacente.
Comportements :
- Un TTL
nullou0signifie « n'expire jamais ». Au-delà de 30 jours, il est converti en timestamp UNIX. - Une valeur
falsestockée est lue comme absente :get()renvoie$default. clear()vide tout le serveur, quel que soit le préfixe.increment()stocke des chaînes numériques ('6') etdecrement()s'arrête à 0.setMultiple(),deleteMultiple(),increment()etdecrement()renvoient toujourstrue.
MicroCache
Implémente CacheInterface dans un tableau PHP.
- Conserve les données uniquement le temps de l'exécution du script.
- Le TTL n'a aucun effet.
- Une valeur
nullstockée est lue comme absente parget(), maishas()renvoietrue.
RateLimit
Antispam qui stocke les tentatives dans un cache PSR-16.
Utilise le principe du seau de jetons (token bucket) : https://en.wikipedia.org/wiki/Token_bucket
__construct(Psr\SimpleCache\CacheInterface $cache, string $name, int $max, int $period)Crée unRateLimit:$name: clé de cache, utilisée telle quelle (à rendre unique, par exemple'login_' . $ip) ;$max: stock initial ;$period: durée en secondes pour reconstituer tout le stock, et TTL de l'entrée.
hit(int $use = 1): boolConsomme$usejetons. Renvoiefalsesi le stock est insuffisant (rien n'est alors consommé).stock(): intStock enregistré lors du dernierhit(), sans la recharge écoulée depuis.purge()Réinitialise le stock.
$limit = new \Pebble\Cache\RateLimit($cache, 'login_' . $ip, 5, 300); if (!$limit->hit()) { http_response_code(429); exit; }
SessionHandler
Implémente SessionHandlerInterface pour stocker les sessions dans n'importe quel cache PSR-16.
__construct(Psr\SimpleCache\CacheInterface $cache, int $expiration = 3600, string $prefix = 'sess_')$expirationest le TTL de chaque écriture.read()renvoie''pour une session inconnue.open(),close()etgc()ne font rien (gc()renvoie toujours 100).
session_set_save_handler(new \Pebble\Cache\SessionHandler(new \Pebble\Cache\MemCache()), true); session_start();
Helper
Helper::dateInterval2Seconds(DateInterval $interval): intConvertit un intervalle en secondes. Attention : les jours, mois et années d'un intervalle construit à la main (new DateInterval('P1D')) sont ignorés (voirTODO.md).
Tests
composer install vendor/bin/phpunit
Les tests de MemCache nécessitent ext-memcached et un serveur (MEMCACHED_HOST, MEMCACHED_PORT, par défaut 127.0.0.1:11211). Ils sont sautés sinon, et n'appellent jamais clear().
Les bugs connus sont figés par des tests annotés // BUG: qui vérifient le comportement actuel.