o
    h|L                     @   s   d Z ddlm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yO   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)
ip_address)sleeptime)AnyDict)
_parse_url)ImproperlyConfigured)
get_logger   )KeyValueStoreBackendN)ClientError)DynamoDBBackendDynamoDBAttributename	data_typec                       sp  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e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dAd$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%d0d1 Z&e'd2d3 Z(d4d5 Z)d6d7 Z*d8d9 Z+d:d; Z,d*e-d+e.fd<d=Z/ fd>d?Z0  Z1S )Br   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sLt|	rbd|	 d|
 | _	d| _
td| j	 n|	| _
| jjj}|d	}|rs|| _	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://: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_urlr   _is_valid_ip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__ Z/var/www/html/optinet_system/venv/lib/python3.10/site-packages/celery/backends/dynamodb.pyr'   D   s   


zDynamoDBBackend.__init__c                 C   s$   zt |  W dS  ty   Y dS w )NTF)r   r9   )iprU   rU   rV   r,      s   zDynamoDBBackend._is_valid_ipc                 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)rE   rF   r-   dynamodb)rY   )
r?   r.   updater-   r*   client_get_or_create_table_has_ttl_validate_ttl_methods_set_table_ttl)rA   r$   r%   client_parametersrU   rU   rV   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)ra   KeyType)ReadCapacityUnitsWriteCapacityUnits)AttributeDefinitions	TableName	KeySchemaProvisionedThroughput)r;   r   r   r)   r6   r7   rA   rU   rU   rV   _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.rh   ErrorCodeUnknownResourceNotFoundExceptionz*DynamoDB Table {} did not exist, creating.ACTIVEz#DynamoDB Table {} is now available.NrU   )rl   r?   describe_tabler)   r   responser4   create_tabler/   infor1   _wait_for_table_status)rA   table_schemarR   
error_codetable_descriptionrU   rU   rV   r\      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   )r8   rk   rU   rU   rV   r]      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/   r:   r1   joinAttributeError)rA   required_methodsmissing_methodsmethodrU   rU   rV   r^      s&   
z%DynamoDBBackend._validate_ttl_methodsc                 C   s   | j |  |ddS )zBGet the boto3 structure describing the DynamoDB TTL specification.)Enabledra   )rh   TimeToLiveSpecification)r)   r]   )rA   ttl_attr_namerU   rU   rV   _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 )Nrm   rn   ro   rp   MessagezJError describing Time to Live on DynamoDB table {table}: {code}: {message})rL   codemessage)	r?   r|   r)   r   rt   r4   r/   r:   r1   )rA   descriptionrR   ry   error_messagerU   rU   rV   _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ENABLINGra   z5DynamoDB Time to Live is {situation} on table {table}r   zalready enabledzcurrently being enabled)	situationrL   )DISABLED	DISABLINGr   zalready disabledzcurrently being disabledzWUnknown DynamoDB Time to Live status {status} on table {table}. Attempting to continue.)statusrL   )r   zUDynamoDB table Time to Live updated: table={table} enabled={enabled} attribute={attr})rL   enabledattrrn   ro   rp   r   zHError {action} Time to Live on DynamoDB table {table}: {code}: {message}enabling	disabling)actionrL   r   r   NrU   )r   r]   
_ttl_fieldr   r/   debugr1   r)   r0   r?   r{   r   rv   r   rt   r4   r:   )	rA   r   r   cur_attr_name	attr_namespecificationrR   ry   r   rU   rU   rV   r_   6  s   
		&

	zDynamoDBBackend._set_table_ttlrr   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.Frm   z+Waiting for DynamoDB table {} to become {}.TableTableStatusr   N)r[   rs   r)   r/   r   r1   r   )rA   expectedachieved_staterz   current_statusrU   rU   rV   rw     s   z&DynamoDBBackend._wait_for_table_statusc                 C   s   | j | jj| jj|iidS )z0Construct the item retrieval request parameters.)rh   Key)r)   r;   r   r   rA   keyrU   rU   rV   _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.rh   Itemr   )r   r)   r;   r   r   r<   r=   strr]   rZ   r   r5   r8   )rA   r   valuer   put_requestrU   rU   rV   _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)   r;   r   r   _count_filedr=   r   )rA   r   r   rU   rU   rV   _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)rh   r   UpdateExpressionExpressionAttributeValuesReturnValues)r)   r;   r   r   r   r   rU   rU   rV   _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_responserU   rV   
<dictcomp>  s    z1DynamoDBBackend._item_to_dict.<locals>.<dictcomp>)r>   )rA   r   rU   r   rV   _item_to_dict  s
   
zDynamoDBBackend._item_to_dictc                 C   s   |   S )N)r@   rk   rU   rU   rV   r[     s   zDynamoDBBackend.clientc                 C   s<   t |}| |}| jjdi |}| |}|| jjS NrU   )r   r   r[   get_itemr   r4   r<   r   )rA   r   request_parametersitem_responseitemrU   rU   rV   r4     s
   

zDynamoDBBackend.getc                 C   s*   t |}| ||}| jjdi | d S r   )r   r   r[   put_item)rA   r   r   r   rU   rU   rV   set  s   zDynamoDBBackend.setc                    s    fdd|D S )Nc                    s   g | ]}  |qS rU   )r4   )r   r   rk   rU   rV   
<listcomp>  s    z(DynamoDBBackend.mget.<locals>.<listcomp>rU   )rA   keysrU   rk   rV   mget  s   zDynamoDBBackend.mgetc                 C   s(   t |}| |}| jjdi | d S r   )r   r   r[   delete_item)rA   r   r   rU   rU   rV   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
AttributesNrU   )r   r   r[   update_itemr   r   r   r5   )rA   r   r   r   	new_countrU   rU   rV   incr  s
   
zDynamoDBBackend.incrc                    sD   |  |d }| t|}| jjdi | t j||fi |S )Nr   rU   )get_key_for_chordr   r   r[   r   r&   _apply_chord_incr)rA   header_result_argsbodyrC   	chord_keyinit_count_requestrS   rU   rV   r   '  s   z!DynamoDBBackend._apply_chord_incr)NN)rr   )2__name__
__module____qualname____doc__r)   r6   r7   r.   r-   r8   supports_autoexpirer   r;   r<   r   r=   r   r>   implements_incrr'   staticmethodr,   r@   rl   r\   r]   r^   r   r   r_   rw   r   r   r   r   r   r   r   r   propertyr[   r4   r   r   r   bytesr5   r   r   __classcell__rU   rU   rS   rV   r      sR    Y




p	
r   )r   collectionsr   	ipaddressr   r   r   typingr   r   kombu.utils.urlr   r+   celery.exceptionsr	   celery.utils.logr
   baser   r*   botocore.exceptionsr   ImportError__all__r   r   r/   r   rU   rU   rU   rV   <module>   s&    
