o
    ›¨ÊhC  ã                   @   s®   d Z ddlmZ ddlmZmZ ddlmZ ddlm	Z	 ddl
mZ ddlmZ zdd	lZdd
lmZ W n eyA   d	 ZZY nw dZeddƒZeeƒZG dd„ deƒZd	S )z"AWS DynamoDB result store backend.é    )Ú
namedtuple)ÚsleepÚtime)Ú
_parse_url)ÚImproperlyConfigured)Ú
get_loggeré   )ÚKeyValueStoreBackendN)ÚClientError)ÚDynamoDBBackendÚDynamoDBAttribute©ÚnameÚ	data_typec                       s  e Zd ZdZdZdZdZdZdZdZ	dZ
eddd�Zed	d
d�Zeddd�Zeddd�ZdZd3‡ fdd„	Zd3dd„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd4d!d"„Zd#d$„ Zd%d&„ Zd'd(„ Zed)d*„ ƒZd+d,„ Z d-d.„ Z!d/d0„ Z"d1d2„ Z#‡  Z$S )5r   z”AWS DynamoDB result backend.

    Raises:
        celery.exceptions.ImproperlyConfigured:
            if module :pypi:`boto3` is not available.
    Úceleryr   NTÚidÚSr   ÚresultÚBÚ	timestampÚNÚttlc              
      s�  t ƒ j|i |¤Ž || _|p| j| _tstdƒ‚d}d }d }|d ur¯t|ƒ\}}	}
}}}}|}|}|d u}|d u}||krAtdƒ‚|}|	dkrZd|
› �| _d| _t	 
d | j¡¡ n|	| _| jjj}|dƒ}|rk|| _t| d	| j¡ƒ| _t| d
| j¡ƒ| _| d| j¡}|r©zt|ƒ| _W n ty¨ } zt	jd|› d�|d� |‚d }~ww |p­| j| _| j| j| jf| _d | _|rÆ| j||d� d S d S )NzBYou need to install the boto3 library to use the DynamoDB backend.Fz6You need to specify both the Access Key ID and Secret.Ú	localhostzhttp://localhost:z	us-east-1z*Using local-only DynamoDB endpoint URL: {}Údynamodb_endpoint_urlÚreadÚwriteÚttl_secondszTTL must be a number; got "ú")Úexc_info)Úaccess_key_idÚsecret_access_key)ÚsuperÚ__init__ÚurlÚ
table_nameÚboto3r   Ú	parse_urlÚendpoint_urlÚ
aws_regionÚloggerÚwarningÚformatÚappÚconfÚgetÚintÚread_capacity_unitsÚwrite_capacity_unitsÚtime_to_live_secondsÚ
ValueErrorÚerrorÚ
_key_fieldÚ_value_fieldÚ_timestamp_fieldÚ_available_fieldsÚ_clientÚ_get_client)Úselfr#   r$   ÚargsÚkwargsÚaws_credentials_givenÚaws_access_key_idÚaws_secret_access_keyÚschemeÚregionÚportÚusernameÚpasswordÚtableÚqueryÚaccess_key_givenÚsecret_key_givenÚ_getÚconfig_endpoint_urlr   Úe©Ú	__class__© úJ/var/www/html/env/lib/python3.10/site-packages/celery/backends/dynamodb.pyr"   >   sŽ   ÿÿÿÿÿ
þÿþÿ
þ€ûý
þÿzDynamoDBBackend.__init__c                 C   s~   | j du r<d| ji}|dur| ||dœ¡ | jdur | j|d< tj	di |¤Ž| _ |  ¡  |  ¡ dur<|  ¡  |  	¡  | j S )zGet client connection.NÚregion_name)r?   r@   r'   Údynamodb)rR   )
r9   r(   Úupdater'   r%   ÚclientÚ_get_or_create_tableÚ_has_ttlÚ_validate_ttl_methodsÚ_set_table_ttl)r;   r   r    Úclient_parametersrO   rO   rP   r:   —   s(   
ÿþ

ÿþzDynamoDBBackend._get_clientc                 C   s6   | j j| j jdœg| j| j jddœg| j| jdœdœS )z=Get the boto3 structure describing the DynamoDB table schema.)ÚAttributeNameÚAttributeTypeÚHASH)rZ   ÚKeyType)ÚReadCapacityUnitsÚWriteCapacityUnits)ÚAttributeDefinitionsÚ	TableNameÚ	KeySchemaÚProvisionedThroughput)r5   r   r   r$   r0   r1   ©r;   rO   rO   rP   Ú_get_table_schema²   s   þÿþÿþòz!DynamoDBBackend._get_table_schemac              
   C   s¢   |   ¡ }z	| jj| jd�W S  tyP } z7|jd  dd¡}|dkrJ| jjd
