@@ -24,6 +24,7 @@ import (
24
24
"context"
25
25
"math/rand"
26
26
"strings"
27
+ "time"
27
28
28
29
"go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"
29
30
"go.uber.org/cadence/.gen/go/shadower"
@@ -46,6 +47,12 @@ const (
46
47
workflowReplayerContextKey contextKey = "workflowReplayer"
47
48
)
48
49
50
+ const (
51
+ minScanWorkflowResultSize = 10
52
+ ratioToCompleteScanWorkflow = 0.8
53
+ scanWorkflowWaitPeriod = 100 * time .Millisecond
54
+ )
55
+
49
56
func scanWorkflowActivity (
50
57
ctx context.Context ,
51
58
params shadower.ScanWorkflowActivityParams ,
@@ -69,6 +76,12 @@ func scanWorkflowExecutionsHelper(
69
76
params shadower.ScanWorkflowActivityParams ,
70
77
logger * zap.Logger ,
71
78
) (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
+ }
72
85
73
86
request := & shared.ListWorkflowExecutionsRequest {
74
87
Domain : params .Domain ,
@@ -77,39 +90,48 @@ func scanWorkflowExecutionsHelper(
77
90
PageSize : params .PageSize ,
78
91
}
79
92
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 ()
101
103
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
106
115
}
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 )
107
132
}
108
133
109
- return shadower.ScanWorkflowActivityResult {
110
- Executions : executions ,
111
- NextPageToken : resp .NextPageToken ,
112
- }, nil
134
+ return result , nil
113
135
}
114
136
115
137
func shouldReplay (probability float64 ) bool {
0 commit comments