+
    }i3                    D   ^ RI Ht ^ RIt^ RIHt ^ RIHt ^ RIHtH	t	 ^ RI
Ht ^ RIHtHt ^ RIHt ^ R	IHt ^ R
IHt ^RIHt ^RIHt ]'       d'   ^ RIHt ^ RIHt ^ RIHt ^ RIHt ^ RIH t  ^ RI!H"t"H#t# ]! ]$4      t%]	! R4      t&]! R4       ! R R]]4      4       t'R# )    )annotationsN)	timedelta)	getLogger)TYPE_CHECKINGTypeVar)override)Requestservice_locator)
docs_group)wait_for_all_tasks_for_finish)RequestManager)Storage)validate_storage_name)Sequence)r	   )Configuration)StorageClient)RequestQueueClient)ProcessedRequestRequestQueueMetadataTStoragesc                     ] tR t^ tRtR R lt]]R R l4       4       t]]R R l4       4       t	]R R	 l4       t
]R
 R l4       t]R R l4       t]]RRRRRRRRRR/R R ll4       4       t]R R l4       t]R R l4       t]RR/R R ll4       t]RRRRR ]! ^R!7      R"RR#R/R$ R% ll4       tR& R' ltR( R) ltR* R+ ltRR/R, R- lltR. R/ ltR0 R1 ltR2^RR/R3 R4 lltR5tR# )6RequestQueuea  Request queue is a storage for managing HTTP requests.

The request queue class serves as a high-level interface for organizing and managing HTTP requests
during web crawling. It provides methods for adding, retrieving, and manipulating requests throughout
the crawling lifecycle, abstracting away the underlying storage implementation details.

Request queue maintains the state of each URL to be crawled, tracking whether it has been processed,
is currently being handled, or is waiting in the queue. Each URL in the queue is uniquely identified
by a `unique_key` property, which prevents duplicate processing unless explicitly configured otherwise.

The class supports both breadth-first and depth-first crawling strategies through its `forefront` parameter
when adding requests. It also provides mechanisms for error handling and request reclamation when
processing fails.

You can open a request queue using the `open` class method, specifying either a name or ID to identify
the queue. The underlying storage implementation is determined by the configured storage client.

### Usage

```python
from crawlee.storages import RequestQueue

# Open a request queue
rq = await RequestQueue.open(name='my_queue')

# Add a request
await rq.add_request('https://example.com')

# Process requests
request = await rq.fetch_next_request()
if request:
    try:
        # Process the request
        # ...
        await rq.mark_request_as_handled(request)
    except Exception:
        await rq.reclaim_request(request)
```
c               (    V ^8  d   QhRRRRRRRR/# )	   clientr   idstrname
str | NonereturnNone )formats   "q/Users/ahmad/.openclaw/workspace/my-crawler/.venv/lib/python3.14/site-packages/crawlee/storages/_request_queue.py__annotate__RequestQueue.__annotate__J   s0     @ @1 @s @* @QU @    c                    \        V4       Wn        W n        W0n        \        \
        P                  ,          ! 4       V n        R# )zInitialize a new instance.

Preferably use the `RequestQueue.open` constructor to create a new instance.

Args:
    client: An instance of a storage client.
    id: The unique identifier of the storage.
    name: The name of the storage, if available.
N)r   _client_id_namelistasyncioTask_add_requests_tasks)selfr   r   r   s   &&&&r%   __init__RequestQueue.__init__J   s2     	d#
#'#5#7 ?r(   c                   V ^8  d   QhRR/# )r   r!   r   r#   )r$   s   "r%   r&   r'   _   s      C r(   c                	    V P                   # N)r+   r1   s   &r%   r   RequestQueue.id]   s     xxr(   c                   V ^8  d   QhRR/# )r   r!   r    r#   )r$   s   "r%   r&   r'   d   s      j r(   c                	    V P                   # r6   )r,   r7   s   &r%   r   RequestQueue.nameb   s     zzr(   c                   V ^8  d   QhRR/# )r   r!   r   r#   )r$   s   "r%   r&   r'   h   s     1 1$8 1r(   c                	R   "   V P                   P                  4       G R j  xL
 #  L5ir6   )r*   get_metadatar7   s   &r%   r>   RequestQueue.get_metadatag   s     \\..0000   '%'c                   V ^8  d   QhRR/# r   r!   intr#   )r$   s   "r%   r&   r'   l   s     . . .r(   c                	j   "   V P                   P                  4       G R j  xL
 pVP                  #  L5ir6   )r*   r>   handled_request_countr1   metadatas   & r%   get_handled_countRequestQueue.get_handled_countk   s+     2244--- 5   313c                   V ^8  d   QhRR/# rB   r#   )r$   s   "r%   r&   r'   q   s     , ,s ,r(   c                	j   "   V P                   P                  4       G R j  xL
 pVP                  #  L5ir6   )r*   r>   total_request_countrF   s   & r%   get_total_countRequestQueue.get_total_countp   s+     2244+++ 5rJ   r   Nr   aliasconfigurationstorage_clientc               0    V ^8  d   QhRRRRRRRRRRR	R
