-
Notifications
You must be signed in to change notification settings - Fork 1.5k
PHPORM-174 Add doc for cache and locks #2909
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
1940776
1e42c9d
2a958da
e639b47
e934c53
5d884e1
a4ead2c
830ebd4
aa1dba8
7d3637d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,234 @@ | ||||||||||
.. _laravel-queues: | ||||||||||
|
||||||||||
=============== | ||||||||||
Cache and Locks | ||||||||||
=============== | ||||||||||
|
||||||||||
.. facet:: | ||||||||||
:name: genre | ||||||||||
:values: tutorial | ||||||||||
|
||||||||||
.. meta:: | ||||||||||
:keywords: php framework, cache, lock, code example | ||||||||||
|
||||||||||
Configuration | ||||||||||
------------- | ||||||||||
|
||||||||||
In order to use MongoDB as backend for `Laravel Cache and Locks <https://laravel.com/docs/{+laravel-docs-version+}/cache>`__, | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
add a store configuration using the ``mongodb`` driver in ``config/cache.php``: | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
.. code-block:: php | ||||||||||
|
||||||||||
'stores' => [ | ||||||||||
'mongodb' => [ | ||||||||||
'driver' => 'mongodb', | ||||||||||
'connection' => 'mongodb', | ||||||||||
'collection' => 'cache', | ||||||||||
'lock_connection' => 'mongodb', | ||||||||||
'lock_collection' => 'cache_locks', | ||||||||||
'lock_lottery' => [2, 100], | ||||||||||
'lock_timeout' => 86400, | ||||||||||
], | ||||||||||
], | ||||||||||
|
||||||||||
The following table describes a list of cache and lock options | ||||||||||
and their default values: | ||||||||||
|
||||||||||
.. list-table:: | ||||||||||
:header-rows: 1 | ||||||||||
:widths: 25 75 | ||||||||||
|
||||||||||
* - Setting | ||||||||||
- Description | ||||||||||
|
||||||||||
* - ``driver`` | ||||||||||
- **Required**. Specifies the lock driver to use. Must be ``mongodb``. | ||||||||||
|
||||||||||
* - ``connection`` | ||||||||||
- **Required**. The database connection to use to store cache items. It must be a ``mongodb`` connection. | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
* - ``collection`` | ||||||||||
- Default ``cache``. Name of the MongoDB collection to store cache items. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't pick up on this when reviewing the original PRs, so forgive me for asking this late: where does the database name come from? Are you relying on whatever is configured through the corresponding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The database name is set in the database connection configuration. Do you think we should add an option to change the database name for cache and lock? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can also consider allowing a namespace for the Otherwise, I'm fine keeping this as-is and revisiting if/when someone asks for further customization. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tracking this feature: PHPORM-176 |
||||||||||
|
||||||||||
* - ``lock_connection`` | ||||||||||
- Default to the cache ``connection``. The database connection to use to store locks. It must be a ``mongodb`` connection. | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
* - ``lock_collection`` | ||||||||||
- Default ``cache_locks``. Name of the MongoDB collection to store locks. | ||||||||||
|
||||||||||
* - ``lock_lottery`` | ||||||||||
- Default ``[2, 100]``. Probability [chance, total] of pruning expired cache items. Set to [0, 0] to disable | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
* - ``lock_timeout`` | ||||||||||
- Default ``86400``. Time-to-live of the locks in seconds | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
|
||||||||||
Setup auto-expiration indexes | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
----------------------------- | ||||||||||
|
||||||||||
The :manual:`TTL indexes </core/index-ttl/>` integrated into MongoDB automatically | ||||||||||
delete documents when they have expired. Their use is optional with the ``mongodb`` | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
driver, but recommended as they provide better performance by delegating the | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
deletion of expired documents to MongoDB instead of requiring the application to | ||||||||||
perform this task randomly. | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
The best way is to create the indexes with a migration calling the methods | ||||||||||
``createTTLIndex()`` provided by both the cache and the lock stores: | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
.. literalinclude:: /includes/cache/migration.php | ||||||||||
:language: php | ||||||||||
:emphasize-lines: 11,12 | ||||||||||
:dedent: | ||||||||||
|
||||||||||
Then run the migration: | ||||||||||
|
||||||||||
.. code-block:: none | ||||||||||
|
||||||||||
$ php artisan migrate | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
Alternatively, the index can be created using :mdb-shell:`MongoDB Shell <>` (``mongosh``): | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
.. code-block:: ts | ||||||||||
|
||||||||||
db.cache.createIndex( | ||||||||||
/* Field that holds the expiration date */ | ||||||||||
{ expires_at: 1 }, | ||||||||||
/* Delay to remove items after expiration */ | ||||||||||
{ expireAfterSeconds: 0 } | ||||||||||
) | ||||||||||
|
||||||||||
If you use Locks, disable ``lock_lottery`` by setting the probability to ``0``: | ||||||||||
|
||||||||||
.. code-block:: php | ||||||||||
:highlightLines: [4] | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
'stores' => [ | ||||||||||
'mongodb' => [ | ||||||||||
'driver' => 'mongodb', | ||||||||||
'connection' => 'mongodb', | ||||||||||
'lock_lottery' => [0, 100], // Disabled | ||||||||||
], | ||||||||||
], | ||||||||||
|
||||||||||
Using MongoDB cache | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
------------------- | ||||||||||
|
||||||||||
The Laravel cache can be used to store any serializable data using the facade | ||||||||||
``Illuminate\Support\Facades\Cache``: | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
In this example: | ||||||||||
- Gets the cache repository with the store ``mongodb``, | ||||||||||
- Tries to read and return the cache item named ``foo``, | ||||||||||
- If missing, calls the closure to compute the value, store this value forever and return it. | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
..code-block:: php | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
use Illuminate\Support\Facades\Cache; | ||||||||||
|
||||||||||
$value = Cache::store('mongodb')->get('foo', function () { | ||||||||||
return [1, 2, 3]; | ||||||||||
}); | ||||||||||
|
||||||||||
The default, cached objects do not expire. It is possible to define an expiry time. | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
..code-block:: php | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
Cache::store('mongodb')->set('foo', 'abc', '1 day'); | ||||||||||
|
||||||||||
Incrementing and decrementing a value is also supported, the value must | ||||||||||
be initialized before. The following example initialize the counter to ``3``, | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
adds 5 and removes 2. | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
..code-block:: php | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
Cache::store('mongodb')->set('counter', 3); | ||||||||||
Cache::store('mongodb')->increment('counter', 5); | ||||||||||
Cache::store('mongodb')->decrement('counter', 2); | ||||||||||
|
||||||||||
.. note:: | ||||||||||
|
||||||||||
{+odm-short+} supports incrementing and decrementing with integer and float values. | ||||||||||
|
||||||||||
Configuring MongoDB as default cache | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
------------------------------------ | ||||||||||
|
||||||||||
To use the ``mongodb`` store by default, change the default store in | ||||||||||
``config/cache.php``: | ||||||||||
|
||||||||||
.. code-block:: php | ||||||||||
:emphasize-lines: 2 | ||||||||||
|
||||||||||
return [ | ||||||||||
'default' => env('CACHE_STORE', 'mongodb'), | ||||||||||
|
||||||||||
'stores' => [ | ||||||||||
'mongodb' => [ | ||||||||||
'driver' => 'mongodb', | ||||||||||
'connection' => 'mongodb', | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should Also, is there any significance to the line break between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here, I rely on the default values. Do you think I should make a note of that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Calling out your reliance on default values makes sense to me. I was mostly concerned with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "connection" is required, "collection" has a default value which is The default is applied in the service provider.
|
||||||||||
], | ||||||||||
], | ||||||||||
]; | ||||||||||
|
||||||||||
The variable ``CACHE_STORE`` could be set in your environment or in | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
the ``.env`` file. Update or remove it: | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
.. code-block:: none | ||||||||||
|
||||||||||
CACHE_STORE=mongodb | ||||||||||
|
||||||||||
Then you can use the ``Illuminate\Support\Facades\Cache`` facade and | ||||||||||
automatic injection: | ||||||||||
|
||||||||||
.. code-block:: php | ||||||||||
|
||||||||||
use Illuminate\Support\Facades\Cache; | ||||||||||
|
||||||||||
Cache::get('foo', 5); | ||||||||||
|
||||||||||
This example shows how to use automatic injection of the cache | ||||||||||
manager, using the default store. It is a controller that | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
increments a counter each time it is invoked. | ||||||||||
|
||||||||||
|
||||||||||
.. code-block:: php | ||||||||||
:emphasize-lines: 9,14 | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you may have meant to highlight 9 and 13? The function names?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think 14 is correct, it's the line with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right. Both lines need to be udpated.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think these should be lines 10 and 15 to highlight the |
||||||||||
|
||||||||||
<?php | ||||||||||
|
||||||||||
namespace App\Http\Controllers; | ||||||||||
|
||||||||||
use App\Contracts\CacheManager; | ||||||||||
|
||||||||||
class CountController extends Controller | ||||||||||
{ | ||||||||||
public function __construct( | ||||||||||
private CacheManager $cache, | ||||||||||
) {} | ||||||||||
|
||||||||||
public function hit(): int | ||||||||||
{ | ||||||||||
return $this->cache->increment('counter'); | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
|
||||||||||
Using MongoDB Lock | ||||||||||
------------------ | ||||||||||
|
||||||||||
Atomic locks allow for the manipulation of distributed locks without worrying | ||||||||||
about race conditions. | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
..code-block:: php | ||||||||||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
:emphasize-lines: 3 | ||||||||||
|
||||||||||
use Illuminate\Support\Facades\Cache; | ||||||||||
|
||||||||||
$lock = Cache::store('mongodb')->lock('foo', 10); | ||||||||||
|
||||||||||
if ($lock->get()) { | ||||||||||
// Lock acquired for 10 seconds... | ||||||||||
|
||||||||||
$lock->release(); | ||||||||||
} | ||||||||||
|
||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
|
||
use Illuminate\Database\Migrations\Migration; | ||
use Illuminate\Support\Facades\Cache; | ||
|
||
return new class extends Migration | ||
{ | ||
public function up(): void | ||
{ | ||
$store = Cache::store('mongodb'); | ||
$store->createTTLIndex(); | ||
$store->lock('')->createTTLIndex(); | ||
} | ||
}; |
Uh oh!
There was an error while loading. Please reload this page.