Coredb fix kvt save only fringe condition (#2592)

* Cosmetics, spelling, etc.

* Aristo: make sure that a save cycle always commits even when empty

why:
  If `Kvt` is tied to the `Aristo` DB save cycle, then this save cycle
  must also be committed if there is no data to save for `Aristo`.

  Otherwise this will lead to excessive core memory use with some fringe
  condition where Eth headers (or blocks) are downloaded while syncing
  and not really stored on disk.

* CoreDb: Correct persistent save mode

why:
  Saving `Kvt` first is seen as a harbinger (or canary) for `Aristo` as
  both run in sync. If `Kvt` succeeds saving first, so must be `Aristo`
  next. Other than this is a defect.
This commit is contained in:
Jordan Hrycaj 2024-09-04 13:48:38 +00:00 committed by GitHub
parent 4d9e288340
commit 3c6400673d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 20 additions and 23 deletions

View File

@ -13,16 +13,12 @@
##
import
std/[strutils, tables],
chronicles,
std/tables,
eth/common,
results,
./aristo_delta/[delta_merge, delta_reverse],
./aristo_desc/desc_backend,
"."/[aristo_desc, aristo_get, aristo_layers, aristo_utils]
logScope:
topics = "aristo-delta"
"."/[aristo_desc, aristo_layers]
# ------------------------------------------------------------------------------
# Public functions, save to backend
@ -55,6 +51,15 @@ proc deltaPersistent*(
# Blind or missing filter
if db.balancer.isNil:
# Add a blind storage frame. This will do no harm if `Aristo` runs
# standalone. Yet it is needed if a `Kvt` is tied to `Aristo` and has
# triggered a save cyle already which is to be completed here.
#
# There is no need to add a blind frame on any error return. If there
# is a `Kvt` tied to `Aristo`, then it must somehow run in sync and an
# error occuring here must have been detected earlier when (implicitely)
# registering `Kvt`. So that error should be considered a defect.
? be.putEndFn(? be.putBegFn())
return ok()
# Make sure that the argument `db` is at the centre so the backend is in

View File

@ -80,7 +80,7 @@ proc getVtxFn(db: RdbBackendRef): GetVtxFn =
# Fetch serialised data record
let vtx = db.rdb.getVtx(rvid).valueOr:
when extraTraceMessages:
trace logTxt "getVtxFn() failed", vid, error=error[0], info=error[1]
trace logTxt "getVtxFn() failed", rvid, error=error[0], info=error[1]
return err(error[0])
if vtx.isValid:
@ -95,7 +95,7 @@ proc getKeyFn(db: RdbBackendRef): GetKeyFn =
# Fetch serialised data record
let key = db.rdb.getKey(rvid).valueOr:
when extraTraceMessages:
trace logTxt "getKeyFn: failed", vid, error=error[0], info=error[1]
trace logTxt "getKeyFn: failed", rvid, error=error[0], info=error[1]
return err(error[0])
if key.isValid:
@ -207,8 +207,6 @@ proc putEndFn(db: RdbBackendRef): PutEndFn =
case hdl.error.pfx:
of VtxPfx, KeyPfx: trace logTxt "putEndFn: vtx/key failed",
pfx=hdl.error.pfx, vid=hdl.error.vid, error=hdl.error.code
of FilPfx: trace logTxt "putEndFn: filter failed",
pfx=FilPfx, qid=hdl.error.qid, error=hdl.error.code
of AdmPfx: trace logTxt "putEndFn: admin failed",
pfx=AdmPfx, aid=hdl.error.aid.uint64, error=hdl.error.code
of Oops: trace logTxt "putEndFn: oops",

View File

@ -166,8 +166,7 @@ proc `$$`*(e: CoreDbError): string =
proc persistent*(
db: CoreDbRef;
blockNumber: BlockNumber;
): CoreDbRc[void]
{.discardable.} =
): CoreDbRc[void] =
## This function stored cached data from the default context (see `ctx()`
## below) to the persistent database.
##
@ -187,16 +186,11 @@ proc persistent*(
else:
result = err(rc.error.toError $api)
break body
block:
let rc = CoreDbAccRef(db.ctx).call(persist, db.ctx.mpt, blockNumber)
if rc.isOk:
discard
elif CoreDbAccRef(db.ctx).call(level, db.ctx.mpt) != 0:
result = err(rc.error.toError($api, TxPending))
break body
else:
result = err(rc.error.toError $api)
break body
# Having reached here `Aristo` must not fail as both `Kvt` and `Aristo`
# are kept in sync. So if there is a legit fail condition it mist be
# caught in the previous clause.
CoreDbAccRef(db.ctx).call(persist, db.ctx.mpt, blockNumber).isOkOr:
raiseAssert $api & ": " & $error
result = ok()
db.ifTrackNewApi: debug logTxt, api, elapsed, blockNumber, result

View File

@ -24,7 +24,7 @@ type
session*: WriteBatchRef ## For batched `put()`
basePath*: string ## Database directory
delayedPersist*: KvtDbRef ## Enable next proggyback write session
delayedPersist*: KvtDbRef ## Enable next piggyback write session
KvtCFs* = enum
## Column family symbols/handles and names used on the database