i |¤Ž}t 	d 
| j¡¡ |  d¡ t 	d 
| j¡¡ |W  Y d	}~S |‚d	}~ww )z=Create table if not exists, otherwise return the description.©ra   ÚErrorÚCodeÚUnknownÚResourceNotFoundExceptionz*DynamoDB Table {} did not exist, creating.ÚACTIVEz#DynamoDB Table {} is now available.NrO   )re   r9   Údescribe_tabler$   r
   Úresponser.   Úcreate_tabler)   Úinfor+   Ú_wait_for_table_status)r;   Útable_schemarL   Ú
error_codeÚtable_descriptionrO   rO   rP   rU   È   s,   ÿÿ
ÿÿ€íz$DynamoDBBackend._get_or_create_tablec                 C   s   | j du rdS | j dkS )zàReturn the desired Time to Live config.

        - True:  Enable TTL on the table; use expiry.
        - False: Disable TTL on the table; don't use expiry.
        - None:  Ignore TTL on the table; don't use expiry.
        Nr   )r2   rd   rO   rO   rP   rV   â   s   ÿzDynamoDBBackend._has_ttlc                 C   sb   d}g }t |ƒD ]}t| j|ƒs| |¡ q|r/t djd |¡d�¡ tdjd |¡d�ƒ‚dS )z:Verify boto support for the DynamoDB Time to Live methods.)Úupdate_time_to_liveÚdescribe_time_to_livezdboto3 method(s) {methods} not found; ensure that boto3>=1.9.178 and botocore>=1.12.178 are installedú,)Úmethodsz#boto3 method(s) {methods} not foundN)	ÚlistÚhasattrr9   Úappendr)   r4   r+   ÚjoinÚAttributeError)r;   Úrequired_methodsÚmissing_methodsÚmethodrO   rO   rP   rW   ì   s&   
€üÿÿÿ÷z%DynamoDBBackend._validate_ttl_methodsc                 C   s   | j |  ¡ |dœdœS )zBGet the boto3 structure describing the DynamoDB TTL specification.)ÚEnabledrZ   )ra   ÚTimeToLiveSpecification)r$   rV   )r;   Úttl_attr_namerO   rO   rP   Ú_get_ttl_specification	  s
   þþz&DynamoDBBackend._get_ttl_specificationc              
   C   sp   z| j j| jd�}W |S  ty7 } z |jd  dd¡}|jd  dd¡}t dj| j||d�¡ |‚d }~ww )Nrf   rg   rh   ri   ÚMessagezJError describing Time to Live on DynamoDB table {table}: {code}: {message})rF   ÚcodeÚmessage)	r9   ru   r$   r
   rm   r.   r)   r4   r+   )r;   ÚdescriptionrL   rr   Úerror_messagerO   rO   rP   Ú_get_table_ttl_description  s$   ÿóú€õz*DynamoDBBackend._get_table_ttl_descriptionc           	      C   sn  |   ¡ }|d d }|dv r2|d d }|  ¡ r1|| jjkr1t dj|dkr(dnd| jd	�¡ |S n'|d
v rN|  ¡ sMt dj|dkrDdnd| jd	�¡ |S nt dj|| jd�¡ |dkr_|n| jj}z | j	j
di | j|d�¤Ž}t dj| j|  ¡ | jjd�¡ |W S  ty¶ } z'|jd  dd¡}|jd  dd¡}t dj|  ¡ r§dnd| j||d�¡ |‚d}~ww )z,Enable or disable Time to Live on the table.ÚTimeToLiveDescriptionÚTimeToLiveStatus)ÚENABLEDÚENABLINGrZ   z5DynamoDB Time to Live is {situation} on table {table}rŒ   zalready enabledzcurrently being enabled)Ú	situationrF   )ÚDISABLEDÚ	DISABLINGr�   zalready disabledzcurrently being disabledzWUnknown DynamoDB Time to Live status {status} on table {table}. Attempting to continue.)ÚstatusrF   )r‚   zUDynamoDB table Time to Live updated: table={table} enabled={enabled} attribute={attr})rF   ÚenabledÚattrrg   rh   ri   r„   zHError {action} Time to Live on DynamoDB table {table}: {code}: {message}ÚenablingÚ	disabling)ÚactionrF   r…   r†   NrO   )r‰   rV   Ú
_ttl_fieldr   r)   Údebugr+   r$   r*   r9   rt   rƒ   ro   r
   rm   r.   r4   )	r;   r‡   r‘   Úcur_attr_nameÚ	attr_nameÚspecificationrL   rr   rˆ   rO   rO   rP   rX   (  s„   
ÿÿù	€ÿù	ôû&ÿ
ÿÿúÿ
ù	€ôzDynamoDBBackend._set_table_ttlrk   c                 C   sT   d}|s(| j j| jd�}t d | j|¡¡ |d d }||k}tdƒ |rdS dS )z#Poll for the expected table status.Frf   z+Waiting for DynamoDB table {} to become {}.ÚTableÚTableStatusr   N)rT   rl   r$   r)   r˜   r+   r   )r;   ÚexpectedÚachieved_staters   Úcurrent_statusrO   rO   rP   rp   ˜  s   ÿþÿôz&DynamoDBBackend._wait_for_table_statusc                 C   s   | j | jj| jj|iidœS )z0Construct the item retrieval request parameters.)ra   ÚKey)r$   r5   r   r   )r;   ÚkeyrO   rO   rP   Ú_prepare_get_request©  s   ÿÿþz$DynamoDBBackend._prepare_get_requestc              	   C   s~   t ƒ }| j| jj| jj|i| jj| jj|i| jj| jjt|ƒiidœ}|  ¡ r=|d  	| j
j| j
jtt|| j ƒƒii¡ |S )z/Construct the item creation request parameters.)ra   ÚItemr¤   )r   r$   r5   r   r   r6   r7   ÚstrrV   rS   r—   r/   r2   )r;   r¢   Úvaluer   Úput_requestrO   rO   rP   Ú_prepare_put_request´  s*   ÿÿÿùþþÿz$DynamoDBBackend._prepare_put_requestc                    s    dˆ vri S ‡ fdd„| j D ƒS )z1Convert get_item() response to field-value pairs.r¤   c                    s$   i | ]}|j ˆ d  |j  |j “qS )r¤   r   )Ú.0Úfield©Úraw_responserO   rP   Ú
<dictcomp>Ò  s    ÿÿz1DynamoDBBackend._item_to_dict.<locals>.<dictcomp>)r8   )r;   r¬   rO   r«   rP   Ú_item_to_dictÎ  s
   
