ok
Direktori : /home2/selectio/www/innerstore/vendor/laravel/framework/src/Illuminate/Cache/ |
Current File : /home2/selectio/www/innerstore/vendor/laravel/framework/src/Illuminate/Cache/DynamoDbStore.php |
<?php namespace Illuminate\Cache; use Aws\DynamoDb\DynamoDbClient; use Aws\DynamoDb\Exception\DynamoDbException; use Illuminate\Contracts\Cache\LockProvider; use Illuminate\Contracts\Cache\Store; use Illuminate\Support\Carbon; use Illuminate\Support\InteractsWithTime; use Illuminate\Support\Str; use RuntimeException; class DynamoDbStore implements LockProvider, Store { use InteractsWithTime; /** * The DynamoDB client instance. * * @var \Aws\DynamoDb\DynamoDbClient */ protected $dynamo; /** * The table name. * * @var string */ protected $table; /** * The name of the attribute that should hold the key. * * @var string */ protected $keyAttribute; /** * The name of the attribute that should hold the value. * * @var string */ protected $valueAttribute; /** * The name of the attribute that should hold the expiration timestamp. * * @var string */ protected $expirationAttribute; /** * A string that should be prepended to keys. * * @var string */ protected $prefix; /** * Create a new store instance. * * @param \Aws\DynamoDb\DynamoDbClient $dynamo * @param string $table * @param string $keyAttribute * @param string $valueAttribute * @param string $expirationAttribute * @param string $prefix * @return void */ public function __construct(DynamoDbClient $dynamo, $table, $keyAttribute = 'key', $valueAttribute = 'value', $expirationAttribute = 'expires_at', $prefix = '') { $this->table = $table; $this->dynamo = $dynamo; $this->keyAttribute = $keyAttribute; $this->valueAttribute = $valueAttribute; $this->expirationAttribute = $expirationAttribute; $this->setPrefix($prefix); } /** * Retrieve an item from the cache by key. * * @param string $key * @return mixed */ public function get($key) { $response = $this->dynamo->getItem([ 'TableName' => $this->table, 'ConsistentRead' => false, 'Key' => [ $this->keyAttribute => [ 'S' => $this->prefix.$key, ], ], ]); if (! isset($response['Item'])) { return; } if ($this->isExpired($response['Item'])) { return; } if (isset($response['Item'][$this->valueAttribute])) { return $this->unserialize( $response['Item'][$this->valueAttribute]['S'] ?? $response['Item'][$this->valueAttribute]['N'] ?? null ); } } /** * Retrieve multiple items from the cache by key. * * Items not found in the cache will have a null value. * * @param array $keys * @return array */ public function many(array $keys) { $prefixedKeys = array_map(function ($key) { return $this->prefix.$key; }, $keys); $response = $this->dynamo->batchGetItem([ 'RequestItems' => [ $this->table => [ 'ConsistentRead' => false, 'Keys' => collect($prefixedKeys)->map(function ($key) { return [ $this->keyAttribute => [ 'S' => $key, ], ]; })->all(), ], ], ]); $now = Carbon::now(); return array_merge(collect(array_flip($keys))->map(function () { // })->all(), collect($response['Responses'][$this->table])->mapWithKeys(function ($response) use ($now) { if ($this->isExpired($response, $now)) { $value = null; } else { $value = $this->unserialize( $response[$this->valueAttribute]['S'] ?? $response[$this->valueAttribute]['N'] ?? null ); } return [Str::replaceFirst($this->prefix, '', $response[$this->keyAttribute]['S']) => $value]; })->all()); } /** * Determine if the given item is expired. * * @param array $item * @param \DateTimeInterface|null $expiration * @return bool */ protected function isExpired(array $item, $expiration = null) { $expiration = $expiration ?: Carbon::now(); return isset($item[$this->expirationAttribute]) && $expiration->getTimestamp() >= $item[$this->expirationAttribute]['N']; } /** * Store an item in the cache for a given number of seconds. * * @param string $key * @param mixed $value * @param int $seconds * @return bool */ public function put($key, $value, $seconds) { $this->dynamo->putItem([ 'TableName' => $this->table, 'Item' => [ $this->keyAttribute => [ 'S' => $this->prefix.$key, ], $this->valueAttribute => [ $this->type($value) => $this->serialize($value), ], $this->expirationAttribute => [ 'N' => (string) $this->toTimestamp($seconds), ], ], ]); return true; } /** * Store multiple items in the cache for a given number of $seconds. * * @param array $values * @param int $seconds * @return bool */ public function putMany(array $values, $seconds) { $expiration = $this->toTimestamp($seconds); $this->dynamo->batchWriteItem([ 'RequestItems' => [ $this->table => collect($values)->map(function ($value, $key) use ($expiration) { return [ 'PutRequest' => [ 'Item' => [ $this->keyAttribute => [ 'S' => $this->prefix.$key, ], $this->valueAttribute => [ $this->type($value) => $this->serialize($value), ], $this->expirationAttribute => [ 'N' => (string) $expiration, ], ], ], ]; })->values()->all(), ], ]); return true; } /** * Store an item in the cache if the key doesn't exist. * * @param string $key * @param mixed $value * @param int $seconds * @return bool */ public function add($key, $value, $seconds) { try { $this->dynamo->putItem([ 'TableName' => $this->table, 'Item' => [ $this->keyAttribute => [ 'S' => $this->prefix.$key, ], $this->valueAttribute => [ $this->type($value) => $this->serialize($value), ], $this->expirationAttribute => [ 'N' => (string) $this->toTimestamp($seconds), ], ], 'ConditionExpression' => 'attribute_not_exists(#key) OR #expires_at < :now', 'ExpressionAttributeNames' => [ '#key' => $this->keyAttribute, '#expires_at' => $this->expirationAttribute, ], 'ExpressionAttributeValues' => [ ':now' => [ 'N' => (string) Carbon::now()->getTimestamp(), ], ], ]); return true; } catch (DynamoDbException $e) { if (Str::contains($e->getMessage(), 'ConditionalCheckFailed')) { return false; } throw $e; } } /** * Increment the value of an item in the cache. * * @param string $key * @param mixed $value * @return int|bool */ public function increment($key, $value = 1) { try { $response = $this->dynamo->updateItem([ 'TableName' => $this->table, 'Key' => [ $this->keyAttribute => [ 'S' => $this->prefix.$key, ], ], 'ConditionExpression' => 'attribute_exists(#key) AND #expires_at > :now', 'UpdateExpression' => 'SET #value = #value + :amount', 'ExpressionAttributeNames' => [ '#key' => $this->keyAttribute, '#value' => $this->valueAttribute, '#expires_at' => $this->expirationAttribute, ], 'ExpressionAttributeValues' => [ ':now' => [ 'N' => (string) Carbon::now()->getTimestamp(), ], ':amount' => [ 'N' => (string) $value, ], ], 'ReturnValues' => 'UPDATED_NEW', ]); return (int) $response['Attributes'][$this->valueAttribute]['N']; } catch (DynamoDbException $e) { if (Str::contains($e->getMessage(), 'ConditionalCheckFailed')) { return false; } throw $e; } } /** * Decrement the value of an item in the cache. * * @param string $key * @param mixed $value * @return int|bool */ public function decrement($key, $value = 1) { try { $response = $this->dynamo->updateItem([ 'TableName' => $this->table, 'Key' => [ $this->keyAttribute => [ 'S' => $this->prefix.$key, ], ], 'ConditionExpression' => 'attribute_exists(#key) AND #expires_at > :now', 'UpdateExpression' => 'SET #value = #value - :amount', 'ExpressionAttributeNames' => [ '#key' => $this->keyAttribute, '#value' => $this->valueAttribute, '#expires_at' => $this->expirationAttribute, ], 'ExpressionAttributeValues' => [ ':now' => [ 'N' => (string) Carbon::now()->getTimestamp(), ], ':amount' => [ 'N' => (string) $value, ], ], 'ReturnValues' => 'UPDATED_NEW', ]); return (int) $response['Attributes'][$this->valueAttribute]['N']; } catch (DynamoDbException $e) { if (Str::contains($e->getMessage(), 'ConditionalCheckFailed')) { return false; } throw $e; } } /** * Store an item in the cache indefinitely. * * @param string $key * @param mixed $value * @return bool */ public function forever($key, $value) { return $this->put($key, $value, Carbon::now()->addYears(5)->getTimestamp()); } /** * Get a lock instance. * * @param string $name * @param int $seconds * @param string|null $owner * @return \Illuminate\Contracts\Cache\Lock */ public function lock($name, $seconds = 0, $owner = null) { return new DynamoDbLock($this, $this->prefix.$name, $seconds, $owner); } /** * Restore a lock instance using the owner identifier. * * @param string $name * @param string $owner * @return \Illuminate\Contracts\Cache\Lock */ public function restoreLock($name, $owner) { return $this->lock($name, 0, $owner); } /** * Remove an item from the cache. * * @param string $key * @return bool */ public function forget($key) { $this->dynamo->deleteItem([ 'TableName' => $this->table, 'Key' => [ $this->keyAttribute => [ 'S' => $this->prefix.$key, ], ], ]); return true; } /** * Remove all items from the cache. * * @return bool * * @throws \RuntimeException */ public function flush() { throw new RuntimeException('DynamoDb does not support flushing an entire table. Please create a new table.'); } /** * Get the UNIX timestamp for the given number of seconds. * * @param int $seconds * @return int */ protected function toTimestamp($seconds) { return $seconds > 0 ? $this->availableAt($seconds) : Carbon::now()->getTimestamp(); } /** * Serialize the value. * * @param mixed $value * @return mixed */ protected function serialize($value) { return is_numeric($value) ? (string) $value : serialize($value); } /** * Unserialize the value. * * @param mixed $value * @return mixed */ protected function unserialize($value) { if (filter_var($value, FILTER_VALIDATE_INT) !== false) { return (int) $value; } if (is_numeric($value)) { return (float) $value; } return unserialize($value); } /** * Get the DynamoDB type for the given value. * * @param mixed $value * @return string */ protected function type($value) { return is_numeric($value) ? 'N' : 'S'; } /** * Get the cache key prefix. * * @return string */ public function getPrefix() { return $this->prefix; } /** * Set the cache key prefix. * * @param string $prefix * @return void */ public function setPrefix($prefix) { $this->prefix = ! empty($prefix) ? $prefix.':' : ''; } /** * Get the DynamoDb Client instance. * * @return DynamoDbClient */ public function getClient() { return $this->dynamo; } }