handle lastUpdateTime for Wopi implementation

* get the last updated time from the stored object's storage
* improve perf on loading content from stored object's storage: keep the
response in cache
This commit is contained in:
2022-06-20 21:22:02 +02:00
parent 1742dd4951
commit 10095343ec
5 changed files with 106 additions and 25 deletions

View File

@@ -15,12 +15,17 @@ use Base64Url\Base64Url;
use ChampsLibres\AsyncUploaderBundle\TempUrl\TempUrlGeneratorInterface;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Exception\StoredObjectManagerException;
use DateTimeImmutable;
use DateTimeInterface;
use RuntimeException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Throwable;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;
use Throwable;
use function array_key_exists;
use const OPENSSL_RAW_DATA;
final class StoredObjectManager implements StoredObjectManagerInterface
@@ -29,6 +34,8 @@ final class StoredObjectManager implements StoredObjectManagerInterface
private HttpClientInterface $client;
private array $inMemory = [];
private TempUrlGeneratorInterface $tempUrlGenerator;
public function __construct(
@@ -39,28 +46,35 @@ final class StoredObjectManager implements StoredObjectManagerInterface
$this->tempUrlGenerator = $tempUrlGenerator;
}
public function read(StoredObject $document): string
public function getLastModified(StoredObject $document): DateTimeInterface
{
try {
$response = $this
->client
->request(
Request::METHOD_GET,
$this
->tempUrlGenerator
->generate(
Request::METHOD_GET,
$document->getFilename()
)
->url
);
} catch (Throwable $e) {
throw StoredObjectManagerException::errorDuringHttpRequest($e);
if ($this->hasCache($document)) {
$response = $this->getResponseFromCache($document);
} else {
try {
$response = $this
->client
->request(
Request::METHOD_HEAD,
$this
->tempUrlGenerator
->generate(
Request::METHOD_PUT,
$document->getFilename()
)
->url
);
} catch (TransportExceptionInterface $exception) {
throw StoredObjectManagerException::errorDuringHttpRequest($exception);
}
}
if ($response->getStatusCode() !== Response::HTTP_OK) {
throw StoredObjectManagerException::invalidStatusCode($response->getStatusCode());
}
return $this->extractLastModifiedFromResponse($response);
}
public function read(StoredObject $document): string
{
$response = $this->getResponseFromCache($document);
try {
$data = $response->getContent();
@@ -90,6 +104,10 @@ final class StoredObjectManager implements StoredObjectManagerInterface
public function write(StoredObject $document, string $clearContent): void
{
if ($this->hasCache($document)) {
unset($this->inMemory[$document->getUuid()->toString()]);
}
$encryptedContent = $this->hasKeysAndIv($document)
? openssl_encrypt(
$clearContent,
@@ -126,6 +144,63 @@ final class StoredObjectManager implements StoredObjectManagerInterface
}
}
private function extractLastModifiedFromResponse(ResponseInterface $response): DateTimeImmutable
{
$lastModifiedString = (($response->getHeaders()['last-modified'] ?? [])[0] ?? '');
$date = DateTimeImmutable::createFromFormat(
DateTimeImmutable::RFC7231,
$lastModifiedString
);
if (false === $date) {
throw new RuntimeException('the date from remote storage could not be parsed: '
. $lastModifiedString);
}
return $date;
}
private function fillCache(StoredObject $document): void
{
try {
$response = $this
->client
->request(
Request::METHOD_GET,
$this
->tempUrlGenerator
->generate(
Request::METHOD_GET,
$document->getFilename()
)
->url
);
} catch (Throwable $e) {
throw StoredObjectManagerException::errorDuringHttpRequest($e);
}
if ($response->getStatusCode() !== Response::HTTP_OK) {
throw StoredObjectManagerException::invalidStatusCode($response->getStatusCode());
}
$this->inMemory[$document->getUuid()->toString()] = $response;
}
private function getResponseFromCache(StoredObject $document): ResponseInterface
{
if (!$this->hasCache($document)) {
$this->fillCache($document);
}
return $this->inMemory[$document->getUuid()->toString()];
}
private function hasCache(StoredObject $document): bool
{
return array_key_exists($document->getUuid()->toString(), $this->inMemory);
}
private function hasKeysAndIv(StoredObject $storedObject): bool
{
return ([] !== $storedObject->getKeyInfos()) && ([] !== $storedObject->getIv());

View File

@@ -12,9 +12,12 @@ declare(strict_types=1);
namespace Chill\DocStoreBundle\Service;
use Chill\DocStoreBundle\Entity\StoredObject;
use DateTimeInterface;
interface StoredObjectManagerInterface
{
public function getLastModified(StoredObject $document): DateTimeInterface;
/**
* Get the content of a StoredObject.
*