-
Notifications
You must be signed in to change notification settings - Fork 9
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
s3 : use cache for listing object #365
Comments
Hi @tristanbes! Yes, adding caching layer is possible and should be fairly simple. CKFinder PHP connector uses Flysystem abstraction layer under the hood, so there are ready to use adapters that decorate regular adapter with caching layer: https://flysystem.thephpleague.com/docs/advanced/caching/#persistent-caching. The recommended way to do that in CKFinder connector is by registering a custom backend adapter inside plugin, as follows: <?php
// ckfinder/plugins/CustomCachingPlugin/CustomCachingPlugin.php
namespace CKSource\CKFinder\Plugin\CustomCachingPlugin;
use CKSource\CKFinder\CKFinder;
use CKSource\CKFinder\Plugin\PluginInterface;
use Aws\S3\S3Client;
use CKSource\CKFinder\Backend\Adapter\AwsS3 as AwsS3Adapter;
use League\Flysystem\Cached\Storage\Predis as PredisStore;
class CustomCachingPlugin implements PluginInterface
{
public function setContainer(CKFinder $app)
{
$backendFactory = $app->getBackendFactory();
$backendFactory->registerAdapter('cached_s3', function ($backendConfig) use ($backendFactory) {
// Regular S3 adapter instantiation.
$clientConfig = [
'credentials' => [
'key' => $backendConfig['key'],
'secret' => $backendConfig['secret']
],
'signature_version' => isset($backendConfig['signature']) ? $backendConfig['signature'] : 'v4',
'version' => isset($backendConfig['version']) ? $backendConfig['version'] : 'latest'
];
if (isset($backendConfig['region'])) {
$clientConfig['region'] = $backendConfig['region'];
}
$client = new S3Client($clientConfig);
$filesystemConfig = [
'visibility' => isset($backendConfig['visibility']) ? $backendConfig['visibility'] : 'private'
];
$prefix = isset($backendConfig['root']) ? trim($backendConfig['root'], '/ ') : null;
$s3Adapter = new AwsS3Adapter($client, $backendConfig['bucket'], $prefix);
// Define cache storage to use for S3 adapter
$predisClient = new Predis\Client(); // Alter this line to configure proper Redis connection
$predisCacheStore = new PredisStore($predisClient);
return $backendFactory->createBackend($backendConfig, $s3Adapter, $filesystemConfig, $predisCacheStore);
});
}
public function getDefaultConfig()
{
return [];
}
} Don't forget to enable the plugin in CKFinder's $config['plugins'] = ['CustomCachingPlugin']; The plugin presented above registers a new adapter type named $config['backends'][] = array(
'name' => 'S3',
'adapter' => 'cached_s3',
// ... Please also have a look at following articles in PHP docs:
Feel free to ask if anything is still unclear. |
Ok thanks, I'll put someone on my team on this subject, we'll comeback to you if any questions. Thank you for this detailled answer. |
Hello, The cache works. Thank you! However what is the procedure for updating the cache without recalling listing s3 (or listContents of Flysystem)? |
Hi @thiphamyp. By default s3 will be checked in case of cache miss. Cache miss occurs if object is not in cache yet, or if cache under given key has expired - you can pass cache lifetime in 3rd parameter of I'm not sure if the above answers your question, so here's another approach: |
Hi @zaak , In fact, version 3.4.2 (PHP) File browser is up to date after deleting, renaming, ... but not after uploading I found these codes below in CKSource\CKFinder\Filesystem\File\DeleteFile, CopiedFile, RenamedFile, MovedFile but not in UploadedFile. ex: Would it be possible to add this to UploadedFile? Thanks |
Hi @thiphamyp. I'm sorry, but I'm not sure if I understand your question. The code you pasted operates on internal CKFinder connector metadata cache (internal image thumbnails etc), it has not much to do with filesystem cache we were discussing earlier. Could you please explain the issue in more detail? |
Hi @zaak , The problem is with the cache, the image is not display on list after uploading (FileUpload). The list of image is updated with DeleteFiles, RenameFile, ... using filesystem cache It seems to me that updateObject of CacheInterface is not be called by putStream of FileUpload that is not existent in CachedAdapter. There are only writeStream and updateStream Regards, |
Hi @thiphamyp. Thanks for the details, I can reproduce this issue now. This happens because the previous response from S3 gets cached and CKFinder does not receive info about newly uploaded files when calls <?php
// ckfinder/plugins/CustomCachingPlugin/CustomCachingPlugin.php
namespace CKSource\CKFinder\Plugin\CustomCachingPlugin;
use CKSource\CKFinder\CKFinder;
use CKSource\CKFinder\Event\BeforeCommandEvent;
use CKSource\CKFinder\Event\CKFinderEvent;
use CKSource\CKFinder\Plugin\PluginInterface;
use Aws\S3\S3Client;
use CKSource\CKFinder\Backend\Adapter\AwsS3 as AwsS3Adapter;
use League\Flysystem\Cached\Storage\Predis as PredisStore;
class CustomCachingPlugin implements PluginInterface
{
/**
* @var PredisStore
*/
private $predisCacheStore = null;
public function __construct()
{
// Define cache storage to use for S3 adapter
$predisClient = new \Predis\Client('tcp://127.0.0.1');
$this->predisCacheStore = new PredisStore($predisClient);
}
public function setContainer(CKFinder $app)
{
$backendFactory = $app->getBackendFactory();
$backendFactory->registerAdapter('cached_s3', function ($backendConfig) use ($backendFactory) {
// Regular S3 adapter instantiation.
$clientConfig = [
'credentials' => array(
'key' => $backendConfig['key'],
'secret' => $backendConfig['secret']
),
'signature_version' => isset($backendConfig['signature']) ? $backendConfig['signature'] : 'v4',
'version' => isset($backendConfig['version']) ? $backendConfig['version'] : 'latest'
];
if (isset($backendConfig['region'])) {
$clientConfig['region'] = $backendConfig['region'];
}
$client = new S3Client($clientConfig);
$filesystemConfig = [
'visibility' => isset($backendConfig['visibility']) ? $backendConfig['visibility'] : 'private'
];
$prefix = isset($backendConfig['root']) ? trim($backendConfig['root'], '/ ') : null;
$s3Adapter = new AwsS3Adapter($client, $backendConfig['bucket'], $prefix);
return $backendFactory->createBackend($backendConfig, $s3Adapter, $filesystemConfig, $this->predisCacheStore);
});
$app->on(CKFinderEvent::BEFORE_COMMAND_FILE_UPLOAD, function (BeforeCommandEvent $event) {
$this->predisCacheStore->flush();
});
}
public function getDefaultConfig()
{
return [];
}
} This is a modified version of the plugin which registers a listener for I hope this helps! After some more detailed testing I see that |
Hello,
We run a very large multi-tenant ecommerce site where we have all our client images under Amazon S3.
Each time they use the CKFinder (PHP), it run multiple getObject/listObject commands (which are not free).
Just for this month we have
Wouldn't it be possible to plug some caching system (Memcache, Redis...) to avoid spam Amazon s3 service with those request and try to serve the file from the cache (with some cache invalidation system and a button to force reload the list from the provider) ?
Regards,
Tristan.
The text was updated successfully, but these errors were encountered: