Вход Регистрация
Файл: vendor/laravel/framework/src/Illuminate/Cache/DynamoDbStore.php
Строк: 432
<?php

namespace IlluminateCache;

use 
AwsDynamoDbDynamoDbClient;
use 
AwsDynamoDbExceptionDynamoDbException;
use 
IlluminateContractsCacheLockProvider;
use 
IlluminateContractsCacheStore;
use 
IlluminateSupportCarbon;
use 
IlluminateSupportInteractsWithTime;
use 
IlluminateSupportStr;
use 
RuntimeException;

class 
DynamoDbStore implements LockProviderStore
{
    use 
InteractsWithTime;

    
/**
     * The DynamoDB client instance.
     *
     * @var AwsDynamoDbDynamoDbClient
     */
    
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  AwsDynamoDbDynamoDbClient  $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$valueCarbon::now()->addYears(5)->getTimestamp());
    }

    
/**
     * Get a lock instance.
     *
     * @param  string  $name
     * @param  int  $seconds
     * @param  string|null  $owner
     * @return IlluminateContractsCacheLock
     */
    
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 IlluminateContractsCacheLock
     */
    
public function restoreLock($name$owner)
    {
        return 
$this->lock($name0$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($valueFILTER_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 AwsDynamoDbDynamoDbClient
     */
    
public function getClient()
    {
        return 
$this->dynamo;
    }
}
Онлайн: 0
Реклама