þzDynamoDBBackend._item_to_dictc                 C   s   |   ¡ S )N)r:   rd   rO   rO   rP   rT   ×  s   zDynamoDBBackend.clientc                 C   s<   t |ƒ}|  |¡}| jjdi |¤Ž}|  |¡}| | jj¡S ©NrO   )r¥   r£   rT   Úget_itemr®   r.   r6   r   )r;   r¢   Úrequest_parametersÚitem_responseÚitemrO   rO   rP   r.   Û  s
   

zDynamoDBBackend.getc                 C   s*   t |ƒ}|  ||¡}| jjdi |¤Ž d S r¯   )r¥   r¨   rT   Úput_item)r;   r¢   r¦   r±   rO   rO   rP   Úsetâ  s   zDynamoDBBackend.setc                    s   ‡ fdd„|D ƒS )Nc                    s   g | ]}ˆ   |¡‘qS rO   )r.   )r©   r¢   rd   rO   rP   Ú
<listcomp>è  s    z(DynamoDBBackend.mget.<locals>.<listcomp>rO   )r;   ÚkeysrO   rd   rP   Úmgetç  s   zDynamoDBBackend.mgetc                 C   s(   t |ƒ}|  |¡}| jjdi |¤Ž d S r¯   )r¥   r£   rT   Údelete_item)r;   r¢   r±   rO   rO   rP   Údeleteê  s   
zDynamoDBBackend.delete)NN)rk   )%Ú__name__Ú
__module__Ú__qualname__Ú__doc__r$   r0   r1   r(   r'   r2   Úsupports_autoexpirer   r5   r6   r7   r—   r8   r"   r:   re   rU   rV   rW   rƒ   r‰   rX   rp   r£   r¨   r®   ÚpropertyrT   r.   rµ   r¸   rº   Ú__classcell__rO   rO   rM   rP   r      sB    
Y


p	
r   )r¾   Úcollectionsr   r   r   Úkombu.utils.urlr   r&   Úcelery.exceptionsr   Úcelery.utils.logr   Úbaser	   r%   Úbotocore.exceptionsr
   ÚImportErrorÚ__all__r   r»   r)   r   rO   rO   rO   rP   Ú<module>   s"    ÿ
