33from asyncio import Lock as aioLock
44from collections .abc import Iterable
55from typing import Union , TYPE_CHECKING
6+ from collections import deque
67if TYPE_CHECKING :
78 from .connections import AsyncConnectionWrapper
89 from cx_Oracle import Queue
@@ -60,34 +61,68 @@ def __init__(self , loop : 'ProactorEventLoop' , thread_pool : ThreadPoolExecuto
6061 self ._thread_pool = thread_pool
6162 self ._queue = queue
6263 self ._count = 0
63- self ._max = maxMessages if maxMessages > - 1 else (1 << 16 - 1 )
64- self ._max = self ._max if self ._max <= (1 << 16 - 1 ) else (1 << 16 - 1 )
64+ self ._max_messages = maxMessages
6565 self ._deqlock = deqlock
66+ self ._buffer = deque ()
67+ self ._soft_max = ((1 << 16 ) - 1 )
68+ self ._max_limit = maxMessages if maxMessages > - 1 else self ._soft_max
69+ self ._max_limit = self ._max_limit if self ._max_limit <= self ._soft_max else self ._soft_max
70+ self ._deqcount = 0
71+ self ._closed = False
72+
73+ @property
74+ def _fetch_num (self ):
75+ return self ._soft_max if self ._max_messages < 0 else min (self ._max_limit , self ._max_messages - self ._deqcount )
6676
6777 def __await__ (self ):
78+ if self ._closed :
79+ raise RuntimeError ('Current query has closed , you cannot activate it twice.' )
6880 yield from self ._deqlock .acquire ().__await__ ()
6981 try :
70- ret = yield from self ._loop .run_in_executor (self ._thread_pool , self ._queue .deqMany , self ._max ).__await__ ()
82+ ret = yield from self ._loop .run_in_executor (self ._thread_pool , self ._queue .deqMany , self ._fetch_num ).__await__ ()
7183 except Exception as exc :
7284 raise exc
7385 finally :
7486 self ._deqlock .release ()
87+ self ._closed = True
7588 return ret
7689
7790 def __aiter__ (self ):
7891 return self
7992
8093 async def __anext__ (self ):
81- self ._count += 1
82- if self ._count <= self ._max :
83- _tmp = self ._queue .deqOptions .wait
84- async with self ._deqlock :
94+ if self ._closed :
95+ raise RuntimeError ('Current query has closed , you cannot activate it twice.' )
96+
97+ if self ._max_messages == 0 :
98+ self ._closed = True
99+ raise StopAsyncIteration
100+
101+ # Fetch off
102+ if self ._max_messages > 0 and self ._deqcount >= self ._max_messages :
103+ if self ._buffer :
104+ return self ._buffer .popleft ()
105+ self ._closed = True
106+ raise StopAsyncIteration
107+
108+ # Fetch on
109+ if self ._buffer :
110+ return self ._buffer .popleft ()
111+ _tmp = self ._queue .deqOptions .wait
112+ async with self ._deqlock :
113+ try :
85114 self ._queue .deqOptions .wait = DEQ_NO_WAIT
86- data = await self ._loop .run_in_executor (self ._thread_pool , self ._queue .deqOne )
115+ data = await self ._loop .run_in_executor (self ._thread_pool , self ._queue .deqMany , self ._fetch_num )
116+ except Exception as exc :
117+ raise exc
118+ finally :
87119 self ._queue .deqOptions .wait = _tmp
120+
88121 if data :
89- return data
90- else :
91- raise StopAsyncIteration
92- else :
122+ self ._buffer .extend (data )
123+ self ._deqcount += len (data )
124+ return self ._buffer .popleft ()
125+
126+ # No data return , close iteration.
127+ self ._closed = True
93128 raise StopAsyncIteration
0 commit comments