@@ -24,6 +24,7 @@ import (
2424 "context"
2525 "math/rand"
2626 "strings"
27+ "time"
2728
2829 "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"
2930 "go.uber.org/cadence/.gen/go/shadower"
@@ -46,6 +47,12 @@ const (
4647 workflowReplayerContextKey contextKey = "workflowReplayer"
4748)
4849
50+ const (
51+ minScanWorkflowResultSize = 10
52+ ratioToCompleteScanWorkflow = 0.8
53+ scanWorkflowWaitPeriod = 100 * time .Millisecond
54+ )
55+
4956func scanWorkflowActivity (
5057 ctx context.Context ,
5158 params shadower.ScanWorkflowActivityParams ,
@@ -69,6 +76,12 @@ func scanWorkflowExecutionsHelper(
6976 params shadower.ScanWorkflowActivityParams ,
7077 logger * zap.Logger ,
7178) (shadower.ScanWorkflowActivityResult , error ) {
79+ var completionTime time.Time
80+ if deadline , ok := ctx .Deadline (); ok {
81+ now := time .Now ()
82+ activityTimeout := deadline .Sub (now )
83+ completionTime = now .Add (time .Duration (ratioToCompleteScanWorkflow * float32 (activityTimeout )))
84+ }
7285
7386 request := & shared.ListWorkflowExecutionsRequest {
7487 Domain : params .Domain ,
@@ -77,39 +90,48 @@ func scanWorkflowExecutionsHelper(
7790 PageSize : params .PageSize ,
7891 }
7992
80- var resp * shared.ListWorkflowExecutionsResponse
81- if err := backoff .Retry (ctx ,
82- func () error {
83- tchCtx , cancel , opt := newChannelContext (ctx )
84-
85- var err error
86- resp , err = service .ScanWorkflowExecutions (tchCtx , request , opt ... )
87- cancel ()
88-
89- return err
90- },
91- createDynamicServiceRetryPolicy (ctx ),
92- isServiceTransientError ,
93- ); err != nil {
94- logger .Error ("Failed to scan workflow executions" ,
95- zap .String (tagDomain , params .GetDomain ()),
96- zap .String (tagVisibilityQuery , params .GetWorkflowQuery ()),
97- zap .Error (err ),
98- )
99- return shadower.ScanWorkflowActivityResult {}, err
100- }
93+ result := shadower.ScanWorkflowActivityResult {}
94+ for {
95+ var resp * shared.ListWorkflowExecutionsResponse
96+ if err := backoff .Retry (ctx ,
97+ func () error {
98+ tchCtx , cancel , opt := newChannelContext (ctx )
99+
100+ var err error
101+ resp , err = service .ScanWorkflowExecutions (tchCtx , request , opt ... )
102+ cancel ()
101103
102- executions := make ([]* shared.WorkflowExecution , 0 , len (resp .Executions ))
103- for _ , execution := range resp .Executions {
104- if shouldReplay (params .GetSamplingRate ()) {
105- executions = append (executions , execution .Execution )
104+ return err
105+ },
106+ createDynamicServiceRetryPolicy (ctx ),
107+ isServiceTransientError ,
108+ ); err != nil {
109+ logger .Error ("Failed to scan workflow executions" ,
110+ zap .String (tagDomain , params .GetDomain ()),
111+ zap .String (tagVisibilityQuery , params .GetWorkflowQuery ()),
112+ zap .Error (err ),
113+ )
114+ return shadower.ScanWorkflowActivityResult {}, err
106115 }
116+
117+ for _ , execution := range resp .Executions {
118+ if shouldReplay (params .GetSamplingRate ()) {
119+ result .Executions = append (result .Executions , execution .Execution )
120+ }
121+ }
122+
123+ request .NextPageToken = resp .NextPageToken
124+ if len (request .NextPageToken ) == 0 ||
125+ len (result .Executions ) >= minScanWorkflowResultSize ||
126+ (! completionTime .IsZero () && time .Now ().After (completionTime )) {
127+ result .NextPageToken = request .NextPageToken
128+ break
129+ }
130+
131+ time .Sleep (scanWorkflowWaitPeriod )
107132 }
108133
109- return shadower.ScanWorkflowActivityResult {
110- Executions : executions ,
111- NextPageToken : resp .NextPageToken ,
112- }, nil
134+ return result , nil
113135}
114136
115137func shouldReplay (probability float64 ) bool {
0 commit comments