o
    DfK                     @   s   d Z ddlmZ ddlmZ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yI   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)AnyDict)
_parse_url)ImproperlyConfigured)
get_logger   )KeyValueStoreBackendN)ClientError)DynamoDBBackendDynamoDBAttributename	data_typec                       sd  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edddZdZdZd> fdd	Zd>ddZdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd?d"d#Zd$d% Zd&d' Zd(ed)e ee!f fd*d+Z"d(ed)e ee!f fd,d-Z#d.d/ Z$e%d0d1 Z&d2d3 Z'd4d5 Z(d6d7 Z)d8d9 Z*d(e+d)e,fd:d;Z- fd<d=Z.  Z/S )@r   zAWS DynamoDB result backend.

    Raises:
        celery.exceptions.ImproperlyConfigured:
            if module :pypi:`boto3` is not available.
    celeryr
   NTidSr   resultBchord_countN	timestampttlc              
      s  t  j|i | || _|p| j| _tstdd}d }d }|d urt|\}}	}
}}}}|}|}|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}|rz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__ Q/home/ubuntu/webapp/venv/lib/python3.10/site-packages/celery/backends/dynamodb.pyr%   C   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)rB   rC   r*   dynamodb)rU   )
r<   r+   updater*   r(   client_get_or_create_table_has_ttl_validate_ttl_methods_set_table_ttl)r>   r"   r#   client_parametersrR   rR   rS   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)r]   KeyType)ReadCapacityUnitsWriteCapacityUnits)AttributeDefinitions	TableName	KeySchemaProvisionedThroughput)r8   r   r   r'   r3   r4   r>   rR   rR   rS   _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.rd   ErrorCodeUnknownResourceNotFoundExceptionz*DynamoDB Table {} did not exist, creating.ACTIVEz#DynamoDB Table {} is now available.NrR   )rh   r<   describe_tabler'   r   responser1   create_tabler,   infor.   _wait_for_table_status)r>   table_schemarO   
error_codetable_descriptionrR   rR   rS   rX      s,   
z$DynamoDBBackend._get_or_create_tablec                 C   s   | j du rdS | j dkS )zReturn 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   )r5   rg   rR   rR   rS   rY      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hasattrr<   appendr,   r7   r.   joinAttributeError)r>   required_methodsmissing_methodsmethodrR   rR   rS   rZ      s&   
z%DynamoDBBackend._validate_ttl_methodsc                 C   s   | j |  |ddS )zBGet the boto3 structure describing the DynamoDB TTL specification.)Enabledr]   )rd   TimeToLiveSpecification)r'   rY   )r>   ttl_attr_namerR   rR   rS   _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 )Nri   rj   rk   rl   MessagezJError describing Time to Live on DynamoDB table {table}: {code}: {message})rI   codemessage)	r<   rx   r'   r   rp   r1   r,   r7   r.   )r>   descriptionrO   ru   error_messagerR   rR   rS   _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|  rdnd| j||d |d}~ww )z,Enable or disable Time to Live on the table.TimeToLiveDescriptionTimeToLiveStatus)ENABLEDENABLINGr]   z5DynamoDB Time to Live is {situation} on table {table}r   zalready enabledzcurrently being enabled)	situationrI   )DISABLED	DISABLINGr   zalready disabledzcurrently being disabledzWUnknown DynamoDB Time to Live status {status} on table {table}. Attempting to continue.)statusrI   )r   zUDynamoDB table Time to Live updated: table={table} enabled={enabled} attribute={attr})rI   enabledattrrj   rk   rl   r   zHError {action} Time to Live on DynamoDB table {table}: {code}: {message}enabling	disabling)actionrI   r   r   NrR   )r   rY   
_ttl_fieldr   r,   debugr.   r'   r-   r<   rw   r   rr   r   rp   r1   r7   )	r>   r   r   cur_attr_name	attr_namespecificationrO   ru   r   rR   rR   rS   r[   -  s   
		&

	zDynamoDBBackend._set_table_ttlrn   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.Fri   z+Waiting for DynamoDB table {} to become {}.TableTableStatusr
   N)rW   ro   r'   r,   r   r.   r   )r>   expectedachieved_staterv   current_statusrR   rR   rS   rs     s   z&DynamoDBBackend._wait_for_table_statusc                 C   s   | j | jj| jj|iidS )z0Construct the item retrieval request parameters.)rd   Key)r'   r8   r   r   r>   keyrR   rR   rS   _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.rd   Itemr   )r   r'   r8   r   r   r9   r:   strrY   rV   r   r2   r5   )r>   r   valuer   put_requestrR   rR   rS   _prepare_put_request  s*   z$DynamoDBBackend._prepare_put_requestr   returnc              	   C   sF   t  }| j| jj| jj|i| jj| jjdi| jj| jjt|iidS )z7Construct the counter initialization request parameters0r   )r   r'   r8   r   r   _count_filedr:   r   )r>   r   r   rR   rR   rS   _prepare_init_count_request  s   z+DynamoDBBackend._prepare_init_count_requestc                 C   s@   | j | jj| jj|iid| jj d| jj ddddiiddS )	z2Construct the counter increment request parameterszset z = z + :numz:numr   1UPDATED_NEW)rd   r   UpdateExpressionExpressionAttributeValuesReturnValues)r'   r8   r   r   r   r   rR   rR   rS   _prepare_inc_count_request  s   z*DynamoDBBackend._prepare_inc_count_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_responserR   rS   
<dictcomp>  s    z1DynamoDBBackend._item_to_dict.<locals>.<dictcomp>)r;   )r>   r   rR   r   rS   _item_to_dict  s
   
zDynamoDBBackend._item_to_dictc                 C   s   |   S )N)r=   rg   rR   rR   rS   rW     s   zDynamoDBBackend.clientc                 C   s<   t |}| |}| jjdi |}| |}|| jjS NrR   )r   r   rW   get_itemr   r1   r9   r   )r>   r   request_parametersitem_responseitemrR   rR   rS   r1     s
   

zDynamoDBBackend.getc                 C   s*   t |}| ||}| jjdi | d S r   )r   r   rW   put_item)r>   r   r   r   rR   rR   rS   set	  s   zDynamoDBBackend.setc                    s    fdd|D S )Nc                    s   g | ]}  |qS rR   )r1   )r   r   rg   rR   rS   
<listcomp>  s    z(DynamoDBBackend.mget.<locals>.<listcomp>rR   )r>   keysrR   rg   rS   mget  s   zDynamoDBBackend.mgetc                 C   s(   t |}| |}| jjdi | d S r   )r   r   rW   delete_item)r>   r   r   rR   rR   rS   delete  s   
zDynamoDBBackend.deletec                 C   sD   t |}| |}| jjdi |}|d | jj | jj }t|S )z<Atomically increase the chord_count and return the new count
AttributesNrR   )r   r   rW   update_itemr   r   r   r2   )r>   r   r   r   	new_countrR   rR   rS   incr  s
   
zDynamoDBBackend.incrc                    sD   |  |d }| t|}| jjdi | t j||fi |S )Nr   rR   )get_key_for_chordr   r   rW   r   r$   _apply_chord_incr)r>   header_result_argsbodyr@   	chord_keyinit_count_requestrP   rR   rS   r     s   z!DynamoDBBackend._apply_chord_incr)NN)rn   )0__name__
__module____qualname____doc__r'   r3   r4   r+   r*   r5   supports_autoexpirer   r8   r9   r   r:   r   r;   implements_incrr%   r=   rh   rX   rY   rZ   r   r   r[   rs   r   r   r   r   r   r   r   r   propertyrW   r1   r   r   r   bytesr2   r   r   __classcell__rR   rR   rP   rS   r      sN    
Y


p	
r   )r   collectionsr   r   r   typingr   r   kombu.utils.urlr   r)   celery.exceptionsr   celery.utils.logr	   baser   r(   botocore.exceptionsr   ImportError__all__r   r   r,   r   rR   rR   rR   rS   <module>   s$    
