-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from DirectoryTree/array-repository
Add ability to set array repository for testing
- Loading branch information
Showing
5 changed files
with
388 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
<?php | ||
|
||
namespace DirectoryTree\ActiveRedis\Repositories; | ||
|
||
use Closure; | ||
use Generator; | ||
use Illuminate\Support\Str; | ||
|
||
class ArrayRepository implements Repository | ||
{ | ||
/** | ||
* Constructor. | ||
*/ | ||
public function __construct( | ||
protected array $data = [], | ||
protected array $expiry = [], | ||
) {} | ||
|
||
/** | ||
* Determine if the given hash exists. | ||
*/ | ||
public function exists(string $hash): bool | ||
{ | ||
return isset($this->data[$hash]); | ||
} | ||
|
||
/** | ||
* Chunk through the hashes matching the given pattern. | ||
*/ | ||
public function chunk(string $pattern, int $count): Generator | ||
{ | ||
$matches = []; | ||
|
||
foreach (array_keys($this->data) as $key) { | ||
if (Str::is($pattern, $key)) { | ||
$matches[] = $key; | ||
} | ||
} | ||
|
||
foreach (array_chunk($matches, $count) as $chunk) { | ||
yield $chunk; | ||
} | ||
} | ||
|
||
/** | ||
* Set the hash field's value. | ||
*/ | ||
public function setAttribute(string $hash, string $attribute, string $value): void | ||
{ | ||
$this->data[$hash][$attribute] = $value; | ||
} | ||
|
||
/** | ||
* Set the hash field's value. | ||
*/ | ||
public function setAttributes(string $hash, array $attributes): void | ||
{ | ||
foreach ($attributes as $attribute => $value) { | ||
$this->setAttribute($hash, $attribute, $value); | ||
} | ||
} | ||
|
||
/** | ||
* Get the hash field's value. | ||
*/ | ||
public function getAttribute(string $hash, string $field): mixed | ||
{ | ||
if ($this->isExpired($hash)) { | ||
$this->delete($hash); | ||
|
||
return null; | ||
} | ||
|
||
return $this->data[$hash][$field] ?? null; | ||
} | ||
|
||
/** | ||
* Get all the attributes in the hash. | ||
*/ | ||
public function getAttributes(string $hash): array | ||
{ | ||
if ($this->isExpired($hash)) { | ||
$this->delete($hash); | ||
|
||
return []; | ||
} | ||
|
||
return $this->data[$hash] ?? []; | ||
} | ||
|
||
/** | ||
* Set a time-to-live on a hash key. | ||
* | ||
* Not supported in ArrayRepository. | ||
*/ | ||
public function setExpiry(string $hash, int $seconds): void | ||
{ | ||
$this->expiry[$hash] = time() + $seconds; | ||
} | ||
|
||
/** | ||
* Get the time-to-live of a hash key. | ||
*/ | ||
public function getExpiry(string $hash): ?int | ||
{ | ||
if (! isset($this->expiry[$hash])) { | ||
return null; | ||
} | ||
|
||
$remaining = $this->expiry[$hash] - time(); | ||
|
||
return $remaining > 0 ? $remaining : null; | ||
} | ||
|
||
/** | ||
* Delete the attributes from the hash. | ||
*/ | ||
public function deleteAttributes(string $hash, array|string $attributes): void | ||
{ | ||
foreach ((array) $attributes as $attribute) { | ||
unset($this->data[$hash][$attribute]); | ||
} | ||
} | ||
|
||
/** | ||
* Delete the given hash. | ||
*/ | ||
public function delete(string $hash): void | ||
{ | ||
unset($this->data[$hash]); | ||
} | ||
|
||
/** | ||
* Perform a transaction. | ||
*/ | ||
public function transaction(Closure $operation): void | ||
{ | ||
$operation($this); | ||
} | ||
|
||
/** | ||
* Determine if the given hash has expired. | ||
*/ | ||
protected function isExpired(string $hash): bool | ||
{ | ||
return isset($this->expiry[$hash]) && $this->expiry[$hash] <= time(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
<?php | ||
|
||
use DirectoryTree\ActiveRedis\Repositories\ArrayRepository; | ||
|
||
it('can check if a hash exists', function () { | ||
$repository = new ArrayRepository(['foo' => ['bar' => 'baz']]); | ||
|
||
expect($repository->exists('foo'))->toBeTrue(); | ||
expect($repository->exists('bar'))->toBeFalse(); | ||
}); | ||
|
||
it('can chunk through hashes matching a pattern', function () { | ||
$repository = new ArrayRepository([ | ||
'user:1' => [], | ||
'user:2' => [], | ||
'post:1' => [], | ||
'user:3' => [], | ||
]); | ||
|
||
$chunks = iterator_to_array($repository->chunk('user:*', 2)); | ||
|
||
expect($chunks)->toHaveCount(2); | ||
expect($chunks[0])->toEqual(['user:1', 'user:2']); | ||
expect($chunks[1])->toEqual(['user:3']); | ||
}); | ||
|
||
it('can set and get a single attribute', function () { | ||
$repository = new ArrayRepository; | ||
|
||
$repository->setAttribute('foo', 'bar', 'baz'); | ||
|
||
expect($repository->getAttribute('foo', 'bar'))->toBe('baz'); | ||
}); | ||
|
||
it('can set and get multiple attributes', function () { | ||
$repository = new ArrayRepository; | ||
|
||
$repository->setAttributes('foo', ['bar' => 'baz', 'qux' => 'quux']); | ||
|
||
expect($repository->getAttributes('foo'))->toEqual(['bar' => 'baz', 'qux' => 'quux']); | ||
}); | ||
|
||
it('can delete attributes', function () { | ||
$repository = new ArrayRepository(['foo' => ['bar' => 'baz', 'qux' => 'quux']]); | ||
|
||
$repository->deleteAttributes('foo', 'bar'); | ||
|
||
expect($repository->getAttributes('foo'))->toEqual(['qux' => 'quux']); | ||
|
||
$repository->deleteAttributes('foo', ['qux']); | ||
|
||
expect($repository->getAttributes('foo'))->toEqual([]); | ||
}); | ||
|
||
it('can delete a hash', function () { | ||
$repository = new ArrayRepository(['foo' => ['bar' => 'baz']]); | ||
|
||
$repository->delete('foo'); | ||
|
||
expect($repository->exists('foo'))->toBeFalse(); | ||
}); | ||
|
||
it('can set and get expiry', function () { | ||
$repository = new ArrayRepository; | ||
|
||
$repository->setExpiry('foo', 10); | ||
|
||
expect($repository->getExpiry('foo'))->toBeGreaterThanOrEqual(9); | ||
}); | ||
|
||
it('returns null for expiry of non-existent key', function () { | ||
$repository = new ArrayRepository; | ||
|
||
expect($repository->getExpiry('foo'))->toBeNull(); | ||
}); | ||
|
||
it('deletes expired hashes', function () { | ||
$repository = new ArrayRepository; | ||
|
||
$repository->setAttributes('foo', ['bar' => 'baz']); | ||
|
||
$repository->setExpiry('foo', 1); | ||
|
||
sleep(2); | ||
|
||
expect($repository->getAttributes('foo'))->toEqual([]); | ||
}); | ||
|
||
it('handles getting attributes from expired hash', function () { | ||
$repository = new ArrayRepository; | ||
|
||
$repository->setAttributes('foo', ['bar' => 'baz']); | ||
|
||
$repository->setExpiry('foo', 1); | ||
|
||
sleep(2); | ||
|
||
expect($repository->getAttribute('foo', 'bar'))->toBeNull(); | ||
}); |
Oops, something went wrong.