@@ -7,10 +7,13 @@ use crate::{
77 worker:: { client:: WorkerClient , wft_poller_behavior} ,
88} ;
99use futures_util:: { Stream , stream} ;
10- use std:: sync:: { Arc , OnceLock } ;
10+ use std:: sync:: {
11+ Arc , OnceLock ,
12+ atomic:: { AtomicBool , Ordering } ,
13+ } ;
1114use temporal_sdk_core_api:: worker:: { WorkerConfig , WorkflowSlotKind } ;
1215use temporal_sdk_core_protos:: temporal:: api:: workflowservice:: v1:: PollWorkflowTaskQueueResponse ;
13- use tokio:: sync:: watch;
16+ use tokio:: sync:: { Notify , watch} ;
1417use tokio_util:: sync:: CancellationToken ;
1518
1619pub ( crate ) fn make_wft_poller (
@@ -74,6 +77,8 @@ pub(crate) struct WFTPollerShared {
7477 last_seen_sticky_backlog : ( watch:: Receiver < usize > , watch:: Sender < usize > ) ,
7578 sticky_active : OnceLock < watch:: Receiver < usize > > ,
7679 non_sticky_active : OnceLock < watch:: Receiver < usize > > ,
80+ wait_for_first_nonsticky_poll : Notify ,
81+ have_done_first_poll : AtomicBool ,
7782}
7883impl WFTPollerShared {
7984 pub ( crate ) fn new ( ) -> Self {
@@ -82,6 +87,8 @@ impl WFTPollerShared {
8287 last_seen_sticky_backlog : ( rx, tx) ,
8388 sticky_active : OnceLock :: new ( ) ,
8489 non_sticky_active : OnceLock :: new ( ) ,
90+ wait_for_first_nonsticky_poll : Notify :: new ( ) ,
91+ have_done_first_poll : AtomicBool :: new ( false ) ,
8592 }
8693 }
8794 pub ( crate ) fn set_sticky_active ( & self , rx : watch:: Receiver < usize > ) {
@@ -93,15 +100,24 @@ impl WFTPollerShared {
93100 /// Makes either the sticky or non-sticky poller wait pre-permit-acquisition so that we can
94101 /// balance which kind of queue we poll appropriately.
95102 pub ( crate ) async fn wait_if_needed ( & self , is_sticky : bool ) {
103+ // Sticky shouldn't start polling until after the first non-sticky poll has been allowed
104+ if is_sticky {
105+ self . wait_for_first_nonsticky_poll . notified ( ) . await ;
106+ }
107+ info ! (
108+ "Waiting if needed. Sticky: {} / backlog {}" ,
109+ is_sticky,
110+ * self . last_seen_sticky_backlog. 0 . borrow( )
111+ ) ;
96112 // If there's a sticky backlog, prioritize it.
97113 if !is_sticky {
98114 let backlog = * self . last_seen_sticky_backlog . 0 . borrow ( ) ;
99- if backlog > 1 {
115+ if backlog >= 1 {
100116 let _ = self
101117 . last_seen_sticky_backlog
102118 . 0
103119 . clone ( )
104- . wait_for ( |v| * v <= 1 )
120+ . wait_for ( |v| * v < 1 )
105121 . await ;
106122 }
107123 }
@@ -111,6 +127,12 @@ impl WFTPollerShared {
111127 if let Some ( ( sticky_active, non_sticky_active) ) =
112128 self . sticky_active . get ( ) . zip ( self . non_sticky_active . get ( ) )
113129 {
130+ info ! (
131+ "Balance (sticky {}), non-sticky {} sticky {}" ,
132+ is_sticky,
133+ * non_sticky_active. borrow( ) ,
134+ * sticky_active. borrow( )
135+ ) ;
114136 if is_sticky {
115137 let _ = sticky_active
116138 . clone ( )
@@ -119,9 +141,13 @@ impl WFTPollerShared {
119141 } else {
120142 let _ = non_sticky_active
121143 . clone ( )
122- . wait_for ( |v| * v <= * sticky_active. borrow ( ) )
144+ . wait_for ( |v| {
145+ * v < * sticky_active. borrow ( )
146+ || !self . have_done_first_poll . load ( Ordering :: Relaxed )
147+ } )
123148 . await ;
124149 }
150+ info ! ( "Done balance (sticky {})" , is_sticky) ;
125151 }
126152 }
127153 }
0 commit comments