Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/static-analysis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:

jobs:
php-cs-fixer:
Comment thread
zakhar-huzenko marked this conversation as resolved.
Resolved
name: PHP-CS-Fixer
name: PHP Code Sniffer
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
/phpunit.xml
.phpunit.result.cache
###< phpunit/phpunit ###
/clover.xml
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@ services:
- '@Macpaw\SchemaContextBundle\Service\BaggageSchemaResolver'
```

Decorate predis client with symfony-bundles/redis-bundle:

```yaml
# config/services.yaml

services:
Macpaw\RedisSchemaBundle\Redis\RedisClientAdapter:
decorates: SymfonyBundles\RedisBundle\Redis\ClientInterface
arguments:
- '@.inner'
- '@Macpaw\SchemaContextBundle\Service\BaggageSchemaResolver'
```

## Usage
Anywhere you use Symfony cache services (injected via CacheInterface or AdapterInterface), your keys will automatically be prefixed based on the current schema.
For example:
Expand Down Expand Up @@ -76,4 +89,3 @@ Feel free to open issues and submit pull requests.

## License
This bundle is released under the MIT license.

6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@
"require-dev": {
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^10.0",
"squizlabs/php_codesniffer": "3.7.*"
"squizlabs/php_codesniffer": "3.7.*",
"symfony-bundles/redis-bundle": "^3.1"
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"suggest": {
"symfony-bundles/redis-bundle": "For predis client key decarations with schema prefix"
},
"scripts": {
"composer-validate": [
"composer validate"
Expand Down
113 changes: 113 additions & 0 deletions src/Redis/RedisClientAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

declare(strict_types=1);

namespace Macpaw\RedisSchemaBundle\Redis;

use Macpaw\SchemaContextBundle\Service\BaggageSchemaResolver;
use Predis\Command\CommandInterface;
use Predis\Command\FactoryInterface;
use Predis\Configuration\OptionsInterface;
use Predis\Connection\ConnectionInterface;
use SymfonyBundles\RedisBundle\Redis\ClientInterface;

class RedisClientAdapter implements ClientInterface
Comment thread
zakhar-huzenko marked this conversation as resolved.
Resolved
{
public function __construct(
private BaggageSchemaResolver $resolver,
private ClientInterface $decorated,
private readonly ?string $defaultSchema = null,
/**
* Method names that should be prefixed with the schema which not present in interfaces
* like a hmget, hset, etc.
*
* @var array<string>
*/
private readonly array $decoratedCallMethods = [],
) {
}

public function pop(string $key): ?string
{
return $this->decorated->pop($this->prefixKey($key));
}

public function push(string $key, ...$values): int
{
return $this->decorated->push($this->prefixKey($key), ...$values);
}

public function count(string $key): int
{
return $this->decorated->count($this->prefixKey($key));
}

public function remove(string $key): int
{
return $this->decorated->remove($this->prefixKey($key));
}

public function getCommandFactory(): FactoryInterface
{
return $this->decorated->getCommandFactory();
}

public function getOptions(): OptionsInterface
{
return $this->decorated->getOptions();
}

public function connect(): void
{
$this->decorated->connect();
}

public function disconnect(): void
{
$this->decorated->disconnect();
}

public function getConnection(): ConnectionInterface
{
return $this->decorated->getConnection();
}

/**
* @param array<array-key, mixed> $arguments
*/
public function createCommand($method, $arguments = []): CommandInterface
{
return $this->decorated->createCommand($method, $arguments);
}

public function executeCommand(CommandInterface $command): mixed
{
return $this->decorated->executeCommand($command);
}

/**
* @param array<array-key, mixed> $arguments
*/
public function __call($method, $arguments): mixed
{
if (in_array($method, $this->decoratedCallMethods, true)) {
// Automatically prefix the first argument if it's a string
if (array_key_exists(0, $arguments) && is_scalar($arguments[0])) {
$arguments[0] = $this->prefixKey((string) $arguments[0]);
}
}

return $this->decorated->$method(...$arguments);
}

private function prefixKey(string $key): string
{
$schema = $this->resolver->getSchema();

if ($this->defaultSchema !== null && $schema === $this->defaultSchema) {
return $key;
}

return $schema ? $schema . '.' . $key : $key;
}
}
19 changes: 12 additions & 7 deletions src/Redis/SchemaAwareRedisAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,10 @@ class SchemaAwareRedisAdapter implements AdapterInterface, CacheInterface, Reset
public function __construct(
private readonly RedisAdapter $decorated,
private readonly BaggageSchemaResolver $resolver,
private readonly ?string $defaultSchema = null,
) {
}

private function prefixKey(string $key): string
{
$schema = $this->resolver->getSchema();

return $schema ? $schema . '.' . $key : $key;
}

public function clear(string $prefix = ''): bool
{
return $this->decorated->clear($prefix);
Expand Down Expand Up @@ -100,4 +94,15 @@ public function reset(): void
{
$this->decorated->clear($this->resolver->getSchema() ?? '');
}

private function prefixKey(string $key): string

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: if SchemaAwarePRedisClient and SchemaAwareRedisAdapter are running at the same time, will they not duplicate the prefix?

{
$schema = $this->resolver->getSchema();

if ($this->defaultSchema !== null && $schema === $this->defaultSchema) {
return $key;
}

return $schema ? $schema . '.' . $key : $key;
}
}
Loading
Loading