/# )r   r   r    r   rP   rQ   zConfiguration | NonerR   zStorageClient | Noner!   r   r#   )r$   s   "r%   r&   r'   w   sH     
 
 
 	

 
 ,
 -
 

r(   c          	     	  "   Vf   \         P                  ! 4       MTpVf   \         P                  ! 4       MTpVP                  WW4R7      pVP	                  VR7      p\         P
                  P                  V VVVVVR7      G R j  xL
 #  L5i)N)r   r   rP   rQ   )rQ   )r   r   rP   client_opener_corostorage_client_cache_key)r
   get_configurationget_storage_clientcreate_rq_clientget_storage_client_cache_keystorage_instance_manageropen_storage_instance)clsr   r   rP   rQ   rR   rU   additional_cache_keys   &$$$$$  r%   openRequestQueue.openu   s      @M?T99;ZgAOAW;;=]k+<<UZ<x-JJYfJg$==SS1%9 T 
 
 	
 
s   BBBBc                   V ^8  d   QhRR/# r   r!   r"   r#   )r$   s   "r%   r&   r'      s     " "D "r(   c                	   "   \         P                  pVP                  V 4       V P                  P	                  4       G R j  xL
  R #  L5ir6   )r
   r[   remove_from_cacher*   drop)r1   r[   s   & r%   re   RequestQueue.drop   s7      $3#K#K  2248ll!!!s   ?A
AA
c                   V ^8  d   QhRR/# rb   r#   )r$   s   "r%   r&   r'      s     # #T #r(   c                	V   "   V P                   P                  4       G R j  xL
  R #  L5ir6   )r*   purger7   s   &r%   ri   RequestQueue.purge   s     ll  """s   )')	forefrontFc               $    V ^8  d   QhRRRRRR/# )r   requestzstr | Requestrk   boolr!   r   r#   )r$   s   "r%   r&   r'      s(     . .. 	.
 
.r(   c               	   "   V P                  V4      pV P                  P                  V.VR 7      G Rj  xL
 pVP                  ^ ,          #  L5i)rk   N)_transform_requestr*   add_batch_of_requestsprocessed_requests)r1   rm   rk   responses   &&$ r%   add_requestRequestQueue.add_request   sM      ))'2;;WIQZ;[[**1-- \s   3AAA
batch_sizei  wait_time_between_batches)seconds!wait_for_all_requests_to_be_added)wait_for_all_requests_to_be_added_timeoutc               4    V ^8  d   QhRRRRRRRRR	RR
RRR/# )r   requestszSequence[str | Request]rk   rn   rw   rC   rx   r   rz   r{   ztimedelta | Noner!   r"   r#   )r$   s   "r%   r&   r'      sQ     0 0)0 	0
 0 $-0 ,00 4D0 
