Ë
    ÛJêj—T  ã                  óš  — d Z ddlmZ ddlZddlZddl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 ddlmZ dd	lmZ dd
lmZ  ej2                  e«      Zedee   f   Zeeeef   gee   f   ZdZ  G d„ dee«      Z!e G d„ d«      «       Z" G d„ d«      Z# G d„ dee«      Z$e G d„ d«      «       Z% G d„ de#«      Z&g d¢Z'y)zLMemoryTaskQueue - in-memory async task queue with lifecycle status tracking.é    )ÚannotationsN)Údeque)Ú	AwaitableÚCallable)Ú	dataclassÚfield)ÚEnum)ÚAny)Úuuid4)ÚSQLiteDatabase.Úexecution_attemptedc                  ó   — e Zd ZdZdZdZdZy)Ú
TaskStatusÚpendingÚrunningÚ	completedÚfailedN)Ú__name__Ú
__module__Ú__qualname__ÚPENDINGÚRUNNINGÚ	COMPLETEDÚFAILED© ó    úT/home/oem/CyberBrain26-unified/src/cyberbrain26/control_plane/task_queue/__init__.pyr   r      s   „ Ø€GØ€GØ€IØ�Fr   r   c                  ó¾   — e Zd ZU dZded<   ded<   ej                  Zded<   dZd	ed
<   dZ	ded<   dZ
ded<    eej                  ¬«      Zded<   dZded<   dZded<   y)Ú
TaskRecordz*A single queued unit of asynchronous work.ÚstrÚidzCallable[[], Awaitable[Any]]Úfuncr   ÚstatusNr
   ÚresultzException | NoneÚerrorr   ÚintÚattempts)Údefault_factoryÚfloatÚ
created_atúfloat | NoneÚ
started_atÚcompleted_at)r   r   r   Ú__doc__Ú__annotations__r   r   r#   r$   r%   r'   r   Útimer*   r,   r-   r   r   r   r   r   &   sf   … á4àƒGØ
&Ó&Ø#×+Ñ+€FˆJÓ+Ø€FˆCÓØ"€EÐÓ"Ø€HˆcÓÙ¨d¯i©iÔ8€J�Ó8Ø#€J�Ó#Ø!%€L�,Ô%r   r   c                  ón   — e Zd ZdZddd„Zedd„«       Zedd„«       Zdd„Zdd„Z	dd„Z
dd„Zdd	„Zdd
„Zy)ÚMemoryTaskQueueaT  Async FIFO task queue executing callables with status tracking.

    Tasks are enqueued as callables returning coroutines. `run` drains the
    pending queue (including tasks enqueued during dispatch), dispatching each
    through the optional concurrency semaphore and recording
    PENDING -> RUNNING -> COMPLETED|FAILED transitions.
    c                óÆ   — t        «       | _        i | _        t        j                  t        d|«      «      | _        t        j                  «       | _        d| _	        || _
        y )Né   r   )r   Ú_queueÚ	_registryÚasyncioÚ	SemaphoreÚmaxÚ
_semaphoreÚLockÚ_lockÚ_counterÚmax_retries)ÚselfÚmax_concurrencyr>   s      r   Ú__init__zMemoryTaskQueue.__init__>   sG   € Ü).«ˆŒØ02ˆŒÜ!×+Ñ+¬C°°?Ó,CÓDˆŒÜ—\‘\“^ˆŒ
ØˆŒØ&ˆÕr   c                ó,   — t        | j                  «      S ©N)Úlenr5   ©r?   s    r   ÚsizezMemoryTaskQueue.sizeF   s   € ä�4—;‘;ÓÐr   c                óV   — t        d„ | j                  j                  «       D «       «      S )Nc              3  ó\   K  — | ]$  }|j                   t        j                  k(  sŒ!d –— Œ& y­w)r4   N)r#   r   r   )Ú.0Úts     r   ú	<genexpr>z*MemoryTaskQueue.pending.<locals>.<genexpr>L   s!   è ø€ ÒX˜¸¿¹ÄZ×EWÑEWÓ9W”1ÑXùs   ‚",¥,)Úsumr6   ÚvaluesrE   s    r   r   zMemoryTaskQueue.pendingJ   s    € äÑX˜dŸn™n×3Ñ3Ó5ÔXÓXÐXr   c                óP  — | xj                   dz  c_         t        «       j                  }t        |t	        j
                  |g|¢­i |¤Ž¬«      }| j                  j                  |«       || j                  |<   t        j                  d||t        | j                  «      dœ¬«       |S )zFSchedule `func(*args, **kwargs)` for execution and return its task id.r4   )r!   r"   zenqueued task %s)Útask_idÚ
queue_size©Úextra)r=   r   Úhexr   Ú	functoolsÚpartialr5   Úappendr6   ÚloggerÚdebugrD   )r?   r"   ÚargsÚkwargsrO   Úrecords         r   ÚenqueuezMemoryTaskQueue.enqueueN   s‹   € à�Š˜Ñ�Ü“'—+‘+ˆÜ˜w¬Y×->Ñ->¸tÐ-UÀdÒ-UÈfÑ-UÔVˆØ�‰×Ñ˜6Ô"Ø"(ˆ�‰�wÑÜ�‰ØØØ%´S¸¿¹Ó5EÑFð 	ô 	
ð
 ˆr   c                óP   — | j                   sy| j                   j                  «       S )z@Pop and return the next pending TaskRecord without executing it.N)r5   ÚpopleftrE   s    r   ÚdequeuezMemoryTaskQueue.dequeue\   s   € à�{Š{ØØ�{‰{×"Ñ"Ó$Ð$r   c                ó8   — | j                   j                  |«      S rC   )r6   Úget)r?   rO   s     r   ra   zMemoryTaskQueue.getb   s   € Ø�~‰~×!Ñ! 'Ó*Ð*r   c                óX   — | j                   j                  |«      }|r|j                  S d S rC   )r6   ra   r#   )r?   rO   Úrecs      r   r#   zMemoryTaskQueue.statuse   s'   € Ø�n‰n× Ñ  Ó)ˆÙ ˆs�z‰zÐ* dÐ*r   c              ƒ  ó,  K  — t         j                  |_        t        j                  «       |_        t
        j                  d|j                  |j                  t         j                  j                  dœ¬«       d}	 	 | j                  4 ƒd{  –—†  |xj                  dz  c_
        |j                  «       ƒ d{  –—† |_        ddd«      ƒd{  –—†  t         j                  |_        t        j                  «       |_        t
        j                  d|j                  |j                  t         j                  j                  dœ¬«       |j                  S 7 ŒÇ7 Œœ7 Œ‰# 1 ƒd{  –—†7  sw Y   Œ™xY w# t        $ �r}||_        t         j"                  |_        t
        j%                  d|j                  |dz   | j&                  dz   |j                  t         j"                  j                  t)        |«      d	œ¬«       || j&                  k\  rt        j                  «       |_        ‚ |dz  }d
d|dz
  z  z  }t
        j+                  d|j                  |«       t-        j.                  |«      ƒ d{  –—†7   t         j                  |_        Y d}~nd}~ww xY w�Œ­w)z×Execute a single TaskRecord, updating its status. Returns its result.

        On failure, retries up to ``self.max_retries`` times with exponential
        backoff (base delay 0.1s, doubling each attempt).
        zdispatched task %s)rO   r#   rQ   r   Nr4   ztask %s completedztask %s failed (attempt %d/%d))rO   r#   r%   çš™™™™™¹?é   zretrying task %s after %.1fs)r   r   r#   r0   r,   rW   Úinfor!   Úvaluer:   r'   r"   r$   r   r-   Ú	Exceptionr%   r   Ú	exceptionr>   r    rX   r7   Úsleep)r?   r[   ÚattemptÚexcÚbackoffs        r   ÚdispatchzMemoryTaskQueue.dispatchi   s  è ø€ ô #×*Ñ*ˆŒÜ ŸI™I›KˆÔÜ�‰Ø Ø�I‰IØ$Ÿi™i´:×3EÑ3E×3KÑ3KÑLð 	ô 	
ð
 ˆØð!3ØŸ?™?÷ 8ñ 8Ø—O’O qÑ(•OØ*0¯+©+«-×$7�F”M÷8÷ 8ô !+× 4Ñ 4�”Ü&*§i¡i£k�Ô#Ü—‘Ø'Ø—I‘IØ&,§i¡i¼:×;OÑ;O×;UÑ;UÑVð ô ð
 —}‘}Ð$ð8øà$7øð8ø÷ 8÷ 8ñ 8ûô ó 3Ø"�”Ü *× 1Ñ 1�”Ü× Ñ Ø4Ø—I‘IØ˜a‘KØ×$Ñ$ qÑ(à#)§9¡9Ü",×"3Ñ"3×"9Ñ"9Ü!$ S£ñð !ô 
