Skip to content

Commit 65b2d61

Browse files
authored
ingest/ledgerbackend: fix rpc ledger backend retries (#5718)
1 parent ef10cd0 commit 65b2d61

File tree

5 files changed

+164
-220
lines changed

5 files changed

+164
-220
lines changed

.github/workflows/golangci-lint.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,15 @@ jobs:
1515
runs-on: ubuntu-22.04
1616
steps:
1717
- name: Checkout
18-
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # version v3.0.2
18+
uses: actions/checkout@v4
1919
with:
2020
fetch-depth: 0 # required for new-from-rev option in .golangci.yml
21-
- name: Setup GO
22-
uses: actions/setup-go@268d8c0ca0432bb2cf416faae41297df9d262d7f # version v3.3.0
21+
- uses: ./.github/actions/setup-go
2322
- name: Run golangci-lint
24-
uses: golangci/golangci-lint-action@537aa1903e5d359d0b27dbc19ddd22c5087f3fbc # version v3.2.0
23+
uses: golangci/golangci-lint-action@v7
2524
with:
26-
version: v1.52.2 # this is the golangci-lint version
27-
args: --issues-exit-code=0 # exit without errors for now - won't fail the build
25+
version: v2.1.6
26+
args: -v --issues-exit-code=0 --config=.golangci.yml # exit without errors for now - won't fail the build
2827
github-token: ${{ secrets.GITHUB_TOKEN }}
2928
only-new-issues: true
3029

.golangci.yml

Lines changed: 71 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,95 @@
1-
linters-settings:
2-
depguard:
3-
list-type: denylist
4-
packages:
5-
# logging is allowed only by logutils.Log, logrus
6-
# is allowed to use only in logutils package
7-
- github.com/sirupsen/logrus
8-
packages-with-error-message:
9-
- github.com/sirupsen/logrus: "logging is allowed only by logutils.Log"
10-
dupl:
11-
threshold: 100
12-
funlen:
13-
lines: 100
14-
statements: 50
15-
goconst:
16-
min-len: 2
17-
min-occurrences: 3
18-
gocritic:
19-
enabled-tags:
20-
- diagnostic
21-
- experimental
22-
- opinionated
23-
- performance
24-
- style
25-
disabled-checks:
26-
- dupImport # https://github.com/go-critic/go-critic/issues/845
27-
- ifElseChain
28-
- octalLiteral
29-
- whyNoLint
30-
gocyclo:
31-
min-complexity: 15
32-
goimports:
33-
local-prefixes: github.com/golangci/golangci-lint
34-
gomnd:
35-
# don't include the "operation" and "assign"
36-
checks:
37-
- argument
38-
- case
39-
- condition
40-
- return
41-
ignored-numbers:
42-
- '0'
43-
- '1'
44-
- '2'
45-
- '3'
46-
ignored-functions:
47-
- strings.SplitN
48-
49-
govet:
50-
check-shadowing: true
51-
settings:
52-
printf:
53-
funcs:
54-
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
55-
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
56-
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
57-
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
58-
lll:
59-
line-length: 140
60-
misspell:
61-
locale: US
62-
nolintlint:
63-
allow-unused: false # report any unused nolint directives
64-
require-explanation: false # don't require an explanation for nolint directives
65-
require-specific: false # don't require nolint directives to be specific about which linter is being skipped
66-
1+
version: "2"
672
linters:
68-
disable-all: true
3+
default: none
694
enable:
705
- bodyclose
716
- depguard
727
- dogsled
738
- dupl
749
- errcheck
75-
- exportloopref
7610
- funlen
7711
- gochecknoinits
7812
- goconst
79-
#- gocritic
8013
- gocyclo
81-
- gofmt
82-
- goimports
83-
- gomnd
8414
- goprintffuncname
8515
- gosec
86-
- gosimple
8716
- govet
8817
- ineffassign
8918
- lll
9019
- misspell
20+
- mnd
9121
- nakedret
9222
- noctx
9323
- nolintlint
9424
- staticcheck
95-
- stylecheck
96-
- typecheck
9725
- unconvert
9826
- unparam
9927
- unused
100-
#- whitespace
101-
102-
# don't enable:
103-
# - asciicheck
104-
# - scopelint
105-
# - gochecknoglobals
106-
# - gocognit
107-
# - godot
108-
# - godox
109-
# - goerr113
110-
# - interfacer
111-
# - maligned
112-
# - nestif
113-
# - prealloc
114-
# - testpackage
115-
# - revive
116-
# - wsl
117-
118-
issues:
119-
# Excluding configuration per-path, per-linter, per-text and per-source
120-
exclude-rules:
121-
- path: _test\.go
122-
linters:
123-
- govet
124-
125-
run:
126-
timeout: 5m
127-
skip-dirs:
128-
- docs
129-
- vendor
28+
settings:
29+
dupl:
30+
threshold: 100
31+
funlen:
32+
lines: 100
33+
statements: 50
34+
goconst:
35+
min-len: 2
36+
min-occurrences: 3
37+
gocritic:
38+
disabled-checks:
39+
- dupImport
40+
- ifElseChain
41+
- octalLiteral
42+
- whyNoLint
43+
enabled-tags:
44+
- diagnostic
45+
- experimental
46+
- opinionated
47+
- performance
48+
- style
49+
gocyclo:
50+
min-complexity: 15
51+
govet:
52+
settings:
53+
printf:
54+
funcs:
55+
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
56+
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
57+
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
58+
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
59+
lll:
60+
line-length: 140
61+
misspell:
62+
locale: US
63+
nolintlint:
64+
require-explanation: false
65+
require-specific: false
66+
allow-unused: false
67+
exclusions:
68+
generated: lax
69+
presets:
70+
- comments
71+
- common-false-positives
72+
- legacy
73+
- std-error-handling
74+
rules:
75+
- linters:
76+
- govet
77+
path: _test\.go
78+
paths:
79+
- third_party$
80+
- builtin$
81+
- examples$
82+
formatters:
83+
enable:
84+
- gofmt
85+
- goimports
86+
settings:
87+
goimports:
88+
local-prefixes:
89+
- github.com/golangci/golangci-lint
90+
exclusions:
91+
generated: lax
92+
paths:
93+
- third_party$
94+
- builtin$
95+
- examples$

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ require (
1313
github.com/adjust/goautoneg v0.0.0-20150426214442-d788f35a0315
1414
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
1515
github.com/aws/aws-sdk-go v1.45.27
16-
github.com/creachadair/jrpc2 v1.2.0
1716
github.com/djherbis/fscache v0.10.1
1817
github.com/elazarl/go-bindata-assetfs v1.0.1
1918
github.com/getsentry/raven-go v0.2.0
@@ -58,6 +57,7 @@ require (
5857

5958
require (
6059
github.com/cenkalti/backoff/v4 v4.3.0
60+
github.com/creachadair/jrpc2 v1.2.0
6161
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da
6262
github.com/docker/docker v27.3.1+incompatible
6363
github.com/docker/go-connections v0.5.0

ingest/ledgerbackend/rpc_backend.go

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,16 @@ func (e *RPCLedgerMissingError) Error() string {
2525
return fmt.Sprintf("ledger %d was not present on rpc", e.Sequence)
2626
}
2727

28-
type RPCLedgerBeyondLatestError struct {
29-
Sequence uint32
30-
LatestLedger uint32
31-
}
28+
type rpcLedgerBeyondLatestError struct{}
3229

33-
func (e *RPCLedgerBeyondLatestError) Error() string {
34-
return fmt.Sprintf("ledger %d is beyond the RPC latest ledger is %d", e.Sequence, e.LatestLedger)
30+
func (e rpcLedgerBeyondLatestError) Error() string {
31+
return "ledger is not available on the RPC server yet"
3532
}
3633

3734
// The minimum required RPC client methods used by RPCLedgerBackend.
3835
type RPCLedgerGetter interface {
3936
GetLedgers(ctx context.Context, req protocol.GetLedgersRequest) (protocol.GetLedgersResponse, error)
37+
GetHealth(ctx context.Context) (protocol.GetHealthResponse, error) // <-- Added
4038
}
4139

4240
type RPCLedgerBackend struct {
@@ -146,8 +144,8 @@ func (b *RPCLedgerBackend) GetLedger(ctx context.Context, sequence uint32) (xdr.
146144
return lcm, nil
147145
}
148146

149-
_, isBeyondErr := err.(*RPCLedgerBeyondLatestError)
150-
if !isBeyondErr {
147+
var beyondErr *rpcLedgerBeyondLatestError
148+
if !(errors.As(err, &beyondErr)) {
151149
return xdr.LedgerCloseMeta{}, err
152150
}
153151

@@ -182,7 +180,7 @@ func (b *RPCLedgerBackend) PrepareRange(ctx context.Context, ledgerRange Range)
182180
_, err := b.getBufferedLedger(ctx, ledgerRange.from)
183181
if err != nil {
184182
// beyond latest is handled later in GetLedger
185-
var beyondErr *RPCLedgerBeyondLatestError
183+
var beyondErr *rpcLedgerBeyondLatestError
186184
if !(errors.As(err, &beyondErr)) {
187185
return err
188186
}
@@ -240,7 +238,16 @@ func (b *RPCLedgerBackend) getBufferedLedger(ctx context.Context, sequence uint3
240238
return lcm, nil
241239
}
242240

243-
// Ledger not in buffer, fetch a small batch from RPC starting from the requested sequence
241+
// Check if requested ledger is beyond the RPC retention window using GetHealth
242+
health, err := b.client.GetHealth(ctx)
243+
if err != nil {
244+
return xdr.LedgerCloseMeta{}, fmt.Errorf("failed to get health from RPC: %w", err)
245+
}
246+
if sequence > health.LatestLedger {
247+
return xdr.LedgerCloseMeta{}, &rpcLedgerBeyondLatestError{}
248+
}
249+
250+
// attempt to fetch a small batch from RPC starting from the requested sequence
244251
req := protocol.GetLedgersRequest{
245252
StartLedger: sequence,
246253
Pagination: &protocol.LedgerPaginationOptions{
@@ -250,19 +257,11 @@ func (b *RPCLedgerBackend) getBufferedLedger(ctx context.Context, sequence uint3
250257

251258
ledgers, err := b.client.GetLedgers(ctx, req)
252259
if err != nil {
253-
return xdr.LedgerCloseMeta{}, fmt.Errorf("failed to get ledgers starting from %d: %w", sequence, err)
260+
return xdr.LedgerCloseMeta{}, err
254261
}
255262

256263
b.initBuffer()
257264

258-
// Check if requested ledger is beyond the RPC retention window
259-
if sequence > ledgers.LatestLedger {
260-
return xdr.LedgerCloseMeta{}, &RPCLedgerBeyondLatestError{
261-
Sequence: sequence,
262-
LatestLedger: ledgers.LatestLedger,
263-
}
264-
}
265-
266265
// Populate buffer with new ledgers
267266
for _, ledger := range ledgers.Ledgers {
268267
var lcm xdr.LedgerCloseMeta

0 commit comments

Comments
 (0)