From 55419acb09ba4bae85b0a29f96e068f97da6e11d Mon Sep 17 00:00:00 2001 From: Lukas Rosenstock Date: Sun, 18 Oct 2026 17:10:23 +0000 Subject: [PATCH] Documented permanent store, updated fallback store docs --- docs/caching.md | 72 ++++++++++++++++++++++++++++++++++++++++++++++++- docs/options.md | 2 ++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/docs/caching.md b/docs/caching.md index 2ffc4c1..9c8b3f9 100644 --- a/docs/caching.md +++ b/docs/caching.md @@ -61,7 +61,7 @@ $retriever = new ObjectRetriever([ Fallback store is a mechanism that can be used by applications that require high availability but may lose connectivity to CloudObjects Core. With fallback store, a copy of an object is saved in a directory. If the API fails with a 5xx error, times out, or the request fails without a response, an `ObjectRetriever` will return the stored copy instead. Be advised that fallback storage will, once configured, result in your application not noticing when the Object API is unreachable - at least for objects in the store - and will continue to deliver the saved copy even if the original in CloudObjects Core is changed or removed. -It is possible for the fallback store to be configured for all objects or only for objects in specified namespaces. Since the fallback store is never purged except by the SDK itself, it can grow large; hence it should be limited to specific namespaces in applications where many random objects may be retrieved. +It is possible for the fallback store to be configured for all objects or only for objects in specified namespaces. Since the SDK updates stored copies whenever it retrieves an object successfully but never deletes them, not even when the object has been removed from CloudObjects Core, the fallback store can grow large; hence it should be limited to specific namespaces in applications where many random objects may be retrieved. **Use this feature with caution and disable it if it causes any problems.** To enable fallback store, set the `fallback_store_directory` option to a writeable path on the filesystem. Also, set `fallback_store_scope` to either the string `*` to save all retrieved objects, or a list of namespaces (domains only without `coid://` prefix); the list of namespaces can be provided as a comma-separated string or an array of strings. @@ -111,3 +111,73 @@ $retriever = new ObjectRetriever([ 'fallback_store_scope' => 'example.com', ]); ``` + +### Permanent Store + +Permanent store is a mechanism that can be used by applications that want to minimize connections to CloudObjects Core, may go offline after initialization, or want to work with the same version of an object for the lifetime of their run without getting updates. With permanent store, an `ObjectRetriever` saves a copy of an object in a directory the first time it retrieves it from the Object API. Once an object is in the permanent store, the API will _never_ be contacted for this object again. Be advised that permanent storage will, once configured, result in your application continuing to deliver the saved copy even if the original in CloudObjects Core is changed or removed, and not noticing when the Object API is unreachable - at least for objects in the store. + +It is possible for the permanent store to be configured for all objects or only for objects in specified namespaces. Since the permanent store is never purged or refreshed by the SDK, it can grow large; hence it should be limited to specific namespaces in applications where many random objects may be retrieved. To get the latest version of an object, delete its copy from the directory, or clear the directory entirely. **Use this feature with caution and disable it if it causes any problems.** + +To enable permanent store, set the `permanent_store_directory` option to a writeable path on the filesystem. Also, set `permanent_store_scope` to either the string `*` to save all retrieved objects, or a list of namespaces (domains only without `coid://` prefix); the list of namespaces can be provided as a comma-separated string or an array of strings. + +Storing all retrieved objects: + +```php +use CloudObjects\SDK\ObjectRetriever; + +$retriever = new ObjectRetriever([ + 'permanent_store_directory' => '/var/lib/myapp/cloudobjects-permanent', + 'permanent_store_scope' => '*', +]); +``` + +Storing only objects from specific namespaces, provided as an array: + +```php +use CloudObjects\SDK\ObjectRetriever; + +$retriever = new ObjectRetriever([ + 'permanent_store_directory' => '/var/lib/myapp/cloudobjects-permanent', + 'permanent_store_scope' => [ 'example.com', 'cloudobjects.io' ], +]); +``` + +Or as a comma-separated string, which is convenient when the value comes from an environment variable: + +```php +use CloudObjects\SDK\ObjectRetriever; + +$retriever = new ObjectRetriever([ + 'permanent_store_directory' => getenv('PERMANENT_STORE_DIRECTORY'), + 'permanent_store_scope' => 'example.com,cloudobjects.io', +]); +``` + +The permanent store can be combined with an external cache. The cache is still consulted first, as it may be faster than the filesystem; the permanent store only comes into play when an object is not cached, and the API is only contacted when the object is in neither. + +```php +use CloudObjects\SDK\ObjectRetriever; +use Symfony\Component\Cache\Adapter\FilesystemAdapter; + +$retriever = new ObjectRetriever([ + 'cache_storage' => new FilesystemAdapter('cloudobjects', 0, '/var/cache/myapp'), + 'cache_ttl' => 300, + 'permanent_store_directory' => '/var/lib/myapp/cloudobjects-permanent', + 'permanent_store_scope' => 'example.com', +]); +``` + +Permanent store and fallback store can be combined, for example to pin objects from your own namespace while keeping a fallback copy of everything else. Both stores must use separate directories, otherwise the `ObjectRetriever` throws an `InvalidSDKConfigurationException`. If an object is in scope of both, the permanent store takes precedence. + +```php +use CloudObjects\SDK\ObjectRetriever; + +$retriever = new ObjectRetriever([ + 'permanent_store_directory' => '/var/lib/myapp/cloudobjects-permanent', + 'permanent_store_scope' => 'example.com', + 'fallback_store_directory' => '/var/lib/myapp/cloudobjects-fallback', + 'fallback_store_scope' => '*', +]); +``` + +Unlike `static_config_path`, which reads object descriptions that you provide yourself, the permanent store is filled automatically by the SDK from the Object API. diff --git a/docs/options.md b/docs/options.md index b8e8862..4f68865 100644 --- a/docs/options.md +++ b/docs/options.md @@ -16,3 +16,5 @@ The `ObjectRetriever` constructor accepts an associative array of options. All o | `connect_timeout` | Timeout for establishing a connection to the API, in seconds. | `5` | | `fallback_store_directory` | Writeable directory in which copies of retrieved objects are saved and returned when the API fails with a 5xx error, times out, or the request fails without a response. Requires `fallback_store_scope`. See [caching](caching.md#fallback-store). | `null` | | `fallback_store_scope` | Which objects are saved in the fallback store: `'*'` for all objects, or a list of namespaces (domains without `coid://` prefix) as a comma-separated string or an array of strings. | `null` | +| `permanent_store_directory` | Writeable directory in which copies of retrieved objects are saved; once an object is stored there, it is always returned from the store and the API is never contacted for it again. Requires `permanent_store_scope` and must differ from `fallback_store_directory`. See [caching](caching.md#permanent-store). | `null` | +| `permanent_store_scope` | Which objects are saved in the permanent store: `'*'` for all objects, or a list of namespaces (domains without `coid://` prefix) as a comma-separated string or an array of strings. | `null` |