-
Notifications
You must be signed in to change notification settings - Fork 78
Feature/etcm 967 db consistency check #1070
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d100da5
d1ba8a9
ec588e2
cfd9679
70f9679
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| package io.iohk.ethereum.nodebuilder.tooling | ||
|
|
||
| import akka.actor.typed.Behavior | ||
| import akka.actor.typed.scaladsl.Behaviors | ||
| import akka.actor.typed.scaladsl.TimerScheduler | ||
|
|
||
| import scala.concurrent.duration.DurationInt | ||
|
|
||
| import io.iohk.ethereum.db.storage.AppStateStorage | ||
| import io.iohk.ethereum.db.storage.BlockHeadersStorage | ||
| import io.iohk.ethereum.db.storage.BlockNumberMappingStorage | ||
| import io.iohk.ethereum.nodebuilder.tooling.PeriodicConsistencyCheck.ConsistencyCheck | ||
| import io.iohk.ethereum.utils.Logger | ||
|
|
||
| object PeriodicConsistencyCheck { | ||
| def start( | ||
| appStateStorage: AppStateStorage, | ||
| blockNumberMappingStorage: BlockNumberMappingStorage, | ||
| blockHeadersStorage: BlockHeadersStorage, | ||
| shutdown: () => Unit | ||
| ): Behavior[ConsistencyCheck] = | ||
| Behaviors.withTimers { timers => | ||
| tick(timers) | ||
| PeriodicConsistencyCheck(timers, appStateStorage, blockNumberMappingStorage, blockHeadersStorage, shutdown) | ||
| .check() | ||
| } | ||
|
|
||
| sealed trait ConsistencyCheck extends Product with Serializable | ||
| case object Tick extends ConsistencyCheck | ||
|
|
||
| def tick(timers: TimerScheduler[ConsistencyCheck]): Unit = | ||
| timers.startSingleTimer(Tick, 10.minutes) | ||
| } | ||
|
|
||
| case class PeriodicConsistencyCheck( | ||
| timers: TimerScheduler[ConsistencyCheck], | ||
| appStateStorage: AppStateStorage, | ||
| blockNumberMappingStorage: BlockNumberMappingStorage, | ||
| blockHeadersStorage: BlockHeadersStorage, | ||
| shutdown: () => Unit | ||
| ) extends Logger { | ||
| import PeriodicConsistencyCheck._ | ||
|
|
||
| def check(): Behavior[ConsistencyCheck] = Behaviors.receiveMessage { case Tick => | ||
| log.debug("Running a storageConsistency check") | ||
| StorageConsistencyChecker.checkStorageConsistency( | ||
| appStateStorage.getBestBlockNumber(), | ||
| blockNumberMappingStorage, | ||
| blockHeadersStorage, | ||
| shutdown | ||
| )(log) | ||
| tick(timers) | ||
| Behaviors.same | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package io.iohk.ethereum.nodebuilder.tooling | ||
|
|
||
| import com.typesafe.scalalogging.Logger | ||
|
|
||
| import io.iohk.ethereum.db.storage.BlockHeadersStorage | ||
| import io.iohk.ethereum.db.storage.BlockNumberMappingStorage | ||
|
|
||
| object StorageConsistencyChecker { | ||
| type ShutdownOp = () => Unit | ||
|
|
||
| val DefaultStep = 1000 | ||
|
|
||
| def checkStorageConsistency( | ||
| bestBlockNumber: BigInt, | ||
| blockNumberMappingStorage: BlockNumberMappingStorage, | ||
| blockHeadersStorage: BlockHeadersStorage, | ||
| shutdown: ShutdownOp, | ||
| step: Int = DefaultStep | ||
| )(implicit log: Logger): Unit = | ||
| Range(0, bestBlockNumber.intValue, step).foreach { idx => | ||
| (for { | ||
| hash <- blockNumberMappingStorage.get(idx) | ||
| _ <- blockHeadersStorage.get(hash) | ||
| } yield ()).fold { | ||
| log.error("Database seems to be in inconsistent state, shutting down") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't we include information on how the user should act when this happens? I guess how to delete the DB?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this a good place to add such documentation for the client? Not convinced, I think we have a mantis docs project.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In that case advising the user to check the website. But I think that saying nothing is the worse option :)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should log the missing block's hash and number. I'm not sure it would really helps us when this happens, but it does not hurt. |
||
| shutdown() | ||
| }(_ => ()) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if it makes sense to check every 1000th block. I imagine a case where the check passes but the db is inconsistent.
Perhaps it would be worthwhile to occasionally check the whole range?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a first pass. I want to start identifying the circumstances when clients loose consistency.