ð ˜d×.Ñ.Ò.Ü*.¯)©)«+�FÔ'ØØ˜1‘�Ø  w°¡{Ñ!3Ñ4�Ü—‘Ð;¸V¿Y¹YÈÔPÜ—m‘m GÓ,×,Ñ,Ü *× 2Ñ 2�—‘ûð+3úñ ùs˜   ‚A9JÁ<E/ ÂEÂE/ Â)EÂ9EÂ:	EÃE/ ÃEÃBE/ ÅJÅE/ ÅEÅE/ ÅE,Å E#Å!E,Å(E/ Å/
JÅ9C1J
É*I-É+J
ÊJÊ
JÊJc              ƒ  óî  K  — g }| j                   4 ƒd{  –—†  | j                  rR| j                  j                  «       }|j                  |«       	 | j	                  |«      ƒ d{  –—†  | j                  rŒRddd«      ƒd{  –—†  |S 7 Œt7 Œ%# t
        $ rC}t        j                  d|j                  ||j                  t        |«      dœ¬«       Y d}~Œjd}~ww xY w7 ŒY# 1 ƒd{  –—†7  sw Y   |S xY w­w)ztDrain the queue, dispatching pending tasks (including those enqueued
        during dispatch) until no tasks remain.Nz$past failure on draining task %s: %s)rO   r%   rQ   )
r<   r5   r^   rV   ro   ri   rW   rX   r!   r    )r?   Úexecutedr[   rm   s       r   ÚrunzMemoryTaskQueue.run›   sÞ   è ø€ ð &(ˆØ—:‘:÷ 	ñ 	Ø—+’+ØŸ™×,Ñ,Ó.�Ø—‘ Ô'ðØŸ-™-¨Ó/×/Ð/ð	 —+“+÷	÷ 	ð ˆð	øð
 0ùÜ ò Ü—L‘LØ>ØŸ	™	ØØ*0¯)©)¼cÀ#»hÑGð	 !÷ ñ ûðúð	ø÷ 	÷ 	ð 	ð ˆüs€   ‚C5•B
–C5™8CÁBÁ&BÁ'BÁ+CÁ8C5ÂCÂC5ÂBÂ	CÂ9CÃCÃCÃCÃC5ÃC2Ã%C(Ã&C2Ã-C5N)r4   r   )r@   r&   r>   r&   ÚreturnÚNone©rs   r&   )r"   ÚTaskFnrY   r
   rZ   r
   rs   r    )rs   úTaskRecord | None)rO   r    rs   rw   )rO   r    rs   zTaskStatus | None)r[   r   rs   r
   ©rs   zlist[TaskRecord])r   r   r   r.   rA   ÚpropertyrF   r   r\   r_   ra   r#   ro   rr   r   r   r   r2   r2   5   sU   „ ñô'ð ò ó ð ð òYó ðYóó%ó+ó+ó03ôdr   r2   c                  ó$   — e Zd ZdZdZdZdZdZdZy)ÚPersistentTaskStatusz6Lifecycle state for JSON-backed jobs stored in SQLite.r   r   r   r   ÚinterruptedN)	r   r   r   r.   r   r   r   r   ÚINTERRUPTEDr   r   r   r{   r{   ¯   s   „ Ù@à€GØ€GØ€IØ€FØ�Kr   r{   c                  óŽ   — e Zd ZU dZded<   ded<   ded<   ded<   d	Zd
ed<   d	Zded<   dZded<   dZded<   d	Z	ded<   d	Z
ded<   y	)ÚPersistentTaskRecordzCSerializable job state that can be inspected after process restart.r    r!   Úhandlerúdict[str, Any]Úpayloadr{   r#   Nr
   r$   ú
str | Noner%   r   r&   r'   g        r)   r*   r+   r,   r-   )r   r   r   r.   r/   r$   r%   r'   r*   r,   r-   r   r   r   r   r   ¹   sW   … áMàƒGØƒLØÓØ Ó Ø€FˆCÓØ€Eˆ:ÓØ€HˆcÓØ€J�ÓØ#€J�Ó#Ø!%€L�,Ô%r   r   c                  ó*  ‡ — e Zd ZdZddddœ	 	 	 	 	 	 	 	 	 dˆ fd„Zedˆ fd„«       Zedˆ fd„«       Zd	d
œ	 	 	 	 	 	 	 dd„Zddœ	 	 	 	 	 	 	 dd„Z	dd„Z
d d„Z	 d!ddœ	 	 	 	 	 d"d„Zd d„Zd d„Zd d„Zd#d„Zd$d„Zd%ˆ fd„Z	 	 	 	 	 	 d&d„Zed'd„«       Zˆ xZS )(ÚSQLiteTaskQueuea„  Memory-compatible queue with an additional durable, named-job API.

    Existing agents may continue to enqueue Python callables in memory. Jobs
    that must survive restart use :meth:`enqueue_job` with a stable handler key
    and JSON payload. A process crash changes a running job to ``interrupted``;
    callers must explicitly retry it to avoid silently repeating side effects.
    Nr4   r   )Úhandlersr@   r>   c               óF  •— t         ‰| �  ||¬«       || _        t        |xs i «      | _        | j                  j                  «       5 }|j                  dt        j                  j                  dt        j                  j                  f«       d d d «       y # 1 sw Y   y xY w)N)r@   r>   z7UPDATE tasks SET status = ?, error = ? WHERE status = ?z?process stopped while task was running; explicit retry required)ÚsuperrA   ÚdatabaseÚdictÚ	_handlersÚtransactionÚexecuter{   r}   rh   r   )r?   r‰   r†   r@   r>   Ú
