Skip to content
This repository has been archived by the owner on Mar 30, 2022. It is now read-only.

Commit

Permalink
Merge pull request #8 from DarkGhostHunter/master
Browse files Browse the repository at this point in the history
Adds the `remember` helper
  • Loading branch information
DarkGhostHunter committed Aug 24, 2021
2 parents 579e812 + c662763 commit 3fd1629
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 11 deletions.
50 changes: 39 additions & 11 deletions README.md
Expand Up @@ -31,17 +31,17 @@ This package includes helpful global helpers for your project make almost anythi

| | | |
|---|---|---|
| [app_call](#app_call) | [in_console](#in_console) | [sleep_between](#sleep_between)
| [call_existing](#call_existing) | [in_development](#in_development) | [taptap](#taptap)
| [created](#created) | [logged_in](#logged_in) | [undot_path](#undot_path)
| [data_update](#data_update) | [methods_of](#methods_of) | [until](#until)
| [delist](#delist) | [missing_trait](#missing_trait) | [user](#user)
| [diff](#diff) | [none_of](#none_of) | [weekend](#weekend)
| [dot_path](#dot_path) | [ok](#ok) | [weekstart](#weekstart)
| [enclose](#enclose) | [period](#period) | [which_of](#which_of)
| [files](#files) | [period_from](#period_from) | [yesterday](#yesterday)
| [has_trait](#has_trait) | [pipe](#pipe) |
| [hashy](#hashy) | [route_is](#route_is) |
| [app_call](#app_call) | [in_console](#in_console) | [route_is](#route_is)
| [call_existing](#call_existing) | [in_development](#in_development) | [sleep_between](#sleep_between)
| [created](#created) | [logged_in](#logged_in) | [taptap](#taptap)
| [data_update](#data_update) | [methods_of](#methods_of) | [undot_path](#undot_path)
| [delist](#delist) | [missing_trait](#missing_trait) | [until](#until)
| [diff](#diff) | [none_of](#none_of) | [user](#user)
| [dot_path](#dot_path) | [ok](#ok) | [weekend](#weekend)
| [enclose](#enclose) | [period](#period) | [weekstart](#weekstart)
| [files](#files) | [period_from](#period_from) | [which_of](#which_of)
| [has_trait](#has_trait) | [pipe](#pipe) | [yesterday](#yesterday)
| [hashy](#hashy) | [remember](#remember) |

### `app_call()`

Expand Down Expand Up @@ -401,6 +401,34 @@ pipe(10, [
// 15
```

### `remember()`

Retrieves an item from the cache, or stores a default value if the item doesn't exist.

```php
remember('foo', 60, function() {
return 'bar';
})
```

If no `ttl` is set, and rather a callback is issued as second parameter, it will be stored forever.

```php
remember('foo', function () {
return 'bar';
})
```

It supports atomic locks, which are created using the same name key. It will lock the key by a given seconds, while also waiting for the same amount of time.

```php
remember('foo', 60, function() {
return 'bar';
}, 20);
```

This can be useful to avoid cache data-races, where multiple processes run the same callback because the cache key is not filled yet.

### `route_is()`

Determine whether the current route's name matches the given patterns.
Expand Down
32 changes: 32 additions & 0 deletions helpers/common.php
Expand Up @@ -135,6 +135,38 @@ function pipe(mixed $passable, array $pipes, callable $destination = null): mixe
}
}

if (!function_exists('remember')) {
/**
* Retrieves an item from the cache, or stores a default value if the item doesn't exist.
*
* @param string $key
* @param \Closure|\DateTimeInterface|\DateInterval|int $ttl
* @param \Closure|\DateTimeInterface|\DateInterval|int|null $callback
* @param int|null $lock If issued, it will lock the key and wait the same amount of seconds.
*
* @return mixed
*/
function remember(
string $key,
Closure|DateTimeInterface|DateInterval|int $ttl,
Closure|DateTimeInterface|DateInterval|int $callback = null,
int $lock = null
): mixed
{
$cache = app('cache');

if (is_callable($ttl)) {
[$ttl, $callback, $lock] = [null, $ttl, $callback];
}

if ($lock) {
return $cache->lock($key, $lock)->block($ttl, static fn() => $cache->remember($key, $ttl, $callback));
}

return $cache->remember($key, $ttl, $callback);
}
}

if (!function_exists('sleep_between')) {
/**
* Runs a callback while sleeping between multiple executions.
Expand Down
48 changes: 48 additions & 0 deletions tests/CommonTest.php
Expand Up @@ -3,6 +3,7 @@
namespace Tests;

use Closure;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\HigherOrderTapProxy;
use Illuminate\Support\Str;
use Orchestra\Testbench\TestCase;
Expand Down Expand Up @@ -33,6 +34,53 @@ public function test_data_update(): void
static::assertNull($array['foo']['quz']['qux']);
}

public function test_remember(): void
{
$result = remember('foo', static function():string {
return 'bar';
});

static::assertSame('bar', $result);

Cache::forget('foo');

$result = remember('foo', 10, static function(): string {
return 'bar';
});

static::assertSame('bar', $result);

Cache::put('foo', 'baz');

$result = remember('foo', 10, static function(): string {
return 'bar';
});

static::assertSame('baz', $result);

Cache::forget('foo');
Cache::lock('foo', 2);

$result = remember('foo', 10, static function (): string {
return 'bar';
}, 10);

static::assertSame('bar', $result);

static::assertFalse(Cache::lock('foo', 2)->release());

Cache::forget('foo');
Cache::lock('foo', 2);

$result = remember('foo', static function (): string {
return 'bar';
}, 10);

static::assertSame('bar', $result);

static::assertFalse(Cache::lock('foo', 2)->release());
}

public function test_delist(): void
{
$list = ['foo' => 'bar', 'quz' => 'qux', 'quuz' => 'quux'];
Expand Down

0 comments on commit 3fd1629

Please sign in to comment.