mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 09:17:43 +03:00
ledger-on-memory: Only support pre-execution. [KVL-821] (#8757)
* ledger-on-memory: Rename `PreExecutingOwner` to just `Owner`. * ledger-on-memory: Push the committer execution context up a little. * ledger-on-memory: Use pre-execution in tests, not batching. * ledger-on-memory: Remove support for batching submissions. Pre-execution is pretty much always faster; let's use it. CHANGELOG_BEGIN CHANGELOG_END * ledger-on-memory: Simplify construction. Now we only support pre-execution, we can be less general.
This commit is contained in:
parent
e79966b890
commit
9c477ffdf5
@ -9,7 +9,7 @@ import java.util.stream.Collectors
|
|||||||
import com.daml.bazeltools.BazelRunfiles._
|
import com.daml.bazeltools.BazelRunfiles._
|
||||||
import com.daml.ledger.api.testing.utils.{AkkaBeforeAndAfterAll, OwnedResource, SuiteResource}
|
import com.daml.ledger.api.testing.utils.{AkkaBeforeAndAfterAll, OwnedResource, SuiteResource}
|
||||||
import com.daml.ledger.api.tls.TlsConfiguration
|
import com.daml.ledger.api.tls.TlsConfiguration
|
||||||
import com.daml.ledger.on.memory.{ExtraConfig, Owner}
|
import com.daml.ledger.on.memory.Owner
|
||||||
import com.daml.ledger.participant.state.kvutils.app.{ParticipantConfig, ParticipantRunMode}
|
import com.daml.ledger.participant.state.kvutils.app.{ParticipantConfig, ParticipantRunMode}
|
||||||
import com.daml.ledger.participant.state.kvutils.{app => kvutils}
|
import com.daml.ledger.participant.state.kvutils.{app => kvutils}
|
||||||
import com.daml.ledger.participant.state.v1
|
import com.daml.ledger.participant.state.v1
|
||||||
@ -73,15 +73,10 @@ trait MultiParticipantFixture
|
|||||||
for {
|
for {
|
||||||
_ <- Owner(
|
_ <- Owner(
|
||||||
kvutils.Config
|
kvutils.Config
|
||||||
.createDefault(ExtraConfig.reasonableDefault)
|
.createDefault(())
|
||||||
.copy(
|
.copy(
|
||||||
participants = Seq(
|
participants = Seq(participant1, participant2),
|
||||||
participant1,
|
archiveFiles = Seq(darFile),
|
||||||
participant2,
|
|
||||||
),
|
|
||||||
archiveFiles = Seq(
|
|
||||||
darFile
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} yield (readPortfile(participant1Portfile), readPortfile(participant2Portfile))
|
} yield (readPortfile(participant1Portfile), readPortfile(participant2Portfile))
|
||||||
|
@ -33,46 +33,13 @@ da_scala_library(
|
|||||||
"//ledger/metrics",
|
"//ledger/metrics",
|
||||||
"//ledger/participant-state",
|
"//ledger/participant-state",
|
||||||
"//ledger/participant-state/kvutils",
|
"//ledger/participant-state/kvutils",
|
||||||
"//libs-scala/concurrent",
|
|
||||||
"//libs-scala/contextualized-logging",
|
"//libs-scala/contextualized-logging",
|
||||||
"//libs-scala/resources",
|
"//libs-scala/resources",
|
||||||
"//libs-scala/resources-akka",
|
|
||||||
"//libs-scala/resources-grpc",
|
|
||||||
"@maven//:com_google_protobuf_protobuf_java",
|
"@maven//:com_google_protobuf_protobuf_java",
|
||||||
"@maven//:io_dropwizard_metrics_metrics_core",
|
"@maven//:io_dropwizard_metrics_metrics_core",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
da_scala_library(
|
|
||||||
name = "ledger-on-memory-test-lib",
|
|
||||||
srcs = glob(["src/test/lib/scala/**/*.scala"]),
|
|
||||||
scala_deps = [
|
|
||||||
"@maven//:com_typesafe_akka_akka_actor",
|
|
||||||
"@maven//:com_typesafe_akka_akka_stream",
|
|
||||||
"@maven//:org_scalactic_scalactic",
|
|
||||||
"@maven//:org_scalatest_scalatest",
|
|
||||||
],
|
|
||||||
deps = [
|
|
||||||
":ledger-on-memory",
|
|
||||||
"//daml-lf/data",
|
|
||||||
"//daml-lf/engine",
|
|
||||||
"//language-support/scala/bindings",
|
|
||||||
"//ledger-api/rs-grpc-bridge",
|
|
||||||
"//ledger-api/testing-utils",
|
|
||||||
"//ledger/caching",
|
|
||||||
"//ledger/ledger-api-common",
|
|
||||||
"//ledger/ledger-api-health",
|
|
||||||
"//ledger/ledger-resources",
|
|
||||||
"//ledger/ledger-resources:ledger-resources-test-lib",
|
|
||||||
"//ledger/metrics",
|
|
||||||
"//ledger/participant-state",
|
|
||||||
"//ledger/participant-state/kvutils",
|
|
||||||
"//ledger/participant-state/kvutils:kvutils-tests-lib",
|
|
||||||
"//libs-scala/contextualized-logging",
|
|
||||||
"//libs-scala/resources",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
da_scala_test_suite(
|
da_scala_test_suite(
|
||||||
name = "ledger-on-memory-tests",
|
name = "ledger-on-memory-tests",
|
||||||
size = "small",
|
size = "small",
|
||||||
@ -94,11 +61,12 @@ da_scala_test_suite(
|
|||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
":ledger-on-memory",
|
":ledger-on-memory",
|
||||||
":ledger-on-memory-test-lib",
|
|
||||||
"//daml-lf/data",
|
"//daml-lf/data",
|
||||||
|
"//daml-lf/engine",
|
||||||
"//language-support/scala/bindings",
|
"//language-support/scala/bindings",
|
||||||
"//ledger-api/rs-grpc-bridge",
|
"//ledger-api/rs-grpc-bridge",
|
||||||
"//ledger-api/testing-utils",
|
"//ledger-api/testing-utils",
|
||||||
|
"//ledger/caching",
|
||||||
"//ledger/ledger-api-common",
|
"//ledger/ledger-api-common",
|
||||||
"//ledger/ledger-api-health",
|
"//ledger/ledger-api-health",
|
||||||
"//ledger/ledger-resources",
|
"//ledger/ledger-resources",
|
||||||
@ -109,6 +77,8 @@ da_scala_test_suite(
|
|||||||
"//ledger/participant-state/kvutils:kvutils-tests-lib",
|
"//ledger/participant-state/kvutils:kvutils-tests-lib",
|
||||||
"//libs-scala/contextualized-logging",
|
"//libs-scala/contextualized-logging",
|
||||||
"//libs-scala/resources",
|
"//libs-scala/resources",
|
||||||
|
"//libs-scala/resources-akka",
|
||||||
|
"//libs-scala/resources-grpc",
|
||||||
"@maven//:io_dropwizard_metrics_metrics_core",
|
"@maven//:io_dropwizard_metrics_metrics_core",
|
||||||
"@maven//:org_mockito_mockito_core",
|
"@maven//:org_mockito_mockito_core",
|
||||||
],
|
],
|
||||||
@ -164,23 +134,7 @@ conformance_test(
|
|||||||
server = ":app",
|
server = ":app",
|
||||||
server_args = [
|
server_args = [
|
||||||
"--contract-id-seeding=testing-weak",
|
"--contract-id-seeding=testing-weak",
|
||||||
"--participant participant-id=example,port=6865",
|
"--participant=participant-id=example,port=6865",
|
||||||
"--batching enable=true,max-batch-size-bytes=262144",
|
|
||||||
],
|
|
||||||
test_tool_args = [
|
|
||||||
"--verbose",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
conformance_test(
|
|
||||||
name = "conformance-test-pre-execution",
|
|
||||||
ports = [6865],
|
|
||||||
server = ":app",
|
|
||||||
server_args = [
|
|
||||||
"--contract-id-seeding=testing-weak",
|
|
||||||
"--participant participant-id=example,port=6865",
|
|
||||||
"--batching enable=false",
|
|
||||||
"--force-pre-execution=true",
|
|
||||||
],
|
],
|
||||||
test_tool_args = [
|
test_tool_args = [
|
||||||
"--verbose",
|
"--verbose",
|
||||||
@ -196,9 +150,8 @@ conformance_test(
|
|||||||
server = ":app",
|
server = ":app",
|
||||||
server_args = [
|
server_args = [
|
||||||
"--contract-id-seeding=testing-weak",
|
"--contract-id-seeding=testing-weak",
|
||||||
"--participant participant-id=example1,port=6865",
|
"--participant=participant-id=example1,port=6865",
|
||||||
"--participant participant-id=example2,port=6866",
|
"--participant=participant-id=example2,port=6866",
|
||||||
"--batching enable=true,max-batch-size-bytes=262144",
|
|
||||||
],
|
],
|
||||||
test_tool_args = [
|
test_tool_args = [
|
||||||
"--verbose",
|
"--verbose",
|
||||||
@ -214,9 +167,8 @@ conformance_test(
|
|||||||
server = ":app",
|
server = ":app",
|
||||||
server_args = [
|
server_args = [
|
||||||
"--contract-id-seeding=testing-weak",
|
"--contract-id-seeding=testing-weak",
|
||||||
"--participant participant-id=split-example,port=6865,server-jdbc-url=jdbc:h2:mem:split-example;db_close_delay=-1;db_close_on_exit=false,shard-name=server1,run-mode=ledger-api-server",
|
"--participant=participant-id=split-example,port=6865,server-jdbc-url=jdbc:h2:mem:split-example;db_close_delay=-1;db_close_on_exit=false,shard-name=server1,run-mode=ledger-api-server",
|
||||||
"--participant participant-id=split-example,port=6865,server-jdbc-url=jdbc:h2:mem:split-example;db_close_delay=-1;db_close_on_exit=false,shard-name=indexer,run-mode=indexer",
|
"--participant=participant-id=split-example,port=6865,server-jdbc-url=jdbc:h2:mem:split-example;db_close_delay=-1;db_close_on_exit=false,shard-name=indexer,run-mode=indexer",
|
||||||
"--batching enable=true,max-batch-size-bytes=262144",
|
|
||||||
],
|
],
|
||||||
test_tool_args = [
|
test_tool_args = [
|
||||||
"--verbose",
|
"--verbose",
|
||||||
@ -230,8 +182,7 @@ conformance_test(
|
|||||||
server = ":app",
|
server = ":app",
|
||||||
server_args = [
|
server_args = [
|
||||||
"--contract-id-seeding=testing-weak",
|
"--contract-id-seeding=testing-weak",
|
||||||
"--participant participant-id=example,port=6865",
|
"--participant=participant-id=example,port=6865",
|
||||||
"--batching enable=true,max-batch-size-bytes=262144",
|
|
||||||
],
|
],
|
||||||
test_tool_args = [
|
test_tool_args = [
|
||||||
"--verbose",
|
"--verbose",
|
||||||
@ -245,8 +196,7 @@ conformance_test(
|
|||||||
server = ":app",
|
server = ":app",
|
||||||
server_args = [
|
server_args = [
|
||||||
"--contract-id-seeding=testing-weak",
|
"--contract-id-seeding=testing-weak",
|
||||||
"--participant participant-id=example,port=6865",
|
"--participant=participant-id=example,port=6865",
|
||||||
"--batching enable=true,max-batch-size-bytes=262144",
|
|
||||||
],
|
],
|
||||||
test_tool_args = [
|
test_tool_args = [
|
||||||
"--verbose",
|
"--verbose",
|
||||||
@ -260,7 +210,7 @@ conformance_test(
|
|||||||
server = ":app",
|
server = ":app",
|
||||||
server_args = [
|
server_args = [
|
||||||
"--contract-id-seeding=testing-weak",
|
"--contract-id-seeding=testing-weak",
|
||||||
"--participant participant-id=example,port=6865",
|
"--participant=participant-id=example,port=6865",
|
||||||
],
|
],
|
||||||
test_tool_args = [
|
test_tool_args = [
|
||||||
"--verbose",
|
"--verbose",
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
// Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package com.daml.ledger.on.memory
|
|
||||||
|
|
||||||
import com.daml.ledger.participant.state.kvutils.api.BatchingLedgerWriterConfig
|
|
||||||
|
|
||||||
final case class ExtraConfig(
|
|
||||||
batchingLedgerWriterConfig: BatchingLedgerWriterConfig,
|
|
||||||
alwaysPreExecute: Boolean,
|
|
||||||
)
|
|
||||||
|
|
||||||
object ExtraConfig {
|
|
||||||
val reasonableDefault: ExtraConfig =
|
|
||||||
ExtraConfig(
|
|
||||||
batchingLedgerWriterConfig =
|
|
||||||
BatchingLedgerWriterConfig.reasonableDefault.copy(maxBatchConcurrentCommits = 2),
|
|
||||||
alwaysPreExecute = false,
|
|
||||||
)
|
|
||||||
}
|
|
@ -5,13 +5,7 @@ package com.daml.ledger.on.memory
|
|||||||
|
|
||||||
import akka.stream.Materializer
|
import akka.stream.Materializer
|
||||||
import com.daml.caching
|
import com.daml.caching
|
||||||
import com.daml.ledger.participant.state.kvutils.api.{
|
import com.daml.ledger.participant.state.kvutils.api.KeyValueParticipantState
|
||||||
BatchingLedgerWriterConfig,
|
|
||||||
KeyValueLedger,
|
|
||||||
KeyValueParticipantState,
|
|
||||||
}
|
|
||||||
import com.daml.ledger.participant.state.kvutils.app.batch.BatchingLedgerWriterConfigReader
|
|
||||||
import com.daml.ledger.participant.state.kvutils.app.batch.BatchingLedgerWriterConfigReader.optionsReader
|
|
||||||
import com.daml.ledger.participant.state.kvutils.app.{Config, LedgerFactory, ParticipantConfig}
|
import com.daml.ledger.participant.state.kvutils.app.{Config, LedgerFactory, ParticipantConfig}
|
||||||
import com.daml.ledger.participant.state.kvutils.caching.`Message Weight`
|
import com.daml.ledger.participant.state.kvutils.caching.`Message Weight`
|
||||||
import com.daml.ledger.resources.ResourceOwner
|
import com.daml.ledger.resources.ResourceOwner
|
||||||
@ -23,30 +17,19 @@ import com.daml.platform.configuration.LedgerConfiguration
|
|||||||
import scopt.OptionParser
|
import scopt.OptionParser
|
||||||
|
|
||||||
private[memory] class InMemoryLedgerFactory(dispatcher: Dispatcher[Index], state: InMemoryState)
|
private[memory] class InMemoryLedgerFactory(dispatcher: Dispatcher[Index], state: InMemoryState)
|
||||||
extends LedgerFactory[KeyValueParticipantState, ExtraConfig] {
|
extends LedgerFactory[KeyValueParticipantState, Unit] {
|
||||||
|
|
||||||
override final def readWriteServiceOwner(
|
override final def readWriteServiceOwner(
|
||||||
config: Config[ExtraConfig],
|
config: Config[Unit],
|
||||||
participantConfig: ParticipantConfig,
|
participantConfig: ParticipantConfig,
|
||||||
engine: Engine,
|
engine: Engine,
|
||||||
)(implicit
|
)(implicit
|
||||||
materializer: Materializer,
|
materializer: Materializer,
|
||||||
loggingContext: LoggingContext,
|
loggingContext: LoggingContext,
|
||||||
): ResourceOwner[KeyValueParticipantState] =
|
): ResourceOwner[KeyValueParticipantState] = {
|
||||||
for {
|
|
||||||
readerWriter <- owner(config, participantConfig, engine)
|
|
||||||
} yield new KeyValueParticipantState(
|
|
||||||
readerWriter,
|
|
||||||
readerWriter,
|
|
||||||
createMetrics(participantConfig, config),
|
|
||||||
)
|
|
||||||
|
|
||||||
def owner(config: Config[ExtraConfig], participantConfig: ParticipantConfig, engine: Engine)(
|
|
||||||
implicit materializer: Materializer
|
|
||||||
): ResourceOwner[KeyValueLedger] = {
|
|
||||||
val metrics = createMetrics(participantConfig, config)
|
val metrics = createMetrics(participantConfig, config)
|
||||||
if (config.extra.alwaysPreExecute)
|
for {
|
||||||
new InMemoryLedgerReaderWriter.PreExecutingOwner(
|
readerWriter <- new InMemoryLedgerReaderWriter.Owner(
|
||||||
ledgerId = config.ledgerId,
|
ledgerId = config.ledgerId,
|
||||||
participantId = participantConfig.participantId,
|
participantId = participantConfig.participantId,
|
||||||
keySerializationStrategy = DefaultStateKeySerializationStrategy,
|
keySerializationStrategy = DefaultStateKeySerializationStrategy,
|
||||||
@ -58,64 +41,19 @@ private[memory] class InMemoryLedgerFactory(dispatcher: Dispatcher[Index], state
|
|||||||
dispatcher = dispatcher,
|
dispatcher = dispatcher,
|
||||||
state = state,
|
state = state,
|
||||||
engine = engine,
|
engine = engine,
|
||||||
|
committerExecutionContext = materializer.executionContext,
|
||||||
)
|
)
|
||||||
else
|
} yield new KeyValueParticipantState(
|
||||||
new InMemoryLedgerReaderWriter.BatchingOwner(
|
readerWriter,
|
||||||
ledgerId = config.ledgerId,
|
readerWriter,
|
||||||
batchingLedgerWriterConfig = config.extra.batchingLedgerWriterConfig,
|
createMetrics(participantConfig, config),
|
||||||
participantId = participantConfig.participantId,
|
)
|
||||||
metrics = metrics,
|
|
||||||
stateValueCache = caching.WeightedCache.from(
|
|
||||||
configuration = config.stateValueCache,
|
|
||||||
metrics = metrics.daml.kvutils.submission.validator.stateValueCache,
|
|
||||||
),
|
|
||||||
dispatcher = dispatcher,
|
|
||||||
state = state,
|
|
||||||
engine = engine,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override def ledgerConfig(config: Config[ExtraConfig]): LedgerConfiguration =
|
override def ledgerConfig(config: Config[Unit]): LedgerConfiguration =
|
||||||
LedgerConfiguration.defaultLocalLedger
|
LedgerConfiguration.defaultLocalLedger
|
||||||
|
|
||||||
override def extraConfigParser(parser: OptionParser[Config[ExtraConfig]]): Unit =
|
override def extraConfigParser(parser: OptionParser[Config[Unit]]): Unit = ()
|
||||||
InMemoryLedgerFactory.extraConfigParser(parser)
|
|
||||||
|
|
||||||
override val defaultExtraConfig: ExtraConfig = InMemoryLedgerFactory.defaultExtraConfig
|
override val defaultExtraConfig: Unit = ()
|
||||||
}
|
|
||||||
|
|
||||||
private[memory] object InMemoryLedgerFactory {
|
|
||||||
val defaultExtraConfig: ExtraConfig = ExtraConfig.reasonableDefault
|
|
||||||
|
|
||||||
final def extraConfigParser(parser: OptionParser[Config[ExtraConfig]]): Unit = {
|
|
||||||
parser
|
|
||||||
.opt[BatchingLedgerWriterConfig]("batching")
|
|
||||||
.optional()
|
|
||||||
.text(BatchingLedgerWriterConfigReader.UsageText)
|
|
||||||
.action { case (parsedBatchingConfig, config) =>
|
|
||||||
config.copy(
|
|
||||||
extra = config.extra.copy(
|
|
||||||
batchingLedgerWriterConfig = parsedBatchingConfig
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
parser
|
|
||||||
.opt[Boolean]("force-pre-execution")
|
|
||||||
.optional()
|
|
||||||
.text("Force pre-execution (mutually exclusive with batching)")
|
|
||||||
.action { case (preExecute, config) =>
|
|
||||||
config.copy(
|
|
||||||
extra = config.extra.copy(
|
|
||||||
alwaysPreExecute = preExecute
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
parser.checkConfig { config =>
|
|
||||||
if (config.extra.alwaysPreExecute && config.extra.batchingLedgerWriterConfig.enableBatching)
|
|
||||||
Left("Either pre-executing can be forced or batching can be enabled, but not both.")
|
|
||||||
else
|
|
||||||
Right(())
|
|
||||||
}
|
|
||||||
()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,7 @@ import com.daml.resources.ProgramResource
|
|||||||
object Main {
|
object Main {
|
||||||
def main(args: Array[String]): Unit = {
|
def main(args: Array[String]): Unit = {
|
||||||
val resource = for {
|
val resource = for {
|
||||||
config <- Config.owner(
|
config <- Config.ownerWithoutExtras(RunnerName, args)
|
||||||
RunnerName,
|
|
||||||
InMemoryLedgerFactory.extraConfigParser,
|
|
||||||
InMemoryLedgerFactory.defaultExtraConfig,
|
|
||||||
args,
|
|
||||||
)
|
|
||||||
owner <- Owner(config)
|
owner <- Owner(config)
|
||||||
} yield owner
|
} yield owner
|
||||||
new ProgramResource(resource).run(ResourceContext.apply)
|
new ProgramResource(resource).run(ResourceContext.apply)
|
||||||
|
@ -8,7 +8,7 @@ import com.daml.ledger.resources.ResourceOwner
|
|||||||
|
|
||||||
object Owner {
|
object Owner {
|
||||||
// Utily if you want to spin this up as a library.
|
// Utily if you want to spin this up as a library.
|
||||||
def apply(config: Config[ExtraConfig]): ResourceOwner[Unit] =
|
def apply(config: Config[Unit]): ResourceOwner[Unit] =
|
||||||
for {
|
for {
|
||||||
dispatcher <- dispatcherOwner
|
dispatcher <- dispatcherOwner
|
||||||
sharedState = InMemoryState.empty
|
sharedState = InMemoryState.empty
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
package com.daml.ledger.on.memory
|
package com.daml.ledger.on.memory
|
||||||
|
|
||||||
import akka.stream.Materializer
|
|
||||||
import com.daml.api.util.TimeProvider
|
import com.daml.api.util.TimeProvider
|
||||||
import com.daml.caching.Cache
|
import com.daml.caching.Cache
|
||||||
import com.daml.ledger.participant.state.kvutils.api._
|
import com.daml.ledger.participant.state.kvutils.api._
|
||||||
@ -14,67 +13,11 @@ import com.daml.lf.engine.Engine
|
|||||||
import com.daml.metrics.Metrics
|
import com.daml.metrics.Metrics
|
||||||
import com.daml.platform.akkastreams.dispatcher.Dispatcher
|
import com.daml.platform.akkastreams.dispatcher.Dispatcher
|
||||||
|
|
||||||
|
import scala.concurrent.ExecutionContext
|
||||||
|
|
||||||
object InMemoryLedgerReaderWriter {
|
object InMemoryLedgerReaderWriter {
|
||||||
|
|
||||||
final class BatchingOwner(
|
final class Owner(
|
||||||
ledgerId: LedgerId,
|
|
||||||
batchingLedgerWriterConfig: BatchingLedgerWriterConfig,
|
|
||||||
participantId: ParticipantId,
|
|
||||||
metrics: Metrics,
|
|
||||||
timeProvider: TimeProvider = InMemoryLedgerWriter.DefaultTimeProvider,
|
|
||||||
stateValueCache: InMemoryLedgerWriter.StateValueCache = Cache.none,
|
|
||||||
dispatcher: Dispatcher[Index],
|
|
||||||
state: InMemoryState,
|
|
||||||
engine: Engine,
|
|
||||||
)(implicit materializer: Materializer)
|
|
||||||
extends ResourceOwner[KeyValueLedger] {
|
|
||||||
override def acquire()(implicit context: ResourceContext): Resource[KeyValueLedger] = {
|
|
||||||
val reader = new InMemoryLedgerReader(ledgerId, dispatcher, state, metrics)
|
|
||||||
for {
|
|
||||||
writer <- new InMemoryLedgerWriter.BatchingOwner(
|
|
||||||
batchingLedgerWriterConfig,
|
|
||||||
participantId,
|
|
||||||
metrics,
|
|
||||||
timeProvider,
|
|
||||||
stateValueCache,
|
|
||||||
dispatcher,
|
|
||||||
state,
|
|
||||||
engine,
|
|
||||||
).acquire()
|
|
||||||
} yield createKeyValueLedger(reader, writer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class SingleParticipantBatchingOwner(
|
|
||||||
ledgerId: LedgerId,
|
|
||||||
batchingLedgerWriterConfig: BatchingLedgerWriterConfig,
|
|
||||||
participantId: ParticipantId,
|
|
||||||
timeProvider: TimeProvider = InMemoryLedgerWriter.DefaultTimeProvider,
|
|
||||||
stateValueCache: InMemoryLedgerWriter.StateValueCache = Cache.none,
|
|
||||||
metrics: Metrics,
|
|
||||||
engine: Engine,
|
|
||||||
)(implicit materializer: Materializer)
|
|
||||||
extends ResourceOwner[KeyValueLedger] {
|
|
||||||
override def acquire()(implicit context: ResourceContext): Resource[KeyValueLedger] = {
|
|
||||||
val state = InMemoryState.empty
|
|
||||||
for {
|
|
||||||
dispatcher <- dispatcherOwner.acquire()
|
|
||||||
readerWriter <- new BatchingOwner(
|
|
||||||
ledgerId,
|
|
||||||
batchingLedgerWriterConfig,
|
|
||||||
participantId,
|
|
||||||
metrics,
|
|
||||||
timeProvider,
|
|
||||||
stateValueCache,
|
|
||||||
dispatcher,
|
|
||||||
state,
|
|
||||||
engine,
|
|
||||||
).acquire()
|
|
||||||
} yield readerWriter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class PreExecutingOwner(
|
|
||||||
ledgerId: LedgerId,
|
ledgerId: LedgerId,
|
||||||
participantId: ParticipantId,
|
participantId: ParticipantId,
|
||||||
keySerializationStrategy: StateKeySerializationStrategy,
|
keySerializationStrategy: StateKeySerializationStrategy,
|
||||||
@ -84,12 +27,12 @@ object InMemoryLedgerReaderWriter {
|
|||||||
dispatcher: Dispatcher[Index],
|
dispatcher: Dispatcher[Index],
|
||||||
state: InMemoryState,
|
state: InMemoryState,
|
||||||
engine: Engine,
|
engine: Engine,
|
||||||
)(implicit materializer: Materializer)
|
committerExecutionContext: ExecutionContext,
|
||||||
extends ResourceOwner[KeyValueLedger] {
|
) extends ResourceOwner[KeyValueLedger] {
|
||||||
override def acquire()(implicit context: ResourceContext): Resource[KeyValueLedger] = {
|
override def acquire()(implicit context: ResourceContext): Resource[KeyValueLedger] = {
|
||||||
val reader = new InMemoryLedgerReader(ledgerId, dispatcher, state, metrics)
|
val reader = new InMemoryLedgerReader(ledgerId, dispatcher, state, metrics)
|
||||||
for {
|
for {
|
||||||
writer <- new InMemoryLedgerWriter.PreExecutingOwner(
|
writer <- new InMemoryLedgerWriter.Owner(
|
||||||
participantId,
|
participantId,
|
||||||
keySerializationStrategy,
|
keySerializationStrategy,
|
||||||
metrics,
|
metrics,
|
||||||
@ -98,6 +41,7 @@ object InMemoryLedgerReaderWriter {
|
|||||||
dispatcher,
|
dispatcher,
|
||||||
state,
|
state,
|
||||||
engine,
|
engine,
|
||||||
|
committerExecutionContext,
|
||||||
).acquire()
|
).acquire()
|
||||||
} yield createKeyValueLedger(reader, writer)
|
} yield createKeyValueLedger(reader, writer)
|
||||||
}
|
}
|
||||||
|
@ -3,28 +3,18 @@
|
|||||||
|
|
||||||
package com.daml.ledger.on.memory
|
package com.daml.ledger.on.memory
|
||||||
|
|
||||||
import akka.stream.Materializer
|
import java.time.Instant
|
||||||
|
|
||||||
import com.daml.api.util.TimeProvider
|
import com.daml.api.util.TimeProvider
|
||||||
import com.daml.caching.Cache
|
import com.daml.caching.Cache
|
||||||
import com.daml.dec.DirectExecutionContext
|
|
||||||
import com.daml.ledger.api.health.{HealthStatus, Healthy}
|
import com.daml.ledger.api.health.{HealthStatus, Healthy}
|
||||||
|
import com.daml.ledger.on.memory.InMemoryLedgerWriter._
|
||||||
import com.daml.ledger.participant.state.kvutils.DamlKvutils.{DamlStateKey, DamlStateValue}
|
import com.daml.ledger.participant.state.kvutils.DamlKvutils.{DamlStateKey, DamlStateValue}
|
||||||
import com.daml.ledger.participant.state.kvutils.api.{
|
import com.daml.ledger.participant.state.kvutils.api.{CommitMetadata, LedgerWriter}
|
||||||
BatchingLedgerWriter,
|
|
||||||
BatchingLedgerWriterConfig,
|
|
||||||
CommitMetadata,
|
|
||||||
LedgerWriter,
|
|
||||||
}
|
|
||||||
import com.daml.ledger.participant.state.kvutils.export.LedgerDataExporter
|
import com.daml.ledger.participant.state.kvutils.export.LedgerDataExporter
|
||||||
import com.daml.ledger.participant.state.kvutils.{KeyValueCommitting, Raw}
|
import com.daml.ledger.participant.state.kvutils.{KeyValueCommitting, Raw}
|
||||||
import com.daml.ledger.participant.state.v1.{ParticipantId, SubmissionResult}
|
import com.daml.ledger.participant.state.v1.{ParticipantId, SubmissionResult}
|
||||||
import com.daml.ledger.resources.{Resource, ResourceContext, ResourceOwner}
|
import com.daml.ledger.resources.{Resource, ResourceContext, ResourceOwner}
|
||||||
import com.daml.ledger.validator.batch.{
|
|
||||||
BatchedSubmissionValidator,
|
|
||||||
BatchedSubmissionValidatorFactory,
|
|
||||||
BatchedValidatingCommitter,
|
|
||||||
ConflictDetection,
|
|
||||||
}
|
|
||||||
import com.daml.ledger.validator.caching.{CachingStateReader, ImmutablesOnlyCacheUpdatePolicy}
|
import com.daml.ledger.validator.caching.{CachingStateReader, ImmutablesOnlyCacheUpdatePolicy}
|
||||||
import com.daml.ledger.validator.preexecution.{
|
import com.daml.ledger.validator.preexecution.{
|
||||||
EqualityBasedPostExecutionConflictDetector,
|
EqualityBasedPostExecutionConflictDetector,
|
||||||
@ -36,13 +26,8 @@ import com.daml.ledger.validator.preexecution.{
|
|||||||
TimeBasedWriteSetSelector,
|
TimeBasedWriteSetSelector,
|
||||||
}
|
}
|
||||||
import com.daml.ledger.validator.reading.{DamlLedgerStateReader, LedgerStateReader}
|
import com.daml.ledger.validator.reading.{DamlLedgerStateReader, LedgerStateReader}
|
||||||
import com.daml.ledger.validator.{
|
import com.daml.ledger.validator.{SerializingStateReader, StateKeySerializationStrategy}
|
||||||
SerializingStateReader,
|
|
||||||
StateKeySerializationStrategy,
|
|
||||||
ValidateAndCommit,
|
|
||||||
}
|
|
||||||
import com.daml.lf.engine.Engine
|
import com.daml.lf.engine.Engine
|
||||||
import com.daml.logging.LoggingContext.newLoggingContext
|
|
||||||
import com.daml.metrics.Metrics
|
import com.daml.metrics.Metrics
|
||||||
import com.daml.platform.akkastreams.dispatcher.Dispatcher
|
import com.daml.platform.akkastreams.dispatcher.Dispatcher
|
||||||
|
|
||||||
@ -52,18 +37,28 @@ import scala.util.Success
|
|||||||
final class InMemoryLedgerWriter private[memory] (
|
final class InMemoryLedgerWriter private[memory] (
|
||||||
override val participantId: ParticipantId,
|
override val participantId: ParticipantId,
|
||||||
dispatcher: Dispatcher[Index],
|
dispatcher: Dispatcher[Index],
|
||||||
|
now: () => Instant,
|
||||||
state: InMemoryState,
|
state: InMemoryState,
|
||||||
validateAndCommit: ValidateAndCommit,
|
committer: Committer,
|
||||||
|
committerExecutionContext: ExecutionContext,
|
||||||
|
metrics: Metrics,
|
||||||
) extends LedgerWriter {
|
) extends LedgerWriter {
|
||||||
override def commit(
|
override def commit(
|
||||||
correlationId: String,
|
correlationId: String,
|
||||||
envelope: Raw.Value,
|
envelope: Raw.Value,
|
||||||
metadata: CommitMetadata,
|
metadata: CommitMetadata,
|
||||||
): Future[SubmissionResult] =
|
): Future[SubmissionResult] =
|
||||||
validateAndCommit(correlationId, envelope, participantId)
|
committer
|
||||||
|
.commit(
|
||||||
|
participantId,
|
||||||
|
correlationId,
|
||||||
|
envelope,
|
||||||
|
exportRecordTime = now(),
|
||||||
|
ledgerStateAccess = new InMemoryLedgerStateAccess(state, metrics),
|
||||||
|
)(committerExecutionContext)
|
||||||
.andThen { case Success(SubmissionResult.Acknowledged) =>
|
.andThen { case Success(SubmissionResult.Acknowledged) =>
|
||||||
dispatcher.signalNewHead(state.newHeadSinceLastWrite())
|
dispatcher.signalNewHead(state.newHeadSinceLastWrite())
|
||||||
}(DirectExecutionContext)
|
}(committerExecutionContext)
|
||||||
|
|
||||||
override def currentHealth(): HealthStatus = Healthy
|
override def currentHealth(): HealthStatus = Healthy
|
||||||
}
|
}
|
||||||
@ -74,74 +69,13 @@ object InMemoryLedgerWriter {
|
|||||||
|
|
||||||
private[memory] type StateValueCache = Cache[DamlStateKey, DamlStateValue]
|
private[memory] type StateValueCache = Cache[DamlStateKey, DamlStateValue]
|
||||||
|
|
||||||
final class BatchingOwner(
|
private[memory] type Committer = PreExecutingValidatingCommitter[
|
||||||
batchingLedgerWriterConfig: BatchingLedgerWriterConfig,
|
Option[DamlStateValue],
|
||||||
participantId: ParticipantId,
|
RawPreExecutingCommitStrategy.ReadSet,
|
||||||
metrics: Metrics,
|
RawKeyValuePairsWithLogEntry,
|
||||||
timeProvider: TimeProvider = DefaultTimeProvider,
|
]
|
||||||
stateValueCache: StateValueCache = Cache.none,
|
|
||||||
dispatcher: Dispatcher[Index],
|
|
||||||
state: InMemoryState,
|
|
||||||
engine: Engine,
|
|
||||||
)(implicit materializer: Materializer)
|
|
||||||
extends ResourceOwner[LedgerWriter] {
|
|
||||||
override def acquire()(implicit context: ResourceContext): Resource[LedgerWriter] =
|
|
||||||
for {
|
|
||||||
ledgerDataExporter <- LedgerDataExporter.Owner.acquire()
|
|
||||||
keyValueCommitting = createKeyValueCommitting(metrics, timeProvider, engine)
|
|
||||||
committer = createBatchedCommitter(keyValueCommitting, ledgerDataExporter)
|
|
||||||
writer = new InMemoryLedgerWriter(participantId, dispatcher, state, committer)
|
|
||||||
// We need to generate batched submissions for the validator in order to improve throughput.
|
|
||||||
// Hence, we have a BatchingLedgerWriter collect and forward batched submissions to the
|
|
||||||
// in-memory committer.
|
|
||||||
batchingWriter <- newLoggingContext { implicit loggingContext =>
|
|
||||||
ResourceOwner
|
|
||||||
.forCloseable(() => BatchingLedgerWriter(batchingLedgerWriterConfig, writer))
|
|
||||||
.acquire()
|
|
||||||
}
|
|
||||||
} yield batchingWriter
|
|
||||||
|
|
||||||
private def createBatchedCommitter(
|
final class Owner(
|
||||||
keyValueCommitting: KeyValueCommitting,
|
|
||||||
ledgerDataExporter: LedgerDataExporter,
|
|
||||||
)(implicit materializer: Materializer): ValidateAndCommit = {
|
|
||||||
val validator = BatchedSubmissionValidator[Index](
|
|
||||||
BatchedSubmissionValidatorFactory.defaultParametersFor(
|
|
||||||
batchingLedgerWriterConfig.enableBatching
|
|
||||||
),
|
|
||||||
keyValueCommitting,
|
|
||||||
new ConflictDetection(metrics),
|
|
||||||
metrics,
|
|
||||||
ledgerDataExporter,
|
|
||||||
)
|
|
||||||
val committer = BatchedValidatingCommitter[Index](
|
|
||||||
() => timeProvider.getCurrentTime,
|
|
||||||
validator,
|
|
||||||
stateValueCache,
|
|
||||||
)
|
|
||||||
locally {
|
|
||||||
implicit val executionContext: ExecutionContext = materializer.executionContext
|
|
||||||
|
|
||||||
def validateAndCommit(
|
|
||||||
correlationId: String,
|
|
||||||
submissionEnvelope: Raw.Value,
|
|
||||||
submittingParticipantId: ParticipantId,
|
|
||||||
) =
|
|
||||||
new InMemoryLedgerStateAccess(state, metrics).inTransaction { ledgerStateOperations =>
|
|
||||||
committer.commit(
|
|
||||||
correlationId,
|
|
||||||
submissionEnvelope,
|
|
||||||
submittingParticipantId,
|
|
||||||
ledgerStateOperations,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
validateAndCommit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class PreExecutingOwner(
|
|
||||||
participantId: ParticipantId,
|
participantId: ParticipantId,
|
||||||
keySerializationStrategy: StateKeySerializationStrategy,
|
keySerializationStrategy: StateKeySerializationStrategy,
|
||||||
metrics: Metrics,
|
metrics: Metrics,
|
||||||
@ -150,28 +84,30 @@ object InMemoryLedgerWriter {
|
|||||||
dispatcher: Dispatcher[Index],
|
dispatcher: Dispatcher[Index],
|
||||||
state: InMemoryState,
|
state: InMemoryState,
|
||||||
engine: Engine,
|
engine: Engine,
|
||||||
)(implicit materializer: Materializer)
|
committerExecutionContext: ExecutionContext,
|
||||||
extends ResourceOwner[LedgerWriter] {
|
) extends ResourceOwner[LedgerWriter] {
|
||||||
override def acquire()(implicit context: ResourceContext): Resource[LedgerWriter] = {
|
private val now = () => timeProvider.getCurrentTime
|
||||||
val keyValueCommitting = createKeyValueCommitting(metrics, timeProvider, engine)
|
|
||||||
|
override def acquire()(implicit context: ResourceContext): Resource[LedgerWriter] =
|
||||||
for {
|
for {
|
||||||
ledgerDataExporter <- LedgerDataExporter.Owner.acquire()
|
ledgerDataExporter <- LedgerDataExporter.Owner.acquire()
|
||||||
} yield {
|
} yield new InMemoryLedgerWriter(
|
||||||
val committer = createPreExecutingCommitter(keyValueCommitting, ledgerDataExporter)
|
participantId,
|
||||||
new InMemoryLedgerWriter(participantId, dispatcher, state, committer)
|
dispatcher,
|
||||||
}
|
now,
|
||||||
}
|
state,
|
||||||
|
newCommitter(ledgerDataExporter),
|
||||||
|
committerExecutionContext,
|
||||||
|
metrics,
|
||||||
|
)
|
||||||
|
|
||||||
private def createPreExecutingCommitter(
|
private def newCommitter(ledgerDataExporter: LedgerDataExporter): Committer = {
|
||||||
keyValueCommitting: KeyValueCommitting,
|
val keyValueCommitting = new KeyValueCommitting(
|
||||||
ledgerDataExporter: LedgerDataExporter,
|
engine,
|
||||||
)(implicit materializer: Materializer): ValidateAndCommit = {
|
metrics,
|
||||||
val now = () => timeProvider.getCurrentTime
|
inStaticTimeMode = needStaticTimeModeFor(timeProvider),
|
||||||
val committer = new PreExecutingValidatingCommitter[
|
)
|
||||||
Option[DamlStateValue],
|
new Committer(
|
||||||
RawPreExecutingCommitStrategy.ReadSet,
|
|
||||||
RawKeyValuePairsWithLogEntry,
|
|
||||||
](
|
|
||||||
transformStateReader = transformStateReader(keySerializationStrategy, stateValueCache),
|
transformStateReader = transformStateReader(keySerializationStrategy, stateValueCache),
|
||||||
validator = new PreExecutingSubmissionValidator(
|
validator = new PreExecutingSubmissionValidator(
|
||||||
keyValueCommitting,
|
keyValueCommitting,
|
||||||
@ -183,24 +119,6 @@ object InMemoryLedgerWriter {
|
|||||||
postExecutionWriter = new RawPostExecutionWriter,
|
postExecutionWriter = new RawPostExecutionWriter,
|
||||||
ledgerDataExporter = ledgerDataExporter,
|
ledgerDataExporter = ledgerDataExporter,
|
||||||
)
|
)
|
||||||
locally {
|
|
||||||
implicit val executionContext: ExecutionContext = materializer.executionContext
|
|
||||||
|
|
||||||
def validateAndCommit(
|
|
||||||
correlationId: String,
|
|
||||||
submissionEnvelope: Raw.Value,
|
|
||||||
submittingParticipantId: ParticipantId,
|
|
||||||
) =
|
|
||||||
committer.commit(
|
|
||||||
submittingParticipantId,
|
|
||||||
correlationId,
|
|
||||||
submissionEnvelope,
|
|
||||||
now(),
|
|
||||||
new InMemoryLedgerStateAccess(state, metrics),
|
|
||||||
)
|
|
||||||
|
|
||||||
validateAndCommit
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private def transformStateReader(
|
private def transformStateReader(
|
||||||
@ -215,13 +133,6 @@ object InMemoryLedgerWriter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def createKeyValueCommitting(
|
|
||||||
metrics: Metrics,
|
|
||||||
timeProvider: TimeProvider,
|
|
||||||
engine: Engine,
|
|
||||||
): KeyValueCommitting =
|
|
||||||
new KeyValueCommitting(engine, metrics, inStaticTimeMode = needStaticTimeModeFor(timeProvider))
|
|
||||||
|
|
||||||
private def needStaticTimeModeFor(timeProvider: TimeProvider): Boolean =
|
private def needStaticTimeModeFor(timeProvider: TimeProvider): Boolean =
|
||||||
timeProvider != TimeProvider.UTC
|
timeProvider != TimeProvider.UTC
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ package object memory {
|
|||||||
|
|
||||||
private[memory] val StartIndex: Index = 0
|
private[memory] val StartIndex: Index = 0
|
||||||
|
|
||||||
private[memory] def dispatcherOwner: ResourceOwner[Dispatcher[Index]] =
|
def dispatcherOwner: ResourceOwner[Dispatcher[Index]] =
|
||||||
Dispatcher.owner(
|
Dispatcher.owner(
|
||||||
name = "in-memory-key-value-participant-state",
|
name = "in-memory-key-value-participant-state",
|
||||||
zeroIndex = StartIndex,
|
zeroIndex = StartIndex,
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
// Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package com.daml.ledger.on.memory
|
|
||||||
|
|
||||||
import com.daml.ledger.participant.state.kvutils.ParticipantStateIntegrationSpecBase
|
|
||||||
import com.daml.ledger.participant.state.kvutils.ParticipantStateIntegrationSpecBase.ParticipantState
|
|
||||||
import com.daml.ledger.participant.state.kvutils.api.{
|
|
||||||
BatchingLedgerWriterConfig,
|
|
||||||
KeyValueParticipantState,
|
|
||||||
}
|
|
||||||
import com.daml.ledger.participant.state.v1.{LedgerId, ParticipantId}
|
|
||||||
import com.daml.ledger.resources.ResourceOwner
|
|
||||||
import com.daml.lf.engine.Engine
|
|
||||||
import com.daml.logging.LoggingContext
|
|
||||||
import com.daml.metrics.Metrics
|
|
||||||
|
|
||||||
import scala.concurrent.duration.DurationInt
|
|
||||||
|
|
||||||
abstract class InMemoryLedgerReaderWriterIntegrationSpecBase(enableBatching: Boolean)
|
|
||||||
extends ParticipantStateIntegrationSpecBase(
|
|
||||||
s"In-memory ledger/participant with parallel validation ${if (enableBatching) "enabled"
|
|
||||||
else "disabled"}"
|
|
||||||
) {
|
|
||||||
|
|
||||||
private val batchingLedgerWriterConfig =
|
|
||||||
BatchingLedgerWriterConfig(
|
|
||||||
enableBatching = enableBatching,
|
|
||||||
// In case of serial validation, we need a queue length of 1000 because the
|
|
||||||
// "process many party allocations" test case will be sending in that many requests at once
|
|
||||||
// (otherwise some of those would be rejected).
|
|
||||||
// See [[ParticipantStateIntegrationSpecBase]].
|
|
||||||
maxBatchQueueSize = if (enableBatching) 100 else 1000,
|
|
||||||
maxBatchSizeBytes = 4L * 1024L * 1024L /* 4MB */,
|
|
||||||
maxBatchWaitDuration = 100.millis,
|
|
||||||
// In-memory ledger doesn't support concurrent commits.
|
|
||||||
maxBatchConcurrentCommits = 1,
|
|
||||||
)
|
|
||||||
|
|
||||||
override val isPersistent: Boolean = false
|
|
||||||
|
|
||||||
override def participantStateFactory(
|
|
||||||
ledgerId: LedgerId,
|
|
||||||
participantId: ParticipantId,
|
|
||||||
testId: String,
|
|
||||||
metrics: Metrics,
|
|
||||||
)(implicit loggingContext: LoggingContext): ResourceOwner[ParticipantState] =
|
|
||||||
new InMemoryLedgerReaderWriter.SingleParticipantBatchingOwner(
|
|
||||||
ledgerId,
|
|
||||||
batchingLedgerWriterConfig,
|
|
||||||
participantId,
|
|
||||||
metrics = metrics,
|
|
||||||
engine = Engine.DevEngine(),
|
|
||||||
).map(readerWriter => new KeyValueParticipantState(readerWriter, readerWriter, metrics))
|
|
||||||
|
|
||||||
}
|
|
@ -6,7 +6,7 @@
|
|||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<root level="TRACE">
|
<root level="DEBUG">
|
||||||
<appender-ref ref="STDOUT"/>
|
<appender-ref ref="STDOUT"/>
|
||||||
</root>
|
</root>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@ -3,5 +3,46 @@
|
|||||||
|
|
||||||
package com.daml.ledger.on.memory
|
package com.daml.ledger.on.memory
|
||||||
|
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
|
import com.daml.ledger.participant.state.kvutils.ParticipantStateIntegrationSpecBase
|
||||||
|
import com.daml.ledger.participant.state.kvutils.ParticipantStateIntegrationSpecBase.ParticipantState
|
||||||
|
import com.daml.ledger.participant.state.kvutils.api.KeyValueParticipantState
|
||||||
|
import com.daml.ledger.participant.state.v1.{LedgerId, ParticipantId}
|
||||||
|
import com.daml.ledger.resources.ResourceOwner
|
||||||
|
import com.daml.ledger.validator.StateKeySerializationStrategy
|
||||||
|
import com.daml.lf.engine.Engine
|
||||||
|
import com.daml.logging.LoggingContext
|
||||||
|
import com.daml.metrics.Metrics
|
||||||
|
|
||||||
|
import scala.concurrent.ExecutionContext
|
||||||
|
|
||||||
class InMemoryLedgerReaderWriterIntegrationSpec
|
class InMemoryLedgerReaderWriterIntegrationSpec
|
||||||
extends InMemoryLedgerReaderWriterIntegrationSpecBase(enableBatching = true)
|
extends ParticipantStateIntegrationSpecBase(s"In-memory ledger/participant") {
|
||||||
|
|
||||||
|
override val isPersistent: Boolean = false
|
||||||
|
|
||||||
|
override def participantStateFactory(
|
||||||
|
ledgerId: LedgerId,
|
||||||
|
participantId: ParticipantId,
|
||||||
|
testId: String,
|
||||||
|
metrics: Metrics,
|
||||||
|
)(implicit loggingContext: LoggingContext): ResourceOwner[ParticipantState] =
|
||||||
|
for {
|
||||||
|
dispatcher <- dispatcherOwner
|
||||||
|
committerExecutionContext <- ResourceOwner
|
||||||
|
.forExecutorService(() => Executors.newCachedThreadPool())
|
||||||
|
.map(ExecutionContext.fromExecutorService)
|
||||||
|
readerWriter <- new InMemoryLedgerReaderWriter.Owner(
|
||||||
|
ledgerId = ledgerId,
|
||||||
|
participantId = participantId,
|
||||||
|
keySerializationStrategy = StateKeySerializationStrategy.createDefault(),
|
||||||
|
metrics = metrics,
|
||||||
|
dispatcher = dispatcher,
|
||||||
|
state = InMemoryState.empty,
|
||||||
|
engine = Engine.DevEngine(),
|
||||||
|
committerExecutionContext = committerExecutionContext,
|
||||||
|
)
|
||||||
|
} yield new KeyValueParticipantState(readerWriter, readerWriter, metrics)
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -3,19 +3,23 @@
|
|||||||
|
|
||||||
package com.daml.ledger.on.memory
|
package com.daml.ledger.on.memory
|
||||||
|
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
import com.codahale.metrics.MetricRegistry
|
||||||
import com.daml.ledger.api.testing.utils.AkkaBeforeAndAfterAll
|
import com.daml.ledger.api.testing.utils.AkkaBeforeAndAfterAll
|
||||||
import com.daml.ledger.participant.state.kvutils.Raw
|
import com.daml.ledger.participant.state.kvutils.Raw
|
||||||
import com.daml.ledger.participant.state.kvutils.api.CommitMetadata
|
import com.daml.ledger.participant.state.kvutils.api.CommitMetadata
|
||||||
import com.daml.ledger.participant.state.v1.{ParticipantId, SubmissionResult}
|
import com.daml.ledger.participant.state.v1.{ParticipantId, SubmissionResult}
|
||||||
import com.daml.ledger.validator.ValidateAndCommit
|
import com.daml.ledger.validator.LedgerStateAccess
|
||||||
import com.daml.lf.data.Ref
|
import com.daml.lf.data.Ref
|
||||||
|
import com.daml.metrics.Metrics
|
||||||
import com.daml.platform.akkastreams.dispatcher.Dispatcher
|
import com.daml.platform.akkastreams.dispatcher.Dispatcher
|
||||||
import com.google.protobuf.ByteString
|
import com.google.protobuf.ByteString
|
||||||
import org.mockito.{ArgumentMatchersSugar, MockitoSugar}
|
import org.mockito.{ArgumentMatchersSugar, MockitoSugar}
|
||||||
import org.scalatest.matchers.should.Matchers
|
import org.scalatest.matchers.should.Matchers
|
||||||
import org.scalatest.wordspec.AsyncWordSpec
|
import org.scalatest.wordspec.AsyncWordSpec
|
||||||
|
|
||||||
import scala.concurrent.Future
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
|
|
||||||
class InMemoryLedgerWriterSpec
|
class InMemoryLedgerWriterSpec
|
||||||
extends AsyncWordSpec
|
extends AsyncWordSpec
|
||||||
@ -26,16 +30,27 @@ class InMemoryLedgerWriterSpec
|
|||||||
"commit" should {
|
"commit" should {
|
||||||
"not signal new head in case of failure" in {
|
"not signal new head in case of failure" in {
|
||||||
val mockDispatcher = mock[Dispatcher[Index]]
|
val mockDispatcher = mock[Dispatcher[Index]]
|
||||||
val mockCommitter = mock[ValidateAndCommit]
|
val mockCommitter = mock[InMemoryLedgerWriter.Committer]
|
||||||
when(mockCommitter(any[String], any[Raw.Value], any[ParticipantId]))
|
when(
|
||||||
|
mockCommitter.commit(
|
||||||
|
any[ParticipantId],
|
||||||
|
any[String],
|
||||||
|
any[Raw.Value],
|
||||||
|
any[Instant],
|
||||||
|
any[LedgerStateAccess[Any]],
|
||||||
|
)(any[ExecutionContext])
|
||||||
|
)
|
||||||
.thenReturn(
|
.thenReturn(
|
||||||
Future.successful(SubmissionResult.InternalError("Validation failed with an exception"))
|
Future.successful(SubmissionResult.InternalError("Validation failed with an exception"))
|
||||||
)
|
)
|
||||||
val instance = new InMemoryLedgerWriter(
|
val instance = new InMemoryLedgerWriter(
|
||||||
Ref.ParticipantId.assertFromString("participant ID"),
|
participantId = Ref.ParticipantId.assertFromString("participant ID"),
|
||||||
mockDispatcher,
|
dispatcher = mockDispatcher,
|
||||||
InMemoryState.empty,
|
now = () => Instant.EPOCH,
|
||||||
mockCommitter,
|
state = InMemoryState.empty,
|
||||||
|
committer = mockCommitter,
|
||||||
|
committerExecutionContext = executionContext,
|
||||||
|
metrics = new Metrics(new MetricRegistry),
|
||||||
)
|
)
|
||||||
|
|
||||||
instance
|
instance
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
// Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package com.daml.ledger.on.memory
|
|
||||||
|
|
||||||
class NonBatchedInMemoryLedgerReaderWriterIntegrationSpec
|
|
||||||
extends InMemoryLedgerReaderWriterIntegrationSpecBase(enableBatching = false) {}
|
|
@ -226,7 +226,6 @@ client_server_build(
|
|||||||
server_args = [
|
server_args = [
|
||||||
"--contract-id-seeding=testing-weak",
|
"--contract-id-seeding=testing-weak",
|
||||||
"--participant=participant-id=%s,port=%d" % (REFERENCE_LEDGER_EXPORT_NAME, REFERENCE_LEDGER_EXPORT_PORT),
|
"--participant=participant-id=%s,port=%d" % (REFERENCE_LEDGER_EXPORT_NAME, REFERENCE_LEDGER_EXPORT_PORT),
|
||||||
"--force-pre-execution=true",
|
|
||||||
],
|
],
|
||||||
visibility = [":__subpackages__"],
|
visibility = [":__subpackages__"],
|
||||||
) if not is_windows and scala_major_version == "2.12" else None
|
) if not is_windows and scala_major_version == "2.12" else None
|
||||||
|
@ -71,6 +71,9 @@ object Config {
|
|||||||
extra = extra,
|
extra = extra,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def ownerWithoutExtras(name: String, args: collection.Seq[String]): ResourceOwner[Config[Unit]] =
|
||||||
|
owner(name, _ => (), (), args)
|
||||||
|
|
||||||
def owner[Extra](
|
def owner[Extra](
|
||||||
name: String,
|
name: String,
|
||||||
extraOptions: OptionParser[Config[Extra]] => Unit,
|
extraOptions: OptionParser[Config[Extra]] => Unit,
|
||||||
|
@ -5,22 +5,14 @@ package com.daml.ledger
|
|||||||
|
|
||||||
import com.daml.caching.ConcurrentCache
|
import com.daml.caching.ConcurrentCache
|
||||||
import com.daml.ledger.participant.state.kvutils.DamlKvutils.DamlStateValue
|
import com.daml.ledger.participant.state.kvutils.DamlKvutils.DamlStateValue
|
||||||
import com.daml.ledger.participant.state.kvutils.{CorrelationId, Raw}
|
import com.daml.ledger.participant.state.kvutils.Raw
|
||||||
import com.daml.ledger.participant.state.v1.{ParticipantId, SubmissionResult}
|
import com.daml.ledger.participant.state.v1.ParticipantId
|
||||||
|
|
||||||
import scala.concurrent.{ExecutionContext, Future}
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
|
|
||||||
package object validator {
|
package object validator {
|
||||||
type SubmittingParticipantId = ParticipantId
|
type SubmittingParticipantId = ParticipantId
|
||||||
|
|
||||||
/** Orchestrates committing to a ledger after validating submissions.
|
|
||||||
*/
|
|
||||||
type ValidateAndCommit = (
|
|
||||||
CorrelationId,
|
|
||||||
Raw.Value,
|
|
||||||
SubmittingParticipantId,
|
|
||||||
) => Future[SubmissionResult]
|
|
||||||
|
|
||||||
type StateValueCache = ConcurrentCache[Raw.Value, DamlStateValue]
|
type StateValueCache = ConcurrentCache[Raw.Value, DamlStateValue]
|
||||||
|
|
||||||
// At some point, someone much smarter than the author of this code will reimplement the usages of
|
// At some point, someone much smarter than the author of this code will reimplement the usages of
|
||||||
|
@ -14,12 +14,10 @@ import akka.stream.scaladsl.Source
|
|||||||
import ch.qos.logback.classic.Level
|
import ch.qos.logback.classic.Level
|
||||||
import com.codahale.metrics.MetricRegistry
|
import com.codahale.metrics.MetricRegistry
|
||||||
import com.daml.ledger.on.memory
|
import com.daml.ledger.on.memory
|
||||||
import com.daml.ledger.participant.state.kvutils.api.{
|
import com.daml.ledger.participant.state.kvutils.api.KeyValueParticipantState
|
||||||
BatchingLedgerWriterConfig,
|
|
||||||
KeyValueParticipantState,
|
|
||||||
}
|
|
||||||
import com.daml.ledger.participant.state.v1._
|
import com.daml.ledger.participant.state.v1._
|
||||||
import com.daml.ledger.resources.{ResourceOwner, TestResourceContext}
|
import com.daml.ledger.resources.{ResourceOwner, TestResourceContext}
|
||||||
|
import com.daml.ledger.validator.StateKeySerializationStrategy
|
||||||
import com.daml.lf.data.Ref
|
import com.daml.lf.data.Ref
|
||||||
import com.daml.lf.data.Ref.LedgerString
|
import com.daml.lf.data.Ref.LedgerString
|
||||||
import com.daml.lf.engine.Engine
|
import com.daml.lf.engine.Engine
|
||||||
@ -256,13 +254,22 @@ object RecoveringIndexerIntegrationSpec {
|
|||||||
loggingContext: LoggingContext,
|
loggingContext: LoggingContext,
|
||||||
): ResourceOwner[ParticipantState] = {
|
): ResourceOwner[ParticipantState] = {
|
||||||
val metrics = new Metrics(new MetricRegistry)
|
val metrics = new Metrics(new MetricRegistry)
|
||||||
new memory.InMemoryLedgerReaderWriter.SingleParticipantBatchingOwner(
|
for {
|
||||||
ledgerId,
|
dispatcher <- memory.dispatcherOwner
|
||||||
BatchingLedgerWriterConfig.reasonableDefault,
|
committerExecutionContext <- ResourceOwner
|
||||||
participantId,
|
.forExecutorService(() => Executors.newCachedThreadPool())
|
||||||
metrics = metrics,
|
.map(ExecutionContext.fromExecutorService)
|
||||||
engine = Engine.DevEngine(),
|
readerWriter <- new memory.InMemoryLedgerReaderWriter.Owner(
|
||||||
).map(readerWriter => new KeyValueParticipantState(readerWriter, readerWriter, metrics))
|
ledgerId = ledgerId,
|
||||||
|
participantId = participantId,
|
||||||
|
keySerializationStrategy = StateKeySerializationStrategy.createDefault(),
|
||||||
|
metrics = metrics,
|
||||||
|
dispatcher = dispatcher,
|
||||||
|
state = memory.InMemoryState.empty,
|
||||||
|
engine = Engine.DevEngine(),
|
||||||
|
committerExecutionContext = committerExecutionContext,
|
||||||
|
)
|
||||||
|
} yield new KeyValueParticipantState(readerWriter, readerWriter, metrics)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user