nicer error message for failed backfill (#4188)

* nicer error message for failed backfill

Many checkpoint sources don't support block download

* RestGenericError -> RestErrorMessage

...and other assorted fixes to bring rest types closer to spec

* fix tests
This commit is contained in:
Jacek Sieka 2022-09-29 22:55:18 +02:00 committed by GitHub
parent 5968ed586b
commit af9ec577d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 169 additions and 163 deletions

View File

@ -369,8 +369,8 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
OK: 1/1 Fail: 0/1 Skip: 0/1
## Serialization/deserialization test suite
```diff
+ RestGenericError parser tests OK
+ RestGenericError writer tests OK
+ RestErrorMessage parser tests OK
+ RestErrorMessage writer tests OK
```
OK: 2/2 Fail: 0/2 Skip: 0/2
## Slashing Interchange tests [Preset: mainnet]

View File

@ -214,7 +214,7 @@ proc restValidatorExit(config: BeaconNodeConf) {.async.} =
quit 0
else:
let responseError = try:
Json.decode(response.data, RestGenericError)
Json.decode(response.data, RestErrorMessage)
except CatchableError as err:
fatal "Failed to decode invalid error server response on `submitPoolVoluntaryExit` request",
err = err.msg

View File

@ -969,20 +969,20 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
res
let failures =
block:
var res: seq[RestAttestationsFailure]
var res: seq[RestIndexedErrorMessageItem]
await allFutures(pending)
for index, future in pending:
if future.done():
let fres = future.read()
if fres.isErr():
let failure = RestAttestationsFailure(index: uint64(index),
message: $fres.error())
let failure = RestIndexedErrorMessageItem(index: index,
message: $fres.error())
res.add(failure)
elif future.failed() or future.cancelled():
# This is unexpected failure, so we log the error message.
let exc = future.readError()
let failure = RestAttestationsFailure(index: uint64(index),
message: $exc.msg)
let failure = RestIndexedErrorMessageItem(index: index,
message: $exc.msg)
res.add(failure)
res
@ -1073,11 +1073,11 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
let failures =
block:
var res: seq[RestAttestationsFailure]
var res: seq[RestIndexedErrorMessageItem]
for index, item in results:
if item.isErr():
res.add(RestAttestationsFailure(index: uint64(index),
message: $item.error()))
res.add(RestIndexedErrorMessageItem(index: index,
message: $item.error()))
res
if len(failures) > 0:
return RestApiResponse.jsonErrorList(Http400,

View File

@ -742,20 +742,20 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
let failures =
block:
var res: seq[RestAttestationsFailure]
var res: seq[RestIndexedErrorMessageItem]
await allFutures(pending)
for index, future in pending:
if future.done():
let fres = future.read()
if fres.isErr():
let failure = RestAttestationsFailure(index: uint64(index),
message: $fres.error())
let failure = RestIndexedErrorMessageItem(index: index,
message: $fres.error())
res.add(failure)
elif future.failed() or future.cancelled():
# This is unexpected failure, so we log the error message.
let exc = future.readError()
let failure = RestAttestationsFailure(index: uint64(index),
message: $exc.msg)
let failure = RestIndexedErrorMessageItem(index: index,
message: $exc.msg)
res.add(failure)
res

View File

@ -72,16 +72,6 @@ const
type
EmptyBody* = object
RestGenericError* = object
code*: uint64
message*: string
stacktraces*: Option[seq[string]]
RestDutyError* = object
code*: uint64
message*: string
failures*: seq[RestFailureItem]
EncodeTypes* =
AttesterSlashing |
DeleteKeystoresBody |
@ -128,8 +118,8 @@ type
ListFeeRecipientResponse |
PrepareBeaconProposer |
ProduceBlockResponseV2 |
RestDutyError |
RestGenericError |
RestIndexedErrorMessage |
RestErrorMessage |
RestValidator |
Web3SignerErrorResponse |
Web3SignerKeysResponse |
@ -2220,12 +2210,12 @@ proc writeValue*(writer: var JsonWriter[RestJson],
writer.writeField("is_optimistic", value.is_optimistic.get())
writer.endRecord()
## RestGenericError
## RestErrorMessage
proc readValue*(reader: var JsonReader[RestJson],
value: var RestGenericError) {.
value: var RestErrorMessage) {.
raises: [SerializationError, IOError, Defect].} =
var
code: Opt[uint64]
code: Opt[int]
message: Opt[string]
stacktraces: Option[seq[string]]
@ -2234,30 +2224,34 @@ proc readValue*(reader: var JsonReader[RestJson],
of "code":
if code.isSome():
reader.raiseUnexpectedField("Multiple `code` fields found",
"RestGenericError")
"RestErrorMessage")
let ires =
try:
let res = reader.readValue(int)
if res < 0:
reader.raiseUnexpectedValue("Invalid `code` field value")
Opt.some(uint64(res))
Opt.some(res)
except SerializationError:
Opt.none(uint64)
Opt.none(int)
if ires.isNone():
let sres = Base10.decode(uint64, reader.readValue(string)).valueOr:
reader.raiseUnexpectedValue("Invalid `code` field format")
let sres =
try: parseInt(reader.readValue(string))
except ValueError:
reader.raiseUnexpectedValue("Invalid `code` field format")
if sres < 0:
reader.raiseUnexpectedValue("Invalid `code` field value")
code = Opt.some(sres)
else:
code = ires
of "message":
if message.isSome():
reader.raiseUnexpectedField("Multiple `message` fields found",
"RestGenericError")
"RestErrorMessage")
message = Opt.some(reader.readValue(string))
of "stacktraces":
if stacktraces.isSome():
reader.raiseUnexpectedField("Multiple `stacktraces` fields found",
"RestGenericError")
"RestErrorMessage")
stacktraces = some(reader.readValue(seq[string]))
else:
# We ignore all additional fields.
@ -2268,7 +2262,7 @@ proc readValue*(reader: var JsonReader[RestJson],
if message.isNone():
reader.raiseUnexpectedValue("Missing or invalid `message` value")
value = RestGenericError(
value = RestErrorMessage(
code: code.get(), message: message.get(),
stacktraces: stacktraces
)

View File

@ -157,16 +157,16 @@ proc getBlockV2*(client: RestClientRef, block_id: BlockIdent,
of 404:
none(ref ForkedSignedBeaconBlock)
of 400, 500:
let error = decodeBytes(RestGenericError, resp.data,
let error = decodeBytes(RestErrorMessage, resp.data,
resp.contentType).valueOr:
let msg = "Incorrect response error format (" & $resp.status &
") [" & $error & "]"
raise newException(RestError, msg)
raise (ref RestResponseError)(msg: msg, status: resp.status)
let msg = "Error response (" & $resp.status & ") [" & error.message & "]"
raise newException(RestError, msg)
raise (ref RestResponseError)(
msg: msg, status: error.code, message: error.message)
else:
let msg = "Unknown response status error (" & $resp.status & ")"
raise newException(RestError, msg)
raiseRestResponseError(resp)
proc getBlockRoot*(block_id: BlockIdent): RestResponse[GetBlockRootResponse] {.
rest, endpoint: "/eth/v1/beacon/blocks/{block_id}/root",

View File

@ -19,7 +19,7 @@ proc raiseGenericError*(resp: RestPlainResponse) {.
noreturn, raises: [RestError, Defect].} =
let error =
block:
let res = decodeBytes(RestGenericError, resp.data, resp.contentType)
let res = decodeBytes(RestErrorMessage, resp.data, resp.contentType)
if res.isErr():
let msg = "Incorrect response error format (" & $resp.status &
") [" & $res.error() & "]"

View File

@ -37,7 +37,7 @@ proc getStateV2*(client: RestClientRef, state_id: StateIdent,
await client.getStateV2Plain(state_id, restAcceptType = restAccept)
else:
await client.getStateV2Plain(state_id)
let data =
return
case resp.status
of 200:
if resp.contentType.isNone() or
@ -64,17 +64,13 @@ proc getStateV2*(client: RestClientRef, state_id: StateIdent,
of 404:
nil
of 400, 500:
let error =
block:
let res = decodeBytes(RestGenericError, resp.data, resp.contentType)
if res.isErr():
let msg = "Incorrect response error format (" & $resp.status &
") [" & $res.error() & "]"
raise newException(RestError, msg)
res.get()
let error = decodeBytes(RestErrorMessage, resp.data,
resp.contentType).valueOr:
let msg = "Incorrect response error format (" & $resp.status &
") [" & $error & "]"
raise (ref RestResponseError)(msg: msg, status: resp.status)
let msg = "Error response (" & $resp.status & ") [" & error.message & "]"
raise newException(RestError, msg)
raise (ref RestResponseError)(
msg: msg, status: error.code, message: error.message)
else:
let msg = "Unknown response status error (" & $resp.status & ")"
raise newException(RestError, msg)
return data
raiseRestResponseError(resp)

View File

@ -167,12 +167,20 @@ type
slot*: Slot
validators*: seq[ValidatorIndex]
RestFailureItem* = object
index*: uint64
RestErrorMessage* = object
## https://github.com/ethereum/beacon-APIs/blob/v2.3.0/types/http.yaml#L86
code*: int
message*: string
stacktraces*: Option[seq[string]]
RestAttestationsFailure* = object
index*: uint64
RestIndexedErrorMessage* = object
## https://github.com/ethereum/beacon-APIs/blob/v2.3.0/types/http.yaml#L101
code*: int
message*: string
failures*: seq[RestIndexedErrorMessageItem]
RestIndexedErrorMessageItem* = object
index*: int
message*: string
RestValidator* = object

View File

@ -106,17 +106,21 @@ proc doTrustedNodeSync*(
for i in 0..<3:
try:
return await client.getBlockV2(BlockIdent.init(slot), cfg)
except CatchableError as exc:
except RestResponseError as exc:
lastError = exc
notice "Server does not support block downloads / backfilling",
msg = exc.msg
break
except CatchableError as exc:
# We'll assume this may be a connectivity error or something similar
lastError = exc
warn "Retrying download of block", slot, err = exc.msg
client = RestClientRef.new(restUrl).valueOr:
error "Cannot connect to server", url = restUrl, error = error
quit 1
error "Unable to download block - backfill incomplete, but will resume when you start the beacon node",
slot, error = lastError.msg, url = client.address
quit 1
raise lastError
let
localGenesisRoot = db.getGenesisBlock().valueOr:
@ -280,8 +284,8 @@ proc doTrustedNodeSync*(
dbCache.update(blck)
(checkpointSlot, checkpointBlock[].root)
else:
notice "Skipping checkpoint download, database already exists",
head = shortLog(dbHead.get())
notice "Skipping checkpoint download, database already exists (remove db directory to get a fresh snapshot)",
databaseDir, head = shortLog(dbHead.get())
(headSlot, dbHead.get())
# Coming this far, we've done what ChainDAGRef.preInit would normally do -
@ -383,23 +387,27 @@ proc doTrustedNodeSync*(
# Download blocks backwards from the checkpoint slot, skipping the ones we
# already have in the database. We'll do a few downloads in parallel which
# risks having some redundant downloads going on, but speeds things up
for i in 0'u64..<(checkpointSlot.uint64 + gets.lenu64()):
if not isNil(gets[int(i mod gets.lenu64)]):
await processBlock(
gets[int(i mod gets.lenu64)],
checkpointSlot + gets.lenu64() - uint64(i))
gets[int(i mod gets.lenu64)] = nil
try:
for i in 0'u64..<(checkpointSlot.uint64 + gets.lenu64()):
if not isNil(gets[int(i mod gets.lenu64)]):
await processBlock(
gets[int(i mod gets.lenu64)],
checkpointSlot + gets.lenu64() - uint64(i))
gets[int(i mod gets.lenu64)] = nil
if i < checkpointSlot:
let slot = checkpointSlot - i
if dbCache.isKnown(slot):
continue
if i < checkpointSlot:
let slot = checkpointSlot - i
if dbCache.isKnown(slot):
continue
gets[int(i mod gets.lenu64)] = downloadBlock(slot)
gets[int(i mod gets.lenu64)] = downloadBlock(slot)
if i mod 1024 == 0:
db.checkpoint() # Transfer stuff from wal periodically
true
if i mod 1024 == 0:
db.checkpoint() # Transfer stuff from wal periodically
true
except CatchableError as exc: # Block download failed
notice "Backfilling incomplete - blocks will be downloaded when starting the node", msg = exc.msg
false
else:
notice "Database initialized, historical blocks will be backfilled when starting the node",
missingSlots

View File

@ -557,19 +557,18 @@ template firstSuccessSequential*(vc: ValidatorClientRef, respType: typedesc,
if exitNow:
break
proc getDutyErrorMessage(response: RestPlainResponse): string =
let res = decodeBytes(RestDutyError, response.data,
proc getIndexedErrorMessage(response: RestPlainResponse): string =
let res = decodeBytes(RestIndexedErrorMessage, response.data,
response.contentType)
if res.isOk():
let errorObj = res.get()
let failures = errorObj.failures.mapIt(Base10.toString(it.index) & ": " &
it.message)
let failures = errorObj.failures.mapIt($it.index & ": " & it.message)
errorObj.message & ": [" & failures.join(", ") & "]"
else:
"Unable to decode error response: [" & $res.error() & "]"
proc getGenericErrorMessage(response: RestPlainResponse): string =
let res = decodeBytes(RestGenericError, response.data,
proc getErrorMessage(response: RestPlainResponse): string =
let res = decodeBytes(RestErrorMessage, response.data,
response.contentType)
if res.isOk():
let errorObj = res.get()
@ -1139,15 +1138,15 @@ proc submitPoolAttestations*(
RestBeaconNodeStatus.Online
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node, response_error = response.getDutyErrorMessage()
endpoint = node, response_error = response.getIndexedErrorMessage()
RestBeaconNodeStatus.Incompatible
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node, response_error = response.getDutyErrorMessage()
endpoint = node, response_error = response.getIndexedErrorMessage()
RestBeaconNodeStatus.Offline
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node, response_error = response.getDutyErrorMessage()
endpoint = node, response_error = response.getIndexedErrorMessage()
RestBeaconNodeStatus.Offline
if res.isErr():
raise newException(ValidatorApiError, res.error())
@ -1168,15 +1167,15 @@ proc submitPoolAttestations*(
return true
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node, response_error = response.getDutyErrorMessage()
endpoint = node, response_error = response.getIndexedErrorMessage()
RestBeaconNodeStatus.Incompatible
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node, response_error = response.getDutyErrorMessage()
endpoint = node, response_error = response.getIndexedErrorMessage()
RestBeaconNodeStatus.Offline
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node, response_error = response.getDutyErrorMessage()
endpoint = node, response_error = response.getIndexedErrorMessage()
RestBeaconNodeStatus.Offline
raise newException(ValidatorApiError, ErrorMessage)
@ -1217,15 +1216,15 @@ proc submitPoolSyncCommitteeSignature*(
RestBeaconNodeStatus.Online
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node, response_error = response.getDutyErrorMessage()
endpoint = node, response_error = response.getIndexedErrorMessage()
RestBeaconNodeStatus.Incompatible
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node, response_error = response.getDutyErrorMessage()
endpoint = node, response_error = response.getIndexedErrorMessage()
RestBeaconNodeStatus.Offline
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node, response_error = response.getDutyErrorMessage()
endpoint = node, response_error = response.getIndexedErrorMessage()
RestBeaconNodeStatus.Offline
if res.isErr():
raise newException(ValidatorApiError, res.error())
@ -1246,15 +1245,15 @@ proc submitPoolSyncCommitteeSignature*(
return true
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node, response_error = response.getDutyErrorMessage()
endpoint = node, response_error = response.getIndexedErrorMessage()
RestBeaconNodeStatus.Incompatible
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node, response_error = response.getDutyErrorMessage()
endpoint = node, response_error = response.getIndexedErrorMessage()
RestBeaconNodeStatus.Offline
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node, response_error = response.getDutyErrorMessage()
endpoint = node, response_error = response.getIndexedErrorMessage()
RestBeaconNodeStatus.Offline
raise newException(ValidatorApiError, ErrorMessage)
@ -1434,17 +1433,17 @@ proc publishAggregateAndProofs*(
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Incompatible
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
if res.isErr():
raise newException(ValidatorApiError, res.error())
@ -1466,17 +1465,17 @@ proc publishAggregateAndProofs*(
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Incompatible
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
raise newException(ValidatorApiError, ErrorMessage)
@ -1511,17 +1510,17 @@ proc publishContributionAndProofs*(
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Incompatible
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
if res.isErr():
@ -1544,17 +1543,17 @@ proc publishContributionAndProofs*(
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Incompatible
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
raise newException(ValidatorApiError, ErrorMessage)
@ -1681,22 +1680,22 @@ proc publishBlock*(
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Incompatible
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
of 503:
debug ResponseNoSyncError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.NotSynced
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
if res.isErr():
raise newException(ValidatorApiError, res.error())
@ -1728,22 +1727,22 @@ proc publishBlock*(
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Incompatible
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
of 503:
debug ResponseNoSyncError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.NotSynced
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
raise newException(ValidatorApiError, ErrorMessage)
@ -1780,22 +1779,22 @@ proc prepareBeaconCommitteeSubnet*(
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Online
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
of 503:
debug ResponseNoSyncError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.NotSynced
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
if res.isErr():
raise newException(ValidatorApiError, res.error())
@ -1817,22 +1816,22 @@ proc prepareBeaconCommitteeSubnet*(
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
return false
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
of 503:
debug ResponseNoSyncError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.NotSynced
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
raise newException(ValidatorApiError, ErrorMessage)
@ -1869,22 +1868,22 @@ proc prepareSyncCommitteeSubnets*(
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Online
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
of 503:
debug ResponseNoSyncError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.NotSynced
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
if res.isErr():
raise newException(ValidatorApiError, res.error())
@ -1906,22 +1905,22 @@ proc prepareSyncCommitteeSubnets*(
of 400:
debug ResponseInvalidError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
return false
of 500:
debug ResponseInternalError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
of 503:
debug ResponseNoSyncError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.NotSynced
else:
debug ResponseUnexpectedError, response_code = response.status,
endpoint = node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
RestBeaconNodeStatus.Offline
raise newException(ValidatorApiError, ErrorMessage)
@ -1999,21 +1998,21 @@ proc getValidatorsActivity*(
debug "Server reports invalid request",
response_code = response.status,
endpoint = apiResponse.node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
apiResponse.node.status = RestBeaconNodeStatus.Incompatible
default
of 500:
debug "Server reports internal error",
response_code = response.status,
endpoint = apiResponse.node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
apiResponse.node.status = RestBeaconNodeStatus.Offline
default
else:
debug "Server reports unexpected error code",
response_code = response.status,
endpoint = apiResponse.node,
response_error = response.getGenericErrorMessage()
response_error = response.getErrorMessage()
apiResponse.node.status = RestBeaconNodeStatus.Offline
default

View File

@ -15,77 +15,77 @@ import
./testutil
suite "Serialization/deserialization test suite":
test "RestGenericError parser tests":
proc init(t: typedesc[RestGenericError], status: int,
message: string): RestGenericError =
RestGenericError(
code: uint64(status), message: message,
test "RestErrorMessage parser tests":
proc init(t: typedesc[RestErrorMessage], status: int,
message: string): RestErrorMessage =
RestErrorMessage(
code: status, message: message,
stacktraces: none[seq[string]]()
)
proc init(t: typedesc[RestGenericError], status: int,
proc init(t: typedesc[RestErrorMessage], status: int,
message: string,
stacktraces: openArray[string]): RestGenericError =
RestGenericError(
code: uint64(status), message: message,
stacktraces: openArray[string]): RestErrorMessage =
RestErrorMessage(
code: status, message: message,
stacktraces: some(@stacktraces)
)
const GoodTestVectors = [
(
"""{"code": 500, "message": "block not found"}""",
RestGenericError.init(500, "block not found")
RestErrorMessage.init(500, "block not found")
),
(
"""{"code": "600", "message": "block not found"}""",
RestGenericError.init(600, "block not found")
RestErrorMessage.init(600, "block not found")
),
(
"""{"code": "700", "message": "block not found",
"data": "data", "custom": "field"}""",
RestGenericError.init(700, "block not found")
RestErrorMessage.init(700, "block not found")
),
(
"""{"code":"701", "message": "block not found",
"data": "data", "custom": 300}""",
RestGenericError.init(701, "block not found")
RestErrorMessage.init(701, "block not found")
),
(
"""{"code": "702", "message": "block not found",
"data": "data", "custom": {"field1": "value1"}}""",
RestGenericError.init(702, "block not found")
RestErrorMessage.init(702, "block not found")
),
(
"""{"code": 800, "message": "block not found",
"custom": "data", "stacktraces": []}""",
RestGenericError.init(800, "block not found", [])
RestErrorMessage.init(800, "block not found", [])
),
(
"""{"code": 801, "message": "block not found",
"custom": 100, "stacktraces": []}""",
RestGenericError.init(801, "block not found", [])
RestErrorMessage.init(801, "block not found", [])
),
(
"""{"code": 802, "message": "block not found",
"custom": {"field1": "value1"}, "stacktraces": []}""",
RestGenericError.init(802, "block not found", [])
RestErrorMessage.init(802, "block not found", [])
),
(
"""{"code": "900", "message": "block not found",
"stacktraces": ["line1", "line2", "line3"], "custom": "data"}""",
RestGenericError.init(900, "block not found",
RestErrorMessage.init(900, "block not found",
["line1", "line2", "line3"])
),
(
"""{"code": "901", "message": "block not found",
"stacktraces": ["line1", "line2", "line3"], "custom": 2000}""",
RestGenericError.init(901, "block not found",
RestErrorMessage.init(901, "block not found",
["line1", "line2", "line3"])
),
(
"""{"code": "902", "message": "block not found",
"stacktraces": ["line1", "line2", "line3"],
"custom": {"field1": "value1"}}""",
RestGenericError.init(902, "block not found",
RestErrorMessage.init(902, "block not found",
["line1", "line2", "line3"])
)
]
@ -119,7 +119,7 @@ suite "Serialization/deserialization test suite":
for test in GoodTestVectors:
let res = decodeBytes(
RestGenericError, test[0].toOpenArrayByte(0, len(test[0]) - 1),
RestErrorMessage, test[0].toOpenArrayByte(0, len(test[0]) - 1),
Opt.some(contentType))
check res.isOk()
let response = res.get()
@ -135,10 +135,11 @@ suite "Serialization/deserialization test suite":
for test in FailureTestVectors:
let res = decodeBytes(
RestGenericError, test.toOpenArrayByte(0, len(test) - 1),
RestErrorMessage, test.toOpenArrayByte(0, len(test) - 1),
Opt.some(contentType))
checkpoint test
check res.isErr()
test "RestGenericError writer tests":
test "RestErrorMessage writer tests":
proc `==`(a: RestApiResponse, b: string): bool =
case a.kind
of RestApiResponseKind.Content: