add BFT enforcement for bulk storage objects - #6438
Conversation
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
| NotUsed, | ||
| ] = { | ||
| Flow[(T, Seq[ObjectKeyAndChecksum])].mapAsync(parallelism = 1) { case (t, obj) => | ||
| Flow[(T, Seq[ObjectKeyAndChecksum])].flatMapConcat { case (t, obj) => |
There was a problem hiding this comment.
This was leaking pipelines, it created a new one that did not get destroyed when the main one was.
Signed-off-by: Itai Segall <itai.segall@digitalasset.com>
| x-jvm-package: scan | ||
| operationId: "getBulkObjectChecksums" | ||
| description: | | ||
| **Under Development, do not use in production yet** Get checksums for bulk history objects. Uses both staging and committed objects. |
There was a problem hiding this comment.
| **Under Development, do not use in production yet** Get checksums for bulk history objects. Uses both staging and committed objects. | |
| **Under Development, do not use in production yet** Get checksums for bulk history objects. Searches for object_keys in both staging and committed objects. |
Minor suggestion
| } | ||
| } | ||
|
|
||
| protected def closeScanConnection(): Option[SyncCloseable] = |
There was a problem hiding this comment.
This doesn't really close, it creates a SyncCloseable (could be confusing)
| httpClient: HttpClient, | ||
| templateJsonDecoder: TemplateJsonDecoder, | ||
| ): Future[BftScanConnection] = | ||
| blocking { |
There was a problem hiding this comment.
the mutex.exclusive looks like a special mutex to especially not having to use blocking:
Lock to be used instead of blocking synchronized
so I think the blocking should be removed.
|
|
||
| import scala.concurrent.{ExecutionContextExecutor, Future, blocking} | ||
|
|
||
| trait HasPeerBftScanConnection { |
There was a problem hiding this comment.
I'd make this a class that owns one connection instead of a trait.
As a trait, the connection state is mixed invisibly into the host class, and the dependencies are method parameters, but only the first caller's arguments are ever used, so a second call site passing a different store or config silently gets the wrong connection.
The mixer also has to remember to wire closeScanConnection() into its closing sequence.
Suggestion:
class PeerBftScanConnection(store: ScanStore, svName: String, ...) extends AutoCloseable {
@volatile private var started = false
lazy val connection: Future[BftScanConnection] = {
started = true
BftScanConnection.peerScanConnection(...)
}
override def close(): Unit = if (started) connection.foreach(_.close())
}
Constructor params pin the dependencies, lazy val gives thread-safe create-once semantics (no mutex, no var, no blocking), caching the future avoids creating two connections on concurrent first calls, and whoever constructs it closes it. Both return a closed connection after close(). But here that's a local owner bug (use-after-close), not a silent failure when calling getOrCreateScanConnection.
If we ever want this fully airtight (post-close access fails loudly with AbortedDueToShutdown, and close() waits for an in-flight creation instead of racing it), extending FlagCloseable and wrapping the accessor in synchronizeWithClosingF fixes that. For a connection closed once at node shutdown I don't think we need that here though.
ray-roestenburg-da
left a comment
There was a problem hiding this comment.
Looks good overall, please have a look at my comments re: HasPeerBftScanConnection
Fixes #6495
Pull Request Checklist
Cluster Testing
/cluster_teston this PR to request it, and ping someone with access to the DA-internal system to approve it./upgrade_teston this PR to request it, and ping someone with access to the DA-internal system to approve it./hdm_teston this PR to request it, and ping someone with access to the DA-internal system to approve it./lsu_teston this PR to request it, and ping someone with access to the DA-internal system to approve it.PR Guidelines
Fixes #n, and mention issues worked on using#nMerge Guidelines