@@ -6,50 +6,83 @@ import (
6
6
"github.com/turbot/go-kit/helpers"
7
7
)
8
8
9
+ // HydrateData :: the input data passed to every hydrate function
9
10
type HydrateData struct {
10
11
Item interface {}
11
- Params map [string ]string
12
12
HydrateResults map [string ]interface {}
13
13
}
14
14
15
- // perform shallow clone
16
- func (h * HydrateData ) Clone () * HydrateData {
17
- return & HydrateData {
18
- Item : h .Item ,
19
- Params : h .Params ,
20
- HydrateResults : h .HydrateResults ,
21
- }
22
- }
23
-
24
- // HydrateFunc is a function which retrieves some or all row data for a single row item.
15
+ // HydrateFunc :: a function which retrieves some or all row data for a single row item.
25
16
type HydrateFunc func (context.Context , * QueryData , * HydrateData ) (interface {}, error )
26
17
27
18
// HydrateDependencies :: define the hydrate function dependencies - other hydrate functions which must be run first
19
+ // Deprecated: used HydrateConfig
28
20
type HydrateDependencies struct {
29
21
Func HydrateFunc
30
22
Depends []HydrateFunc
31
23
}
32
24
25
+ // HydrateConfig :: define the hydrate function configurations, Name, Maximum number of concurrent calls to be allowed, dependencies
26
+ type HydrateConfig struct {
27
+ Func HydrateFunc
28
+ MaxConcurrency int
29
+ // ConcurrencyMapKey ConcurrencyMapKeyFunc
30
+ // ShouldRetryError ErrorPredicate
31
+ // ShouldIgnoreError ErrorPredicate
32
+ Depends []HydrateFunc
33
+ }
34
+
35
+ // DefaultHydrateConfig :: plugin levelk config to define default hydrate concurrency
36
+ // - used if no HydrateConfig is specified for a specific call
37
+ type DefaultHydrateConfig struct {
38
+ // max number of ALL hydrate calls in progress
39
+ MaxConcurrency int
40
+ DefaultMaxConcurrencyPerCall int
41
+ }
42
+
43
+ // HydrateCall :: struct encapsulating a hydrate call, its config and dependencies
33
44
type HydrateCall struct {
34
45
Func HydrateFunc
35
46
// the dependencies expressed using function name
36
47
Depends []string
48
+ Config * HydrateConfig
37
49
}
38
50
39
- func newHydrateCall (hydrateFunc HydrateFunc , dependencies [] HydrateFunc ) * HydrateCall {
40
- res := & HydrateCall {Func : hydrateFunc }
41
- for _ , f := range dependencies {
51
+ func newHydrateCall (hydrateFunc HydrateFunc , config * HydrateConfig ) * HydrateCall {
52
+ res := & HydrateCall {Func : hydrateFunc , Config : config }
53
+ for _ , f := range config . Depends {
42
54
res .Depends = append (res .Depends , helpers .GetFunctionName (f ))
43
55
}
44
56
return res
45
57
}
46
58
47
- // CanStart :: can this hydrate call - check whether all dependency hydrate functions have been completed
48
- func (h HydrateCall ) CanStart (rowData * RowData ) bool {
59
+ // CanStart :: return whether this hydrate call can execute
60
+ // - check whether all dependency hydrate functions have been completed
61
+ // - check whether the concurrency limits would be exceeded
62
+
63
+ func (h HydrateCall ) CanStart (rowData * RowData , name string , concurrencyManager * ConcurrencyManager ) bool {
49
64
for _ , dep := range h .Depends {
50
65
if ! helpers .StringSliceContains (rowData .getHydrateKeys (), dep ) {
51
66
return false
52
67
}
53
68
}
54
- return true
69
+ // ask the concurrency manager whether the call can start
70
+ // NOTE: if the call is allowed to start, the concurrency manager ASSUMES THE CALL WILL START
71
+ // and increments the counters
72
+ // it may seem more logical to do this in the Start() function below, but we need to check and increment the counters
73
+ // within the same mutex lock to ensure another call does not start between checking and starting
74
+ return concurrencyManager .StartIfAllowed (name , h .Config .MaxConcurrency )
75
+ }
76
+
77
+ // Start :: start a hydrate call
78
+ func (h * HydrateCall ) Start (ctx context.Context , r * RowData , hydrateFuncName string , concurrencyManager * ConcurrencyManager ) {
79
+ // tell the roewdata to wait for this call to complete
80
+ r .wg .Add (1 )
81
+
82
+ // call callHydrate async, ignoring return values
83
+ go func () {
84
+ r .callHydrate (ctx , r .queryData , h .Func , hydrateFuncName )
85
+ // decrement number of hydrate functions running
86
+ concurrencyManager .Finished (hydrateFuncName )
87
+ }()
55
88
}
0 commit comments