connectionÚ	__class__s         €r   rA   zSQLiteTaskQueue.__init__Ò   sŒ   ø€ ô 	‰Ñ¨ÀkÐÔRØ ˆŒÜ8<¸Xº^ÈÓ8LˆŒØ�]‰]×&Ñ&Ó(ð 	¨JØ×ÑØIä(×4Ñ4×:Ñ:ØUÜ(×0Ñ0×6Ñ6ðô÷	÷ 	ñ 	ús   ÁABÂB c                ó  •— | j                   j                  «       5 }|j                  dt        j                  j
                  f«      j                  «       d   }d d d «       t        ‰| �   t        «      z   S # 1 sw Y   ŒxY w©Nz+SELECT COUNT(*) FROM tasks WHERE status = ?r   )
r‰   rŽ   r�   r{   r   rh   Úfetchonerˆ   rF   r&   ©r?   rŽ   Údurable_pendingr�   s      €r   rF   zSQLiteTaskQueue.sizeç   su   ø€ à�]‰]×%Ñ%Ó'ð 	¨:Ø(×0Ñ0Ø=Ü%×-Ñ-×3Ñ3Ð5ó÷ ‰h‹j˜ñˆO÷	ô
 ‰w‰|œc /Ó2Ñ2Ð2÷	ð 	úó   œ=A7Á7B c                ó  •— | j                   j                  «       5 }|j                  dt        j                  j
                  f«      j                  «       d   }d d d «       t        ‰| �   t        «      z   S # 1 sw Y   ŒxY wr‘   )
r‰   rŽ   r�   r{   r   rh   r’   rˆ   r   r&   r“   s      €r   r   zSQLiteTaskQueue.pendingð   su   ø€ à�]‰]×%Ñ%Ó'ð 	¨:Ø(×0Ñ0Ø=Ü%×-Ñ-×3Ñ3Ð5ó÷ ‰h‹j˜ñˆO÷	ô
 ‰w‰¤ _Ó!5Ñ5Ð5÷	ð 	úr•   F)Úreplacec               óž   — |r|j                  «       |k7  rt        d«      ‚|| j                  v r|st        d|› �«      ‚|| j                  |<   y)z5Register a stable handler key used by persisted jobs.ú*handler name must be non-empty and trimmedz!task handler already registered: N)ÚstripÚ
ValueErrorr‹   )r?   Únamer€   r—   s       r   Úregister_handlerz SQLiteTaskQueue.register_handlerù   sO   € ñ �t—z‘z“| tÒ+ÜÐIÓJÐJØ�4—>‘>Ñ!©'ÜÐ@ÀÀÐGÓHÐHØ&ˆ�‰�tÒr   )rO   c          	     ó
  — |r|j                  «       |k7  rt        d«      ‚t        |t        «      st	        d«      ‚	 t        j                  |dd¬«      }|xs t        «       j                  }t        j                  «       }| j                  j                  «       5 }|j                  d|||t        j                  j                  |f«       ddd«       |S # t        t        f$ r}t	        d«      |‚d}~ww xY w# 1 sw Y   |S xY w)	z4Persist a named job and a JSON-serializable payload.r™   z)durable task payload must be a dictionary©ú,ú:F©Ú
separatorsÚ	allow_nanz-durable task payload must contain JSON valuesNziINSERT INTO tasks(task_id, handler, payload_json, status, attempts, created_at) VALUES (?, ?, ?, ?, 0, ?))rš   r›   Ú
isinstancerŠ   Ú	TypeErrorÚjsonÚdumpsr   rS   r0   r‰   rŒ   r�   r{   r   rh   )	r?   r€   r‚   rO   Úpayload_jsonrm   Ú
identifierr*   rŽ   s	            r   Úenqueue_jobzSQLiteTaskQueue.enqueue_job  sû   € ñ ˜'Ÿ-™-›/¨WÒ4ÜÐIÓJÐJÜ˜'¤4Ô(ÜÐGÓHÐHð	VÜŸ:™: g¸*ÐPUÔVˆLð Ò+¤£§¡ˆ
Ü—Y‘Y“[ˆ
Ø�]‰]×&Ñ&Ó(ð 	¨JØ×Ñð,ð ØØ Ü(×0Ñ0×6Ñ6Øðô
÷	ð Ðøô! œ:Ð&ò 	VÜÐKÓLÐRUÐUûð	Vú÷	ð Ðús#   ½C Â0C8ÃC5Ã$C0Ã0C5Ã8Dc                óÌ   — | j                   j                  «       5 }|j                  d|f«      j                  «       }d d d «       �| j	                  |«      S d S # 1 sw Y   ŒxY w)Nz%SELECT * FROM tasks WHERE task_id = ?)r‰   rŽ   r�   r’   Ú_row_to_record)r?   rO   rŽ   Úrows       r   Úget_jobzSQLiteTaskQueue.get_job'  sf   € Ø�]‰]×%Ñ%Ó'ð 	¨:Ø×$Ñ$Ø7¸'¸óç‰h‹jð ÷	ð ,/¨?ˆt×"Ñ" 3Ó'ÐDÀÐD÷		ð 	ús   ›"AÁA#c                óÞ   — | j                   j                  «       5 }|j                  d|t        j                  j
                  f«      j                  }ddd«       |dk(  S # 1 sw Y   dk(  S xY w)a²  Delete a durable job by task ID.

        Used by ``cyberbrain plan`` to discard a stale durable result for a
        planner step before re-planning with the same ``--id``, so the new plan
        is always freshly dispatched rather than read back from a prior run.

        Only terminal tasks (completed/failed) are removable; a running task is
        left untouched so an in-flight dispatch is never orphaned mid-flight.
        z3DELETE FROM tasks WHERE task_id = ? AND status != ?Nr4   )r‰   rŒ   r�   r{   r   rh   Úrowcount)r?   rO   rŽ   Údeleteds       r   Ú
delete_jobzSQLiteTaskQueue.delete_job.  sr   € ð �]‰]×&Ñ&Ó(ð 	¨JØ ×(Ñ(ØEàÜ(×0Ñ0×6Ñ6ðó÷ ‰hð ÷	ð ˜!‰|Ð÷	ð ˜!‰|Ðús   ›7AÁA,éd   ©Úlimitc               óh  — |dk  rt        d«      ‚| j                  j                  «       5 }|€"|j                  d|f«      j	                  «       }n,|j                  d|j
                  |f«      j	                  «       }d d d «       D �cg c]  }| j                  |«      ‘Œ c}S # 1 sw Y   Œ(xY wc c}w )Nr   zlimit must not be negativez4SELECT * FROM tasks ORDER BY created_at DESC LIMIT ?zESELECT * FROM tasks WHERE status = ? ORDER BY created_at DESC LIMIT ?)r›   r‰   rŽ   r�   Úfetchallrh   r­   )r?   r#   r¶   rŽ   Úrowsr®   s         r   Ú	list_jobszSQLiteTaskQueue.list_jobsB  s³   € ð �1Š9ÜÐ9Ó:Ð:Ø�]‰]×%Ñ%Ó'ð 		¨:Øˆ~Ø!×)Ñ)ØJÈUÈHóç‘(“*ñ ð "×)Ñ)Ø[Ø—\‘\ 5Ð)ó÷ ‘(“*ð ÷		ð 59Ö9¨S�×#Ñ# CÕ(Ò9Ð9÷		ð 		üò :s   «AB#ÂB/Â#B,c                ó  — | j                   j                  «       5 }|j                  dt        j                  j
                  |t        j                  j
                  f«      j                  }ddd«       |dk(  S # 1 sw Y   dk(  S xY w)z<Explicitly make an interrupted job eligible for another run.úJUPDATE tasks SET status = ?, error = NULL WHERE task_id = ? AND status = ?Nr4   )r‰   rŒ   r�   r{   r   rh   r}   r±   ©r?   rO   rŽ   Úupdateds       r   Úretry_interruptedz!SQLiteTaskQueue.retry_interruptedV  s   € à�]‰]×&Ñ&Ó(ð 	¨JØ ×(Ñ(Ø\ä(×0Ñ0×6Ñ6ØÜ(×4Ñ4×:Ñ:ðó÷ ‰hð ÷	ð ˜!‰|Ð÷	ð ˜!‰|Ðúó   ›AA8Á8Bc                ó  — | j                   j                  «       5 }|j                  dt        j                  j
                  |t        j                  j
                  f«      j                  }ddd«       |dk(  S # 1 sw Y   dk(  S xY w)a  Explicitly make a failed job eligible for another dispatch.

        ``failed`` is only reached when the handler raised, so the job never
        produced a successful result. Re-dispatching it re-runs the handler
        from the top, which for Ptah means the full authorization chain again.
        This is deliberately different from ``retry_interrupted``: an
        interrupted job may have applied side effects before the process died,
        whereas a failed job has no approved result to protect.
        r¼   Nr4   )r‰   rŒ   r�   r{   r   rh   r   r±   r½   s       r   Úretry_failedzSQLiteTaskQueue.retry_failedc  s�   € ð �]‰]×&Ñ&Ó(ð 	¨JØ ×(Ñ(Ø\ä(×0Ñ0×6Ñ6ØÜ(×/Ñ/×5Ñ5ðó÷ ‰hð ÷	ð ˜!‰|Ð÷	ð ˜!‰|ÐúrÀ   c                ó”  — | j                   j                  «       5 }|j                  d|f«      j                  «       }|� |d   t        j
                  j                  k7  r
	 ddd«       y|d   rt        j                  |d   «      nd}t        |t        «      s
	 ddd«       y|j                  t        «      dur
	 ddd«       y|j                  d«      r
	 ddd«       y|j                  dt        j                  j                  |t        j
                  j                  f«      j                  }ddd«       |dk(  S # 1 sw Y   dk(  S xY w)	aR  Re-open a completed job that was refused before any code ran.

        A refusal is not a queue failure: the agent catches it and reports a
        result, so the job is stored as COMPLETED with ``success=False`` and
        ``retry_failed`` never applies. This method is the only way to make such
        a job dispatchable again, and it accepts nothing but a record that
        structurally states ``execution_attempted`` is false.

        Everything else is refused on purpose: a completed job whose result may
        represent executed code, and a result with no such field at all (a
        legacy row, written before the marker existed). Guessing there could
        duplicate side effects of code that really ran, so the check is a
        structural equality against a boolean, never a heuristic on messages or
        error text.
        z7SELECT status, result_json FROM tasks WHERE task_id = ?Nr#   FÚresult_jsonÚsuccesszsUPDATE tasks SET status = ?, error = NULL, result_json = NULL, completed_at = NULL WHERE task_id = ? AND status = ?r4   )r‰   rŒ   r�   r’   r{   r   rh   r§   Úloadsr¥   rŠ   ra   ÚEXECUTION_ATTEMPTED_KEYr   r±   )r?   rO   rŽ   r®   r$   r¾   s         r   Úretry_blockedzSQLiteTaskQueue.retry_blockedx  sF  € ð  �]‰]×&Ñ&Ó(ð 	¨JØ×$Ñ$ØIÈGÈ:óç‰h‹jð ð ˆ{˜c (™mÔ/C×/MÑ/M×/SÑ/SÒSØ÷	ð 	ð 8;¸=Ò7I”T—Z‘Z  MÑ 2Ô3ÈtˆFÜ˜f¤dÔ+Ø÷	ð 	ð �z‰zÔ1Ó2¸%Ñ?Ø÷	ð 	ð �z‰z˜)Ô$Ø÷	ð 	ð !×(Ñ(ðGô )×0Ñ0×6Ñ6ØÜ(×2Ñ2×8Ñ8ðó÷ ‰hð ÷	ð, ˜!‰|Ð÷-	ð, ˜!‰|Ðús%   ›AD:Á)0D:Â"D:ÃD:ÃAD:Ä:Ec              ƒ  óÜ   K  — g }t        | j                  t        j                  d¬«      «      D ]6  }| j	                  |j
                  «      ƒ d{  –—† }|j                  |«       Œ8 |S 7 Œ­w)zARun pending named jobs in order and return their durable records.i † rµ   N)Úreversedrº   r{   r   Údispatch_jobr!   rV   )r?   ÚresultsÚjobr$   s       r   Úrun_persistedzSQLiteTaskQueue.run_persisted   sb   è ø€ à.0ˆÜ˜DŸN™NÔ+?×+GÑ+GÈw˜NÓWÓXò 	#ˆCØ×,Ñ,¨S¯V©VÓ4×4ˆFØ�N‰N˜6Õ"ð	#ð ˆð 5ús   ‚AA,ÁA*ÁA,c              ƒ  óX  K  — | j                  |«      }|€t        d|› �«      ‚| j                  j                  |j                  «      }|€%t        d|j                  › d|j                  › �«      ‚|j                  t        j                  ur|S | j                  ||«      ƒ d{  –—† S 7 Œ­w)z'Dispatch one pending durable job by ID.Nzdurable task not found: z'no registered handler for durable task ú: )r¯   ÚKeyErrorr‹   ra   r€   ÚLookupErrorr!   r#   r{   r   Ú_dispatch_job)r?   rO   rÍ   r€   s       r   rË   zSQLiteTaskQueue.dispatch_job¨  s¡   è ø€ à�l‰l˜7Ó#ˆØˆ;ÜÐ5°g°YÐ?Ó@Ð@Ø—.‘.×$Ñ$ S§[¡[Ó1ˆØˆ?ÜØ9¸#¿&¹&¸ÀÀCÇKÁKÀ=ÐQóð ð �:‰:Ô1×9Ñ9Ñ9ØˆJØ×'Ñ'¨¨WÓ5×5Ð5Ð5ús   ‚B!B*Â#B(Â$B*c              ƒ  ót   •K  — t         ‰| �  «       ƒ d{  –—† }| j                  «       ƒ d{  –—†  |S 7 Œ7 Œ­w)z2Run legacy callable work, then durable named jobs.N)rˆ   rr   rÎ   )r?   Úrecordsr�   s     €r   rr   zSQLiteTaskQueue.run¶  s5   øè ø€ ä™™›×%ˆØ× Ñ Ó"×"Ð"Øˆð &øØ"ús   ƒ8•4–8­6®8¶8c           
   ƒ  óÎ  K  — d}	 t        j                   «       }| j                  j                  «       5 }|j                  dt        j
                  j                  ||j                  t        j                  j                  f«      j                  }d d d «       dk7  r!| j                  |j                  «      }|�|S |S 	  ||j                  «      }t        j                  |«      st        d«      ‚|ƒ d {  –—† }	t        j                   |	dd¬«      }
| j                  j                  «       5 }|j                  dt        j8                  j                  |
t        j                   «       |j                  t        j
                  j                  f«       d d d «       	 | j                  |j                  «      }|�|S |S # 1 sw Y   �Œ-xY w7 ŒÑ# t"        j$                  $ r� | j                  j                  «       5 }|j                  dt        j&                  j                  d	|j                  t        j
                  j                  f«       d d d «       ‚ # 1 sw Y   ‚ xY wt(        $ �rp}|dz  }|| j*                  k  rt        j                  nt        j,                  }|t        j                  u rd nt        j                   «       }| j                  j                  «       5 }|j                  d
|j                  t/        |«      j0                  › d|› �||j                  t        j
                  j                  f«       d d d «       n# 1 sw Y   nxY w|t        j,                  u r&t2        j5                  d|j                  «       Y d }~�Œët#        j6                  dd|dz
  z  z  «      ƒ d {  –—†7   | j                  |j                  «      xs |}Y d }~�ŒËd }~ww xY w# 1 sw Y   �ŒJxY w­w)Nr   zsUPDATE tasks SET status = ?, started_at = ?, attempts = attempts + 1, error = NULL WHERE task_id = ? AND status = ?r4   z.durable task handlers must return an awaitablerŸ   Fr¢   z\UPDATE tasks SET status = ?, error = ?, completed_at = NULL WHERE task_id = ? AND status = ?z'task cancelled; explicit retry requiredzYUPDATE tasks SET status = ?, error = ?, completed_at = ? WHERE task_id = ? AND status = ?rÐ   zdurable task %s failedre   rf   zmUPDATE tasks SET status = ?, result_json = ?, error = NULL, completed_at = ? WHERE task_id = ? AND status = ?)r0   r‰   rŒ   r�   r{   r   rh   r!   r   r±   r¯   r‚   ÚinspectÚisawaitabler¦   r§   r¨   r7   ÚCancelledErrorr}   ri   r>   r   Útyper   rW   rj   rk   r   )r?   rÍ   r€   rl   r,   rŽ   ÚclaimedÚcurrentrh   r$   rÄ   rm   r#   r-   Úlatests                  r   rÓ   zSQLiteTaskQueue._dispatch_job¼  s^  è ø€ ð
 ˆØÜŸ™›ˆJØ—‘×*Ñ*Ó,ð 