0r(   c               	  a aaaa	a
a"   S P                  V4      o
SP                  4       oS
R S pV'       d   S P                  VSSR7      G R j  xL
  R VVV V
VV3R llp\        P                  ! V! 4       RR7      o	S P
                  P                  S	4       S	P                  V	V 3R l4       V'       d   \        S	3\        VR7      G R j  xL
  R # R #  L L
5i)Nbase_retry_waitrk   c                   V ^8  d   QhRR/# rb   r#   )r$   s   "r%   r&   /RequestQueue.add_requests.<locals>.__annotate__   s     		8 		8$ 		8r(   c                   <"   \        S\        S4      S4       Fa  p SW S,            pSP                  VSSR 7      G Rj  xL
  V S,           \        S4      8  g   KC  \        P                  ! S4      G Rj  xL
  Kc  	  R#  LA L5i)r   N)rangelen_process_batchr.   sleep)ibatchrw   rk   r1   transformed_requestsrx   wait_time_secss     r%   _process_remaining_batches=RequestQueue.add_requests.<locals>._process_remaining_batches   s     :s+?'@*M,QZ@))$=' *   
 z>C(<$==!--777 N 8s(   <BB BB6B7BB,request_queue_process_remaining_batches_task)r   c                :   < SP                   P                  S4      # r6   )r0   remove)_remaining_batches_taskr1   s   &r%   <lambda>+RequestQueue.add_requests.<locals>.<lambda>   s    4;S;S;Z;Z[q;rr(   )loggertimeout)
_transform_requeststotal_secondsr   r.   create_taskr0   appendadd_done_callbackr   r   )r1   r}   rk   rw   rx   rz   r{   first_batchr   r   r   r   s   f&ddd$$  @@@r%   add_requestsRequestQueue.add_requests   s       $77A2@@B +;J7%% 9# &   		8 		8 ")!4!4&(?"

 	  ''(>?001rs -/')A   -78s+   ACCA'C8CC	CCc                   V ^8  d   QhRR/# )r   r!   Request | Noner#   )r$   s   "r%   r&   r'      s     7 7. 7r(   c                R   "   V P                   P                  4       G Rj  xL
 #  L5i)a  Return the next request in the queue to be processed.

Once you successfully finish processing of the request, you need to call `RequestQueue.mark_request_as_handled`
to mark the request as handled in the queue. If there was some error in processing the request, call
`RequestQueue.reclaim_request` instead, so that the queue will give the request to some other consumer
in another call to the `fetch_next_request` method.

Note that the `None` return value does not mean the queue processing finished, it means there are currently
no pending requests. To check whether all requests in queue were finished, use `RequestQueue.is_finished`
instead.

Returns:
    The next request to process, or `None` if there are no more pending requests.
N)r*   fetch_next_requestr7   s   &r%   r   RequestQueue.fetch_next_request   s       \\446666r@   c                    V ^8  d   QhRRRR/# )r   
unique_keyr   r!   r   r#   )r$   s   "r%   r&   r'      s     	: 	:C 	:N 	:r(   c                T   "   V P                   P                  V4      G Rj  xL
 #  L5i)zRetrieve a specific request from the queue by its ID.

Args:
    unique_key: Unique key of the request to retrieve.

Returns:
    The request with the specified ID, or `None` if no such request exists.
N)r*   get_request)r1   r   s   &&r%   r   RequestQueue.get_request   s"      \\--j9999   (&(c                    V ^8  d   QhRRRR/# )r   rm   r	   r!   ProcessedRequest | Noner#   )r$   s   "r%   r&   r'      s     C CW CAX Cr(   c                T   "   V P                   P                  V4      G Rj  xL
 #  L5i)a  Mark a request as handled after successful processing.

This method should be called after a request has been successfully processed.
Once marked as handled, the request will be removed from the queue and will
not be returned in subsequent calls to `fetch_next_request` method.

Args:
    request: The request to mark as handled.

Returns:
    Information about the queue operation.
N)r*   mark_request_as_handled)r1   rm   s   &&r%   r   $RequestQueue.mark_request_as_handled   s"      \\99'BBBBr   c               $    V ^8  d   QhRRRRRR/# )r   rm   r	   rk   rn   r!   r   r#   )r$   s   "r%   r&   r'     s-     P PP 	P
 
!Pr(   c               V   "   V P                   P                  WR7      G Rj  xL
 #  L5i)a  Reclaim a failed request back to the queue for later processing.

If a request fails during processing, this method can be used to return it to the queue.
The request will be returned for processing again in a subsequent call
to `RequestQueue.fetch_next_request`.

Args:
    request: The request to return to the queue.
    forefront: If true, the request will be added to the beginning of the queue.
        Otherwise, it will be added to the end.

Returns:
    Information about the queue operation.
rp   N)r*   reclaim_request)r1   rm   rk   s   &&$r%   r   RequestQueue.reclaim_request  s%     ( \\11'1OOOOs    )')c                   V ^8  d   QhRR/# r   r!   rn   r#   )r$   s   "r%   r&   r'     s     
- 
- 
-r(   c                R   "   V P                   P                  4       G Rj  xL
 #  L5i)at  Check if the request queue is empty.

An empty queue means that there are no requests currently in the queue, either pending or being processed.
However, this does not necessarily mean that the crawling operation is finished, as there still might be
tasks that could add additional requests to the queue.

Returns:
    True if the request queue is empty, False otherwise.
N)r*   is_emptyr7   s   &r%   r   RequestQueue.is_empty  s       \\**,,,,r@   c                   V ^8  d   QhRR/# r   r#   )r$   s   "r%   r&   r'   &  s      4 r(   c                   "   V P                   '       d   \        P                  R4       R# V P                  4       G Rj  xL
 '       d   \        P                  R4       R# R#  L#5i)a  Check if the request queue is finished.

A finished queue means that all requests in the queue have been processed (the queue is empty) and there
are no more tasks that could add additional requests to the queue. This is the definitive way to check
if a crawling operation is complete.

Returns:
    True if the request queue is finished (empty and no pending add operations), False otherwise.
z4Background add requests tasks are still in progress.FNzThe request queue is empty.T)r0   r   debugr   r7   s   &r%   is_finishedRequestQueue.is_finished&  sJ      ###LLOP  LL67	 !s   =A%A# 	A%
A%attemptc          
     ,    V ^8  d   QhRRRRRRRRR	R
/# )r   r   zSequence[Request]r   r   r   rC   rk   rn   r!   r"   r#   )r$   s   "r%   r&   r'   :  s<        #	
   
r(   c               H  "   ^pV P                   P                  WR7      G Rj  xL
 pVP                  '       Ed    \        P	                  RVP                   R24       W58  d'   \        P                  RV RVP                   24       M\        P	                  R4       VP                   Uu0 uF  qwP                  kK  	  ppV Uu. uF  qwP                  V9   g   K  VNK  	  p	p\        P                  ! W#,          P                  4       4      G Rj  xL
  V P                  WV^,           R7      G Rj  xL
  \        V4      \        VP                  4      ,
          p
V
'       d(   \        P	                  R	V
 R
VP                   24       R# R#  ELmu upi u upi  L Li5i)z;Process a batch of requests with automatic retry mechanism.rp   Nz'Following requests were not processed: .z1Following requests were not processed even after z attempts:
zRetry to add requests.)r   r   zAdded z, requests to the queue. Processed requests: )r*   rr   unprocessed_requestsr   r   warningr   r.   r   r   r   r   rs   )r1   r   r   r   rk   max_attemptsrt   rm    unprocessed_requests_unique_keysretry_batchrequest_counts   &&$$$      r%   r   RequestQueue._process_batch:  sh     ;;E;WW(((LLB8C`C`Baabcd%G~Ua4457
 56V^VsVs3tVs74F4FVs03t6;ve7?Q?QUu?uwwevmm_%>$M$M$OPPP))+`gjk`k)lllE
S)F)F%GGLL'ST\ToToSpq % X 4uvPlsX   "F"FF"A2F".FF"FF%/F"F!F"6F 7AF"F" F")r0   r*   r+   r,   )__name__
__module____qualname____firstlineno____doc__r2   propertyr   r   r   r>   rH   rN   classmethodr_   re   ri   ru   r   r   r   r   r   r   r   r   r   __static_attributes__r#   r(   r%   r   r       s   &P@&       1 1 . . , , 
 
  	

 !
 /3
 04
  
0 " " # # .  	. . 0  	0
 0 09/C0 380 GK0 0d7"	:CP  	P,
-(
    r(   r   )(
__future__r   r.   datetimer   loggingr   typingr   r   typing_extensionsr   crawleer	   r
   crawlee._utils.docsr   crawlee._utils.waitr   crawlee.request_loadersr   _baser   _utilsr   collections.abcr   crawlee.configurationr   crawlee.storage_clientsr   crawlee.storage_clients._baser   crawlee.storage_clients.modelsr   r   r   r   r   r   r#   r(   r%   <module>r      sv    "    ) & , * = 2  )(35@U	8	CL Jx7N x xr(   