diff --git a/composer.json b/composer.json index 9605e86..0632874 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ "php": ">=8.0", "illuminate/support": "^8.0 || ^9.0 || ^10.0 || ^11.0", "irazasyed/telegram-bot-sdk": "^3.1", - "predis/predis": "^1.0 || ^2.0" + "predis/predis": "^1.0 || ^2.0", + "psr/simple-cache": "^3.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.54", @@ -32,10 +33,10 @@ } }, "config": { - "sort-packages": true, "allow-plugins": { "ergebnis/composer-normalize": false - } + }, + "sort-packages": true }, "extra": { "laravel": { diff --git a/src/DialogManager.php b/src/DialogManager.php index 9452e1d..a2c9532 100644 --- a/src/DialogManager.php +++ b/src/DialogManager.php @@ -5,6 +5,7 @@ namespace KootLabs\TelegramBotDialogs; use KootLabs\TelegramBotDialogs\Storages\Store; +use Psr\SimpleCache\CacheInterface; use Telegram\Bot\Api; use Telegram\Bot\Objects\Update; @@ -14,9 +15,9 @@ final class DialogManager private Api $bot; /** Storage to store Dialog state between requests. */ - private Store $store; + private Store | CacheInterface $store; - public function __construct(Api $bot, Store $store) + public function __construct(Api $bot, Store | CacheInterface $store) { $this->bot = $bot; $this->store = $store; diff --git a/src/Storages/Drivers/RedisStore.php b/src/Storages/Drivers/RedisStore.php index a3e0447..60945be 100644 --- a/src/Storages/Drivers/RedisStore.php +++ b/src/Storages/Drivers/RedisStore.php @@ -27,14 +27,7 @@ public function __construct(string $host = '127.0.0.1', int $port = 6379, string } /** @inheritDoc */ - public function set(string | int $key, mixed $value, int $ttl): void - { - $ttl = $ttl === 0 ? -1 : $ttl; - $this->redis->setEx($this->decorateKey($key), $ttl, $this->serialize($value)); - } - - /** @inheritDoc */ - public function get(string | int $key): mixed + public function get(string $key, mixed $default = null): mixed { $value = $this->redis->get($this->decorateKey($key)); @@ -42,17 +35,24 @@ public function get(string | int $key): mixed } /** @inheritDoc */ - public function has(int | string $key): bool + public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null): bool { - return (bool) $this->redis->exists($this->decorateKey($key)); + $ttl = $ttl === 0 ? -1 : $ttl; + $this->redis->setEx($this->decorateKey($key), $ttl, $this->serialize($value)); } /** @inheritDoc */ - public function delete(string | int $key): void + public function delete(string $key): bool { $this->redis->del($this->decorateKey($key)); } + /** @inheritDoc */ + public function has(string $key): bool + { + return (bool) $this->redis->exists($this->decorateKey($key)); + } + /** * @throws \RuntimeException * @throws \RedisException diff --git a/src/Storages/Store.php b/src/Storages/Store.php index 8e1643a..ed740b1 100644 --- a/src/Storages/Store.php +++ b/src/Storages/Store.php @@ -4,19 +4,62 @@ namespace KootLabs\TelegramBotDialogs\Storages; +/** Keep exiting methods compatible with {@see \Psr\SimpleCache\CacheInterface} to be able to use CacheInterface instead. */ interface Store { public const STORE_PREFIX = 'tg:dialog:'; - /** Save an item in the storage with a specific key and data. */ - public function set(string | int $key, mixed $value, int $ttl): void; + /** + * Fetches a value from the cache. + * + * @param string $key The unique key of this item in the cache. + * @param mixed $default Default value to return if the key does not exist. + * + * @return mixed The value of the item from the cache, or $default in case of cache miss. + * + * @throws \Psr\SimpleCache\InvalidArgumentException MUST be thrown if the $key string is not a legal value. + */ + public function get(string $key, mixed $default = null): mixed; - /** Retrieve an item from the storage by key. */ - public function get(string | int $key): mixed; + /** + * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time. + * + * @param string $key The key of the item to store. + * @param mixed $value The value of the item to store, must be serializable. + * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and + * the driver supports TTL then the library may set a default value + * for it or let the driver take care of that. + * + * @return bool True on success and false on failure. + * + * @throws \Psr\SimpleCache\InvalidArgumentException MUST be thrown if the $key string is not a legal value. + */ + public function set(string $key, mixed $value, null | int | \DateInterval $ttl = null): bool; - /** Whether a key exist in a Storage. */ - public function has(string | int $key): bool; + /** + * Delete an item from the cache by its unique key. + * + * @param string $key The unique cache key of the item to delete. + * + * @return bool True if the item was successfully removed. False if there was an error. + * + * @throws \Psr\SimpleCache\InvalidArgumentException MUST be thrown if the $key string is not a legal value. + */ + public function delete(string $key): bool; - /** Delete a stored item by its key. */ - public function delete(string | int $key): void; + /** + * Determines whether an item is present in the cache. + * + * NOTE: It is recommended that has() is only to be used for cache warming type purposes + * and not to be used within your live applications operations for get/set, as this method + * is subject to a race condition where your has() will return true and immediately after, + * another script can remove it making the state of your app out of date. + * + * @param string $key The cache item key. + * + * @return bool + * + * @throws \Psr\SimpleCache\InvalidArgumentException MUST be thrown if the $key string is not a legal value. + */ + public function has(string $key): bool; }