°
Ø$×,Ñ,ðDô -×4Ñ4×:Ñ:Ø"ØŸ™Ü,×4Ñ4×:Ñ:ð	ó	÷ ‘(ð ÷
ð ˜!Š|ØŸ,™, s§v¡vÓ.�Ø")Ð"5�wÐ>¸3Ð>ð'Ù §¡Ó,�Ü×*Ñ*¨5Ô1Ü#Ð$TÓUÐUØ$Ÿ�Ü"Ÿj™j¨¸JÐRWÔX�ðH —‘×*Ñ*Ó,ð °
Ø×"Ñ"ð7ô -×6Ñ6×<Ñ<Ø#ÜŸ	™	›ØŸ™Ü,×4Ñ4×:Ñ:ðô
÷ð à—‘˜cŸf™fÓ%ˆØÐ+ˆvÐ4°Ð4÷O
ñ 
úð& %ùä×)Ñ)ò Ø—]‘]×.Ñ.Ó0ð 
°JØ×&Ñ&ð;ô 1×<Ñ<×BÑBØEØŸF™FÜ0×8Ñ8×>Ñ>ð	ô	÷
ð ÷
ð úÜó Ø˜1‘�ð  $×"2Ñ"2Ò2ô )×0Ò0ä-×4Ñ4ð ð
 (.Ô1E×1MÑ1MÑ'M™tÔSW×S\ÑS\ÓS^�Ø—]‘]×.Ñ.Ó0ð °JØ×&Ñ&ð;àŸ™¬$¨s«)×*<Ñ*<Ð)=¸RÀ¸uÐ'EÀ|ÐUX×U[ÑU[Ü-×5Ñ5×;Ñ;ð=ô÷÷ ñ úð Ô1×8Ñ8Ñ8Ü×$Ñ$Ð%=¸s¿v¹vÔFÝÜ—m‘m C¨1°¸1±Ñ+=Ñ$>Ó?×?Ñ?Ø—l‘l 3§6¡6Ó*Ò1¨c�Ýûð)ú÷,ñ üs½   ‚2O%´AF:Â.O%Â>7G	 Ã5GÃ6G	 ÄO%Ä,A$OÆ*O%Æ:GÆ?O%ÇG	 Ç	-OÇ6AIÉ	OÉI	ÉOÉ%A6OËAM Ì7	OÍ M		Í9OÍ>O%Î!OÎ%N(Î&$OÏ
O%ÏOÏO%ÏO"ÏO%c                óÔ   — t        | d   | d   t        j                  | d   «      t        | d   «      | d   �t        j                  | d   «      nd | d   | d   | d   | d	   | d
   ¬«
      S )NrO   r€   r©   r#   rÄ   r%   r'   r*   r,   r-   )
r!   r€   r‚   r#   r$   r%   r'   r*   r,   r-   )r   r§   rÆ   r{   )r®   s    r   r­   zSQLiteTaskQueue._row_to_record  s~   € ä#Ø�9‰~Ø˜	‘NÜ—J‘J˜s >Ñ2Ó3Ü'¨¨H©Ó6Ø58¸Ñ5GÐ5S”4—:‘:˜c -Ñ0Ô1ÐY]Ø�g‘,Ø˜‘_Ø˜<Ñ(Ø˜<Ñ(Ø˜^Ñ,ô
ð 	
r   )
r‰   r   r†   z$dict[str, DurableTaskHandler] | Noner@   r&   r>   r&   rs   rt   ru   )rœ   r    r€   ÚDurableTaskHandlerr—   Úboolrs   rt   )r€   r    r‚   r�   rO   rƒ   rs   r    )rO   r    rs   zPersistentTaskRecord | None)rO   r    rs   rà   rC   )r#   zPersistentTaskStatus | Noner¶   r&   rs   úlist[PersistentTaskRecord])rs   rá   )rO   r    rs   r   rx   )rÍ   r   r€   rß   rs   r   )r®   r
   rs   r   )r   r   r   r.   rA   ry   rF   r   r�   r«   r¯   r³   rº   r¿   rÂ   rÈ   rÎ   rË   rr   rÓ   Ústaticmethodr­   Ú__classcell__)r�   s   @r   r…   r…   É   se  ø„ ñð :>Ø Øñà ðð 7ð	ð
 ðð ðð 
