@@ -2742,6 +2742,24 @@ def _fresh_owner_envelope(
27422742 }
27432743
27442744
2745+ def _materialize_owner_projection (
2746+ self , params : Mapping [str , Any ],
2747+ ) -> tuple [tuple [int , int , int , int ], float | None , dict [str , Any ]]:
2748+ version , valid_until , envelope = self ._owners_result (params )
2749+ view_key = self ._owner_view_key (params )
2750+ with self ._frame_lock :
2751+ self ._owner_result_revision += 1
2752+ envelope = {** envelope , "revision" : self ._owner_result_revision }
2753+ ready = (version , valid_until , envelope )
2754+ self ._owner_results [view_key ] = ready
2755+ self ._owner_results .move_to_end (view_key )
2756+ self ._owner_last_started [view_key ] = time .monotonic ()
2757+ while len (self ._owner_results ) > 64 :
2758+ stale_view , _ = self ._owner_results .popitem (last = False )
2759+ if ("owners" , stale_view ) not in self ._frame_futures :
2760+ self ._owner_last_started .pop (stale_view , None )
2761+ return ready
2762+
27452763 def _owner_projection (
27462764 self , raw_params : Mapping [str , Any ], * , wait : bool ,
27472765 ) -> dict [str , Any ] | None :
@@ -2757,29 +2775,17 @@ def _owner_projection(
27572775 ] | None = None
27582776 pending : Future | None = None
27592777 delay = 0.0
2778+ leader = False
27602779 failure : BaseException | None = None
27612780 with self ._frame_lock :
27622781 pending = self ._frame_futures .get (future_key )
27632782 if pending is not None and pending .done ():
27642783 self ._frame_futures .pop (future_key , None )
27652784 try :
2766- version , valid_until , envelope = pending .result ()
2785+ ready = pending .result ()
27672786 except BaseException as exc :
27682787 failure = exc
27692788 else :
2770- self ._owner_result_revision += 1
2771- envelope = {
2772- ** envelope ,
2773- "revision" : self ._owner_result_revision ,
2774- }
2775- ready = (version , valid_until , envelope )
2776- self ._owner_results [view_key ] = ready
2777- self ._owner_results .move_to_end (view_key )
2778- self ._owner_last_started [view_key ] = time .monotonic ()
2779- while len (self ._owner_results ) > 64 :
2780- stale_view , _ = self ._owner_results .popitem (last = False )
2781- if ("owners" , stale_view ) not in self ._frame_futures :
2782- self ._owner_last_started .pop (stale_view , None )
27832789 pending = None
27842790 if failure is None :
27852791 cached = self ._owner_results .get (view_key )
@@ -2810,13 +2816,30 @@ def _owner_projection(
28102816 earliest = self ._owner_last_started .get (view_key , 0.0 ) + 1.0
28112817 delay = max (0.0 , earliest - now )
28122818 if delay == 0.0 :
2813- pending = self ._frame_executor .submit (
2814- self ._owners_result , dict (params ),
2815- )
2819+ if wait and ready is None :
2820+ pending = Future ()
2821+ leader = True
2822+ else :
2823+ pending = self ._frame_executor .submit (
2824+ self ._materialize_owner_projection , dict (params ),
2825+ )
28162826 self ._frame_futures [future_key ] = pending
28172827 self ._owner_last_started [view_key ] = now
28182828 if failure is not None :
28192829 raise failure
2830+ if leader :
2831+ assert pending is not None
2832+ try :
2833+ pending .set_result (self ._materialize_owner_projection (params ))
2834+ except BaseException as exc :
2835+ pending .set_exception (exc )
2836+ if ready is None and wait and pending is not None :
2837+ try :
2838+ ready = pending .result ()
2839+ finally :
2840+ with self ._frame_lock :
2841+ if self ._frame_futures .get (future_key ) is pending :
2842+ self ._frame_futures .pop (future_key , None )
28202843 if ready is not None :
28212844 version , _valid_until , envelope = ready
28222845 # Continuous appends cannot starve completed, qualified snapshots.
@@ -2832,15 +2855,6 @@ def _owner_projection(
28322855 return fresh
28332856 if not wait :
28342857 return None
2835- if pending is not None :
2836- try :
2837- pending .result ()
2838- except BaseException :
2839- with self ._frame_lock :
2840- if self ._frame_futures .get (future_key ) is pending :
2841- self ._frame_futures .pop (future_key , None )
2842- raise
2843- continue
28442858 if delay :
28452859 time .sleep (delay )
28462860
0 commit comments