U
    /eB&                     @  s   d dl mZ d dlZd dlZd dl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mZ eeZG dd dZG d	d
 d
ZdS )    )annotationsN)defaultdict)parse_timedelta	stringify)ClientFuture)
get_client
get_workerc                   @  sT   e Zd ZdZdd ZdddZddd	Zdd
dZdddZdddZ	dddZ
dS )QueueExtensionzAn extension for the scheduler to manage queues

    This adds the following routes to the scheduler

    *  queue_create
    *  queue_release
    *  queue_put
    *  queue_get
    *  queue_size
    c                 C  s`   || _ t | _t | _tdd | _| j j| j| j	| j
| jd | j j| j| jd d S )Nc                   S  s   dS )Nr    r   r   r   6/tmp/pip-unpacked-wheel-g426oqom/distributed/queues.py<lambda>        z)QueueExtension.__init__.<locals>.<lambda>)queue_create	queue_put	queue_getqueue_qsize)queue-future-releasequeue_release)	schedulerdictqueuesclient_refcountr   future_refcounthandlersupdatecreateputgetqsizeZstream_handlersfuture_releaserelease)selfr   r   r   r   __init__   s    	zQueueExtension.__init__Nr   c                 C  sN   t d|  || jkr8tj|d| j|< d| j|< n| j|  d7  < d S )NzQueue name: )maxsize   )loggerdebugr   asyncioQueuer   r"   nameclientr$   r   r   r   r   /   s
    
zQueueExtension.createc                 C  st   || j krd S | j|  d8  < | j| dkrp| j|= | j | j}| j |= dd |D }|rp| jj|d| d d S )Nr%   r   c                 S  s    g | ]}|d  dkr|d qS )typer   valuer   ).0dr   r   r   
<listcomp>@   s      z*QueueExtension.release.<locals>.<listcomp>queue-%skeysr,   )r   r   _queuer   client_releases_keys)r"   r+   r,   Zfuturesr4   r   r   r   r!   7   s    
zQueueExtension.releasec                   sn   |d k	r@d|d}| j ||f  d7  < | jj|gd| d n
d|d}tj| j| ||dI d H  d S )Nr   )r-   r.   r%   r2   r3   msgpacktimeout)r   r   Zclient_desires_keysr(   wait_forr   r   )r"   r+   keydatar,   r9   recordr   r   r   r   D   s    

zQueueExtension.putc                 C  sN   | j ||f  d8  < | j ||f dkrJ| jj|gd| d | j ||f= d S )Nr%   r   r2   r3   )r   r   r6   )r"   r+   r;   r,   r   r   r   r    M   s    zQueueExtension.future_releaseFc           
        s   fdd |rj | }g }|dkrJ| s| I d H }|| q&n:|d k	r^d}t|t|D ]}	| I d H }|| qf fdd|D }|S tjj |  |dI d H } |}|S d S )Nc                   sh   | d dkrd|   } | d } jj|}|dk	r8|jnd}|| d< |dkrd|jj| d< |jj| d	< | S )
zAdd task status if knownr-   r   r.   NZloststateerred	exception	traceback)copyr   Ztasksr   r>   Zexception_blamer@   rA   )r=   r;   tsr>   r"   r   r   processT   s    z#QueueExtension.get.<locals>.processTzNDask queues don't support simultaneous use of integer batch sizes and timeoutsc                   s   g | ]} |qS r   r   )r/   o)rE   r   r   r1   t   s     z&QueueExtension.get.<locals>.<listcomp>r8   )r   emptyr   appendNotImplementedErrorranger(   r:   )
r"   r+   r,   r9   batchqoutr=   msg_r   )rE   r"   r   r   S   s(    
zQueueExtension.getc                 C  s   | j |  S N)r   r   )r"   r+   r,   r   r   r   r   {   s    zQueueExtension.qsize)NNr   )NN)NNNNN)NNN)NNNF)NN)__name__
__module____qualname____doc__r#   r   r!   r   r    r   r   r   r   r   r   r
      s   


	

(r
   c                   @  sz   e Zd ZdZdddZdd Zdd	 Zdd
dZdddZd ddZ	dd Z
d!ddZdd Zdd Zdd Zdd ZdS )"r)   a^  Distributed Queue

    This allows multiple clients to share futures or small bits of data between
    each other with a multi-producer/multi-consumer queue.  All metadata is
    sequentialized through the scheduler.

    Elements of the Queue must be either Futures or msgpack-encodable data
    (ints, strings, lists, dicts).  All data is sent through the scheduler so
    it is wise not to send large objects.  To share large objects scatter the
    data and share the future instead.

    .. warning::

       This object is experimental

    Parameters
    ----------
    name: string (optional)
        Name used by other clients and the scheduler to identify the queue. If
        not given, a random name will be generated.
    client: Client (optional)
        Client used for communication with the scheduler.
        If not given, the default global client will be used.
    maxsize: int (optional)
        Number of items allowed in the queue. If 0 (the default), the queue
        size is unbounded.

    Examples
    --------
    >>> from dask.distributed import Client, Queue  # doctest: +SKIP
    >>> client = Client()  # doctest: +SKIP
    >>> queue = Queue('x')  # doctest: +SKIP
    >>> future = client.submit(f, x)  # doctest: +SKIP
    >>> queue.put(future)  # doctest: +SKIP

    See Also
    --------
    Variable: shared variable between clients
    Nr   c                 C  sx   z|pt  | _W n tk
r0   t j| _Y nX |pBdt j | _|| _	| jj
rft|  | _n| j| j d S )Nzqueue-)r   currentr,   
ValueErrorr	   uuidZuuid4hexr+   r$   Zasynchronousr(   Zensure_future_start_startedsyncr*   r   r   r   r#      s    zQueue.__init__c                   s    | j jj| j| jdI d H  | S )N)r+   r$   )r,   r   r   r+   r$   rD   r   r   r   rY      s    zQueue._startc                   s.   t  dr j S  fdd}|  S d S )NrZ   c                     s    S rP   r   r   rD   r   r   rO      s    zQueue.__await__.<locals>._)hasattrrZ   	__await__)r"   rO   r   rD   r   r]      s    

zQueue.__await__c                   sN   t |tr.| jjjt|j|| jdI d H  n| jjj||| jdI d H  d S )N)r;   r9   r+   )r<   r9   r+   )
isinstancer   r,   r   r   r   r;   r+   )r"   r.   r9   r   r   r   _put   s    
    z
Queue._putc                 K  s$   t |}| jj| j|fd|i|S )a9  Put data into the queue

        Parameters
        ----------
        timeout : number or string or timedelta, optional
            Time in seconds to wait before timing out.
            Instead of number of seconds, it is also possible to specify
            a timedelta in string format, e.g. "200ms".
        r9   )r   r,   r[   r_   )r"   r.   r9   kwargsr   r   r   r      s    
z	Queue.putFc                 K  s$   t |}| jj| jf||d|S )a4  Get data from the queue

        Parameters
        ----------
        timeout : number or string or timedelta, optional
            Time in seconds to wait before timing out.
            Instead of number of seconds, it is also possible to specify
            a timedelta in string format, e.g. "200ms".
        batch : boolean, int (optional)
            If True then return all elements currently waiting in the queue.
            If an integer than return that many elements from the queue
            If False (default) then return one item at a time
        )r9   rK   )r   r,   r[   _get)r"   r9   rK   r`   r   r   r   r      s    z	Queue.getc                 K  s   | j j| jf|S )z'Current number of elements in the queue)r,   r[   _qsize)r"   r`   r   r   r   r      s    zQueue.qsizec                   sL    j jj| j|dI d H } fdd}|dkr:||}ntt||}|S )N)r9   r+   rK   c                   sp   | d dkrdt | d  jd| d d}| d dkrH|j| d | d	   jd
 j| d d n| d }|S )Nr-   r   r.   Tr>   )Zinformr>   r?   r@   rA   r   )opr+   r;   )r   r,   _stateZ	set_error_send_to_schedulerr+   )r0   r.   rD   r   r   rE      s    zQueue._get.<locals>.processF)r,   r   r   r+   listmap)r"   r9   rK   resprE   resultr   rD   r   ra      s      
z
Queue._getc                   s   | j jj| jdI d H }|S )N)r+   )r,   r   r   r+   )r"   ri   r   r   r   rb   	  s    zQueue._qsizec                 C  s$   | j jdkr | j d| jd d S )NZrunningr   )rc   r+   )r,   statusre   r+   rD   r   r   r   close  s    zQueue.closec                 C  s   | j | jjjfS rP   )r+   r,   r   addressrD   r   r   r   __getstate__  s    zQueue.__getstate__c              	   C  s\   |\}}zt |}|jj|ks"tW n$ ttfk
rH   t|dd}Y nX | j||d d S )NF)Zset_as_default)r+   r,   )r   r   rl   AssertionErrorAttributeErrorr   r#   )r"   r>   r+   rl   r,   r   r   r   __setstate__  s    zQueue.__setstate__)NNr   )N)N)NF)NF)rQ   rR   rS   rT   r#   rY   r]   r_   r   r   r   ra   rb   rk   rm   rp   r   r   r   r   r)      s   (






r)   )
__future__r   r(   loggingrW   collectionsr   Z
dask.utilsr   r   Zdistributed.clientr   r   Zdistributed.workerr   r	   	getLoggerrQ   r&   r
   r)   r   r   r   r   <module>   s   
o