-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathrefresh_strategy.go
93 lines (84 loc) · 2.5 KB
/
refresh_strategy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package stencil
import (
"encoding/json"
"fmt"
"strings"
)
// RefreshStrategy clients can configure which refresh strategy to use to download latest schema.
// Default is LongPollingRefresh strategy
type RefreshStrategy int
const (
// LongPollingRefresh this refresh strategy tries to update schema on every specified interval.
// It doesn't check for schema changes explicitly.
LongPollingRefresh RefreshStrategy = iota
// VersionBasedRefresh this refresh strategy utilizes versions API provided by Stencil Server.
// If new version is available then only schema cache would be updated.
VersionBasedRefresh
)
func (r RefreshStrategy) getLoader(opts Options) loaderFunc {
switch r {
case VersionBasedRefresh:
return versionBasedRefresh(opts)
default:
return longPollingRefresh(opts)
}
}
func loadFromURL(url string, opts Options) (*Resolver, error) {
logger := wrapLogger(opts.Logger)
logger.Info(fmt.Sprintf("fetching schema from %s", url))
data, err := downloader(url, opts.HTTPOptions)
if err != nil {
logger.Error(fmt.Sprintf("failed to fetch schema from %s", url))
return nil, err
}
logger.Info(fmt.Sprintf("successfully fetched schema from %s", url))
return NewResolver(data)
}
func longPollingRefresh(opts Options) loaderFunc {
return func(url string) (*Resolver, error) {
return loadFromURL(url, opts)
}
}
type versionsModel struct {
Versions []int `json:"versions"`
}
func versionBasedRefresh(opts Options) loaderFunc {
lastVersion := 0
logger := wrapLogger(opts.Logger)
return func(url string) (*Resolver, error) {
versionsURL := fmt.Sprintf("%s/versions", strings.TrimRight(url, "/"))
data, err := downloader(versionsURL, opts.HTTPOptions)
if err != nil {
logger.Error(fmt.Sprintf("unable to download versions info, %s", err))
return nil, err
}
versionsResp := &versionsModel{}
if err := json.Unmarshal(data, versionsResp); err != nil {
return nil, err
}
versions := versionsResp.Versions
if len(versions) == 0 {
logger.Error("no versions available for this schema")
return nil, fmt.Errorf("no versions available")
}
maxVersion := getMaxVersion(versions)
if maxVersion > lastVersion {
data, err := loadFromURL(fmt.Sprintf("%s/%d", versionsURL, maxVersion), opts)
if err != nil {
return nil, err
}
lastVersion = maxVersion
return data, err
}
return nil, fmt.Errorf("schema already upto date")
}
}
func getMaxVersion(array []int) int {
max := array[0]
for _, value := range array {
if max < value {
max = value
}
}
return max
}