22from typing import List , Generator , Any
33import queue
44import time
5- from cloudquery .sdk .schema import Table
5+ from cloudquery .sdk .schema import Table , Resource
66from cloudquery .sdk .message import SyncMessage , SyncInsertMessage , SyncMigrateMessage
7- import concurrent . futures
7+ from concurrent import futures
88from typing import Generator
9-
10- # This is all WIP
11- class Task :
12- def __init__ (self , fetcher , parent_item ):
13- self ._fetcher = fetcher
14- self ._parent_item = parent_item
15-
16- class Item :
17- def __init__ (self , fetcher , parent_item ):
18- self ._fetcher = fetcher
19- self ._parent_item = parent_item
20-
21- class Fetcher :
22- def __init__ (self , relations : List [Any ]):
23- self ._relations = relations
24-
25- def get (self , parent_item ) -> Generator [SyncInsertMessage ]:
26- for i in range (10 ):
27- yield SyncInsertMessage (None )
28-
29- def process_item (self , item : Any ) -> Generator [SyncInsertMessage ]:
30- pass
31-
32- def transform_item (self , item : Any ) -> Any :
33- pass
34-
35-
36- def worker (fetcher : Fetcher , parent_item : Any ):
37- for arr in fetcher .get (parent_item ):
38- for res in arr :
39- fetcher .get ()
40-
41- # while True:
42- # item = q.get()
43- # if item is None:
44- # break
45- # do_work(item)
46- # q.task_done()
47-
48- def worker_task (q , worker_id ):
49- for i in range (5 ):
50- time .sleep (0.1 ) # Simulate work
51- task = (worker_id , i )
52- print (f"Worker { worker_id } created task { task } " )
53- q .put (task )
54-
55- def main_task (q : queue .Queue ):
56- with concurrent .futures .ThreadPoolExecutor (max_workers = 5 ) as executor :
57- while True :
58- try :
59- task = q .get (timeout = 1 ) # Wait up to 1 second for a task.
60- except queue .Empty :
61- print ("All tasks completed." )
62- break # Exit while loop if no more tasks.
63- print (f"Main: Running task { task } " )
64- executor .submit (run_task , task )
65- q .task_done ()
66-
67- def run_task (task ):
68-
69- print (f"Running task { task } " )
70-
9+ from .table_resolver import TableResolver
7110
7211QUEUE_PER_WORKER = 100
7312
13+ class ThreadPoolExecutorWithQueueSizeLimit (futures .ThreadPoolExecutor ):
14+ def __init__ (self , maxsize , * args , ** kwargs ):
15+ super (ThreadPoolExecutorWithQueueSizeLimit , self ).__init__ (* args , ** kwargs )
16+ self ._work_queue = queue .Queue (maxsize = maxsize )
17+
7418class Scheduler :
7519 def __init__ (self , concurrency : int , queue_size : int = 0 , max_depth : int = 3 ):
7620 self ._queue = queue .Queue ()
@@ -82,33 +26,50 @@ def __init__(self, concurrency: int, queue_size: int = 0, max_depth : int = 3):
8226 if max_depth <= 0 :
8327 raise ValueError ("max_depth must be greater than 0" )
8428 self ._queue_size = queue_size if queue_size > 0 else concurrency * QUEUE_PER_WORKER
85- self ._pools = []
86- self ._queues = []
29+ self ._pools : List [ThreadPoolExecutorWithQueueSizeLimit ] = []
8730 current_depth_concurrency = concurrency
8831 current_depth_queue_size = queue_size
89- for i in range (max_depth + 1 ):
90- self ._queues .append (queue .Queue (maxsize = current_depth_queue_size ))
91- self ._pools .append (concurrent .futures .ThreadPoolExecutor (max_workers = current_depth_concurrency ))
32+ for _ in range (max_depth + 1 ):
33+ self ._pools .append (ThreadPoolExecutorWithQueueSizeLimit (maxsize = current_depth_queue_size ,max_workers = current_depth_concurrency ))
9234 current_depth_concurrency = current_depth_concurrency // 2 if current_depth_concurrency > 1 else 1
9335 current_depth_queue_size = current_depth_queue_size // 2 if current_depth_queue_size > 1 else 1
9436
95- def worker (self , max_depth : int ):
96- while True :
97- task = self ._queues [max_depth ].get ()
98- if task is None :
99- break
100- self ._pools [max_depth ].submit (* task )
101-
102- def table_resolver (self , table : Table , client , res : queue .Queue ):
103- for resource in table .resolve (client ):
104- pass
105- # task.resolve
37+ def resolve_resource (self , resolver : TableResolver , client , parent : Resource , item : Any ) -> Resource :
38+ resource = Resource (resolver .table , None , item )
39+ resolver .pre_resource_resolve (client , resource )
40+ for column in resolver .table .columns :
41+ resolver .resolve_column (client , resource , column .name )
42+ resolver .post_resource_resolve (client , resource )
43+ return resource
44+
45+ def resolve_table (self , resolver : TableResolver , client , parent_item : Any , res : queue .Queue ):
46+ for item in resolver .resolve (client , parent_item ):
47+ resource = self .resolve_resource (resolver , client , parent_item )
48+ res .put (SyncInsertMessage (resource ))
49+ res .put (None )
10650
107- def sync (self , client , tables : List [Table ], res : queue .Queue , deterministic_cq_id = False ):
108- for table in tables :
109- res .put (SyncMigrateMessage (record = table .to_arrow_schemas ()))
110- for table in tables :
111- clients = table .multiplex (client )
112- for client in clients :
113- self ._queues [0 ].put ((table .resolver , client , res ))
114- self ._queues [0 ].put (None )
51+ def _sync (self , client , resolvers : List [TableResolver ], res : queue .Queue , deterministic_cq_id = False ):
52+ internal_res = queue .Queue ()
53+ for resolver in resolvers :
54+ clients = resolver .multiplex (client )
55+ for client in clients :
56+ self ._pools [0 ].submit (self .resolve_table , resolver , client , None , internal_res )
57+ while True :
58+ message = internal_res .get ()
59+ if message is None :
60+ break
61+ res .put (message )
62+ res .put (None )
63+
64+ def sync (self , client , resolvers : List [TableResolver ], deterministic_cq_id = False ) -> Generator [SyncMessage ]:
65+ res = queue .Queue ()
66+ for resolver in resolvers :
67+ yield SyncMigrateMessage (record = resolver .table .to_arrow_schemas ())
68+ thread = futures .ThreadPoolExecutor ()
69+ thread .submit (self ._sync , client , resolvers , res , deterministic_cq_id )
70+ while True :
71+ message = res .get ()
72+ if message is None :
73+ break
74+ yield message
75+ thread .shutdown ()
0 commit comments