Skip to content

Commit

Permalink
feat(alpacabkfeeder): API Retry (#621)
Browse files Browse the repository at this point in the history
  • Loading branch information
dakimura committed Nov 1, 2022
1 parent d2880b0 commit 44f556c
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 43 deletions.
3 changes: 3 additions & 0 deletions contrib/alpacabkfeeder/README.md
Expand Up @@ -65,6 +65,9 @@ bgworkers:
# such as "300ms", "5.5s" if you want to change it from the default 10sec timeout.
# Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
#
# RetryMax: The number of maximum retries for Alpaca API.
# It can be updated only by "APCA_API_RETRY_MAX" environmental variable.
#
# Interval [sec] to call Alpaca Broker API
interval: 10
# The data-feeding is executed when 'minute' of the current time matches off_hours_schedule
Expand Down
21 changes: 17 additions & 4 deletions contrib/alpacabkfeeder/api/client.go
Expand Up @@ -9,10 +9,12 @@ import (
"net/url"
"os"
"sort"
"strconv"
"strings"
"time"

v1 "github.com/alpacahq/marketstore/v4/contrib/alpacabkfeeder/api/v1"
"github.com/hashicorp/go-retryablehttp"
)

const (
Expand All @@ -28,7 +30,9 @@ var (
dataURL = "https://data.alpaca.markets"
apiVersion = "v2"
clientTimeout = 10 * time.Second
do = defaultDo
// maximum number of retries
retryMax = 1
do = defaultDo
)

func defaultDo(c *Client, req *http.Request) (*http.Response, error) {
Expand All @@ -44,9 +48,11 @@ func defaultDo(c *Client, req *http.Request) (*http.Response, error) {
}
}

client := &http.Client{
Timeout: clientTimeout,
}
retryClient := retryablehttp.NewClient()
retryClient.RetryMax = retryMax
client := retryClient.StandardClient() // *http.Client
client.Timeout = clientTimeout

var resp *http.Response
var err error
for i := 0; ; i++ {
Expand Down Expand Up @@ -99,6 +105,13 @@ func init() {
}
clientTimeout = d
}
if s := os.Getenv("APCA_API_RETRY_MAX"); s != "" {
d, err := strconv.Atoi(s)
if err != nil {
log.Fatal("invalid APCA_API_RETRY_MAX: " + err.Error())
}
retryMax = d
}
}

// APIError wraps the detailed code and message supplied
Expand Down
14 changes: 7 additions & 7 deletions contrib/alpacabkfeeder/feed/backfill.go
Expand Up @@ -41,7 +41,7 @@ func NewBackfill(symbolManager symbols.Manager, apiClient GetMultiBarsAPIClient,
// and store it to "{symbol}/{timeframe}/OHLCV" bucket in marketstore.
func (b *Backfill) UpdateSymbols() {
allSymbols := b.symbolManager.GetAllSymbols()
y, m, d := time.Now().Date()
y, m, d := time.Now().UTC().Date()
until := time.Date(y, m, d, 0, 0, 0, 0, time.UTC)

// paginate symbols & paginate bars
Expand Down Expand Up @@ -133,12 +133,12 @@ type dateRange struct {
// datePageIndex returns a channel with paginated date ranges.
// datePageIndex assumes that start and end have only year, month, and day information
// like time.Date(yyyy, mm, dd, 0,0,0,0, time.UTC)
// e.g. start = 2021-12-01, end = 2021-12-05, pageDays = 2
// e.g. start = 2021-12-01, end = 2021-12-06, pageDays = 2
// -> chan will return
// [
// {From:2021-12-01, To:2021-12-02},
// {From:2021-12-03, To:2021-12-04},
// {From:2021-12-05, To:2021-12-05}
// {From:2021-12-01, To:2021-12-03},
// {From:2021-12-03, To:2021-12-05},
// {From:2021-12-05, To:2021-12-06}
// ].
func datePageIndex(start, end time.Time, pageDays int) <-chan dateRange {
ch := make(chan dateRange)
Expand All @@ -149,15 +149,15 @@ func datePageIndex(start, end time.Time, pageDays int) <-chan dateRange {
i := start
for {
pageStart := i
pageEnd := i.AddDate(0, 0, pageDays-1)
pageEnd := i.AddDate(0, 0, pageDays)
if pageEnd.After(end) {
pageEnd = end
}
page := dateRange{From: pageStart, To: pageEnd}
ch <- page

i = i.AddDate(0, 0, pageDays)
if i.After(end) {
if i.Equal(end) || i.After(end) {
break
}
}
Expand Down
20 changes: 10 additions & 10 deletions contrib/alpacabkfeeder/feed/backfill_test.go
Expand Up @@ -14,11 +14,11 @@ import (
)

var (
dYear, dMonth, dDay = time.Now().Add(-24 * time.Hour).Date()
dYear, dMonth, dDay = time.Now().UTC().Add(-24 * time.Hour).Date()
d = time.Date(dYear, dMonth, dDay, 0, 0, 0, 0, time.UTC)
d2Year, d2Month, d2Day = time.Now().Add(-48 * time.Hour).Date()
d2Year, d2Month, d2Day = time.Now().UTC().Add(-48 * time.Hour).Date()
d2 = time.Date(d2Year, d2Month, d2Day, 0, 0, 0, 0, time.UTC)
d3Year, d3Month, d3Day = time.Now().Add(-72 * time.Hour).Date()
d3Year, d3Month, d3Day = time.Now().UTC().Add(-72 * time.Hour).Date()
d3 = time.Date(d3Year, d3Month, d3Day, 0, 0, 0, 0, time.UTC)
)

Expand Down Expand Up @@ -48,7 +48,7 @@ type MockErrorAPIClient struct {
}

// GetMultiBars returns an error if symbol:"ERROR" is included, but returns data to other symbols.
func (mac *MockErrorAPIClient) GetMultiBars(symbols []string, opts api.GetBarsParams) (map[string][]api.Bar, error) {
func (mac *MockErrorAPIClient) GetMultiBars(symbols []string, req api.GetBarsParams) (map[string][]api.Bar, error) {
ret := make(map[string][]api.Bar)
for _, symbl := range symbols {
if symbl == errorSymbol {
Expand All @@ -60,10 +60,10 @@ func (mac *MockErrorAPIClient) GetMultiBars(symbols []string, opts api.GetBarsPa
// filter by time
for _, bar := range bars {
barTime := time.Unix(bar.Timestamp.Unix(), 0).UTC().Truncate(24 * time.Hour) // 00:00:00 of the bar time
startDt := opts.Start.UTC().Truncate(24 * time.Hour)
endDt := opts.End.UTC().Truncate(24 * time.Hour)
startDt := req.Start.UTC().Truncate(24 * time.Hour)
endDt := req.End.UTC().Truncate(24 * time.Hour)

if barTime.Equal(startDt) || (barTime.After(startDt) && barTime.Before(startDt)) || barTime.Equal(endDt) {
if barTime.Equal(startDt) || (barTime.After(startDt) && barTime.Before(endDt)) {
barPage = append(barPage, bar)
}
}
Expand Down Expand Up @@ -104,7 +104,7 @@ func TestBackfill_UpdateSymbols(t *testing.T) {
testBars: testBars,
maxBarsPerReq: 2,
maxSymbolsPerReq: 2,
since: time.Now().Add(-72 * time.Hour),
since: time.Now().UTC().Add(-72 * time.Hour),
wantWrittenBarCount: 9,
},
{
Expand All @@ -113,7 +113,7 @@ func TestBackfill_UpdateSymbols(t *testing.T) {
testBars: testBars,
maxBarsPerReq: 1,
maxSymbolsPerReq: 3,
since: time.Now().Add(-72 * time.Hour),
since: time.Now().UTC().Add(-72 * time.Hour),
wantWrittenBarCount: 9,
},
{
Expand All @@ -122,7 +122,7 @@ func TestBackfill_UpdateSymbols(t *testing.T) {
testBars: testBars,
maxBarsPerReq: 2,
maxSymbolsPerReq: 2,
since: time.Now().Add(-72 * time.Hour),
since: time.Now().UTC().Add(-72 * time.Hour),
// firstPage=[AMZN, AAPL] so all data succeed.
// secondPage=[error FB] so all data result in error.
wantWrittenBarCount: 6,
Expand Down
11 changes: 5 additions & 6 deletions contrib/alpacabkfeeder/feed/paginate_test.go
Expand Up @@ -31,9 +31,8 @@ func Test_datePageIndex(t *testing.T) {
end: date(5),
pageDays: 2,
want: []dateRange{
{From: date(1), To: date(2)},
{From: date(3), To: date(4)},
{From: date(5), To: date(5)},
{From: date(1), To: date(3)},
{From: date(3), To: date(5)},
},
},
{
Expand All @@ -51,9 +50,9 @@ func Test_datePageIndex(t *testing.T) {
end: date(3),
pageDays: 1,
want: []dateRange{
{From: date(1), To: date(1)},
{From: date(2), To: date(2)},
{From: date(3), To: date(3)},
{From: date(1), To: date(2)},
{From: date(2), To: date(3)},
{From: date(3), To: date(4)},
},
},
}
Expand Down
7 changes: 5 additions & 2 deletions go.mod
Expand Up @@ -44,14 +44,18 @@ require (
gopkg.in/yaml.v2 v2.4.0
)

require google.golang.org/protobuf v1.28.0
require (
github.com/hashicorp/go-retryablehttp v0.7.1
google.golang.org/protobuf v1.28.0
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/gopacket v1.1.16-0.20181023151400-a35e09f9f224 // indirect
github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/kr/text v0.2.0 // indirect
Expand All @@ -72,7 +76,6 @@ require (
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/appengine v1.4.0 // indirect
google.golang.org/genproto v0.0.0-20220527130721-00d5c0f3be58 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
Expand Down
20 changes: 6 additions & 14 deletions go.sum
Expand Up @@ -127,6 +127,12 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmg
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ=
github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
Expand Down Expand Up @@ -252,7 +258,6 @@ github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaU
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
Expand All @@ -269,7 +274,6 @@ go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2 h1:y102fOLFqhV41b+4GPiJoa0k/x+pJcEi2/HB1Y5T6fU=
Expand All @@ -280,9 +284,6 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand All @@ -303,8 +304,6 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220526153639-5463443f8c37 h1:lUkvobShwKsOesNfWWlCS5q7fnbG1MEliIzwu886fn8=
golang.org/x/net v0.0.0-20220526153639-5463443f8c37/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
Expand All @@ -314,7 +313,6 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand All @@ -336,8 +334,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
Expand All @@ -359,13 +355,9 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963 h1:K+NlvTLy0oONtRtkl1jRD9xIhnItbG2PiE7YOdjPb+k=
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down

0 comments on commit 44f556c

Please sign in to comment.