8686import org .apache .pinot .spi .utils .CommonConstants .Helix ;
8787import org .apache .pinot .spi .utils .CommonConstants .MultiStageQueryRunner ;
8888import org .apache .pinot .spi .utils .CommonConstants .MultiStageQueryRunner .JoinOverFlowMode ;
89+ import org .apache .pinot .spi .utils .CommonConstants .MultiStageQueryRunner .TimeoutOverflowMode ;
8990import org .apache .pinot .spi .utils .CommonConstants .MultiStageQueryRunner .WindowOverFlowMode ;
9091import org .apache .pinot .spi .utils .CommonConstants .Query .Request ;
9192import org .apache .pinot .spi .utils .CommonConstants .Query .Response ;
107108 */
108109public class QueryRunner {
109110 private static final Logger LOGGER = LoggerFactory .getLogger (QueryRunner .class );
111+ private static final double DEFAULT_LEAF_TIMEOUT_RATIO = 0.8 ;
110112
111113 private ExecutorService _executorService ;
112114 private OpChainSchedulerService _opChainScheduler ;
@@ -138,6 +140,8 @@ public class QueryRunner {
138140 @ Nullable
139141 private WindowOverFlowMode _windowOverflowMode ;
140142 @ Nullable
143+ private TimeoutOverflowMode _timeoutOverflowMode ;
144+ @ Nullable
141145 private PhysicalTimeSeriesServerPlanVisitor _timeSeriesPhysicalPlanVisitor ;
142146 private BooleanSupplier _sendStats ;
143147
@@ -191,6 +195,10 @@ public void init(PinotConfiguration serverConf, InstanceDataManager instanceData
191195 String windowOverflowModeStr = serverConf .getProperty (MultiStageQueryRunner .KEY_OF_WINDOW_OVERFLOW_MODE );
192196 _windowOverflowMode = windowOverflowModeStr != null ? WindowOverFlowMode .valueOf (windowOverflowModeStr ) : null ;
193197
198+ String timeoutOverflowModeStr = serverConf .getProperty (MultiStageQueryRunner .KEY_OF_TIMEOUT_OVERFLOW_MODE );
199+ _timeoutOverflowMode =
200+ timeoutOverflowModeStr != null ? TimeoutOverflowMode .valueOf (timeoutOverflowModeStr ) : null ;
201+
194202 ExecutorService baseExecutorService =
195203 ExecutorServiceUtils .create (serverConf , Server .MULTISTAGE_EXECUTOR_CONFIG_PREFIX , "query-runner-on-" + port ,
196204 Server .DEFAULT_MULTISTAGE_EXECUTOR_TYPE );
@@ -271,6 +279,7 @@ private void processQueryBlocking(WorkerMetadata workerMetadata, StagePlan stage
271279 Map <String , String > requestMetadata ) {
272280 StageMetadata stageMetadata = stagePlan .getStageMetadata ();
273281 Map <String , String > opChainMetadata = consolidateMetadata (stageMetadata .getCustomProperties (), requestMetadata );
282+ applyLeafDeadlineOverrides (workerMetadata , opChainMetadata );
274283
275284 // run pre-stage execution for all pipeline breakers
276285 PipelineBreakerResult pipelineBreakerResult =
@@ -508,9 +517,64 @@ private Map<String, String> consolidateMetadata(Map<String, String> customProper
508517 opChainMetadata .put (QueryOptionKey .WINDOW_OVERFLOW_MODE , windowOverflowMode .name ());
509518 }
510519
520+ TimeoutOverflowMode timeoutOverflowMode = QueryOptionsUtils .getTimeoutOverflowMode (opChainMetadata );
521+ if (timeoutOverflowMode == null ) {
522+ timeoutOverflowMode = _timeoutOverflowMode ;
523+ }
524+ if (timeoutOverflowMode != null ) {
525+ opChainMetadata .put (QueryOptionKey .TIMEOUT_OVERFLOW_MODE , timeoutOverflowMode .name ());
526+ }
527+
511528 return opChainMetadata ;
512529 }
513530
531+ private void applyLeafDeadlineOverrides (WorkerMetadata workerMetadata , Map <String , String > opChainMetadata ) {
532+ if (!workerMetadata .isLeafStageWorker ()) {
533+ return ;
534+ }
535+ Long leafTimeoutMs = QueryOptionsUtils .getLeafTimeoutMs (opChainMetadata );
536+ Long leafExtraPassiveTimeoutMs = QueryOptionsUtils .getLeafExtraPassiveTimeoutMs (opChainMetadata );
537+ TimeoutOverflowMode timeoutOverflowMode = _timeoutOverflowMode ;
538+ String timeoutOverflowModeStr = opChainMetadata .get (QueryOptionKey .TIMEOUT_OVERFLOW_MODE );
539+ if (timeoutOverflowModeStr != null ) {
540+ try {
541+ timeoutOverflowMode = TimeoutOverflowMode .valueOf (timeoutOverflowModeStr );
542+ } catch (IllegalArgumentException e ) {
543+ LOGGER .warn ("Invalid timeout overflow mode: {}" , timeoutOverflowModeStr , e );
544+ }
545+ }
546+ QueryThreadContext threadContext = QueryThreadContext .getIfAvailable ();
547+ if (threadContext == null ) {
548+ return ;
549+ }
550+ QueryExecutionContext executionContext = threadContext .getExecutionContext ();
551+ long startTimeMs = executionContext .getStartTimeMs ();
552+ if (leafTimeoutMs == null && timeoutOverflowMode == TimeoutOverflowMode .BREAK ) {
553+ long globalActiveWindowMs = Math .max (1L , executionContext .getActiveDeadlineMs () - startTimeMs );
554+ leafTimeoutMs = Math .max (1L , (long ) Math .floor (globalActiveWindowMs * DEFAULT_LEAF_TIMEOUT_RATIO ));
555+ }
556+ if (leafExtraPassiveTimeoutMs == null && timeoutOverflowMode == TimeoutOverflowMode .BREAK ) {
557+ long globalPassiveWindowMs =
558+ Math .max (0L , executionContext .getPassiveDeadlineMs () - executionContext .getActiveDeadlineMs ());
559+ leafExtraPassiveTimeoutMs =
560+ Math .max (0L , (long ) Math .floor (globalPassiveWindowMs * DEFAULT_LEAF_TIMEOUT_RATIO ));
561+ }
562+ if (leafTimeoutMs == null && leafExtraPassiveTimeoutMs == null ) {
563+ return ;
564+ }
565+ long activeDeadlineMs = executionContext .getActiveDeadlineMs ();
566+ long passiveDeadlineMs = executionContext .getPassiveDeadlineMs ();
567+ if (leafTimeoutMs != null ) {
568+ activeDeadlineMs = Math .min (activeDeadlineMs , startTimeMs + leafTimeoutMs );
569+ }
570+ if (leafExtraPassiveTimeoutMs != null ) {
571+ passiveDeadlineMs = Math .min (passiveDeadlineMs , activeDeadlineMs + leafExtraPassiveTimeoutMs );
572+ }
573+ passiveDeadlineMs = Math .max (passiveDeadlineMs , activeDeadlineMs );
574+ opChainMetadata .put (LeafOperator .LEAF_ACTIVE_DEADLINE_METADATA_KEY , Long .toString (activeDeadlineMs ));
575+ opChainMetadata .put (LeafOperator .LEAF_PASSIVE_DEADLINE_METADATA_KEY , Long .toString (passiveDeadlineMs ));
576+ }
577+
514578 public Map <Integer , MultiStageQueryStats .StageStats .Closed > cancel (long requestId ) {
515579 return _opChainScheduler .cancel (requestId );
516580 }
@@ -524,6 +588,7 @@ public StagePlan explainQuery(WorkerMetadata workerMetadata, StagePlan stagePlan
524588
525589 StageMetadata stageMetadata = stagePlan .getStageMetadata ();
526590 Map <String , String > opChainMetadata = consolidateMetadata (stageMetadata .getCustomProperties (), requestMetadata );
591+ applyLeafDeadlineOverrides (workerMetadata , opChainMetadata );
527592
528593 if (PipelineBreakerExecutor .hasPipelineBreakers (stagePlan )) {
529594 //TODO: See https://github.com/apache/pinot/pull/13733#discussion_r1752031714
0 commit comments