õð* ô3ó ð3ð ô6ó ð6ð ñ'àð'ð $ð'ð
 ð'ð 
ó'ð& #ñàðð  ðð
 ðð 
óó@Eóð, /3ð:ð ñ	:à+ð:ð ð	:ð
 
$ó:ó(óó*&óPó6õðO5à!ðO5ð $ðO5ð 
ó	O5ðb ò
ó ô
r   r…   )	rÇ   rß   r2   r   r{   r…   rv   r   r   )(r.   Ú
__future__r   r7   rT   r×   r§   Úloggingr0   Úcollectionsr   Úcollections.abcr   r   Údataclassesr   r   Úenumr	   Útypingr
   Úuuidr   Ú$cyberbrain26.data_plane.sqlite_storer   Ú	getLoggerr   rW   rv   rŠ   r    rß   rÇ   r   r   r2   r{   r   r…   Ú__all__r   r   r   ú<module>rï      sï   ðÙ RÝ "ã Û Û Û Û Û Ý ß /ß (Ý Ý Ý å ?à	ˆ×	Ñ	˜8Ó	$€à	�#�y ‘~Ð%Ñ	&€Ø˜t C¨ H™~Ð.°	¸#±Ð>Ñ?Ð ð 0Ð ô��dô ð ÷&ð &ó ð&÷wñ wôt ˜3 ô  ð ÷&ð &ó ð&ôQ
�oô Q
òh

�r   