Frequently Asked Questions¶
This section covers other questions that frequently arise when using Canton. If your question is not answered here, consider searching the Daml forum and creating a post if you can’t find the answer.
Log Messages¶
Database task queue full¶
If you see the log message:
java.util.concurrent.RejectedExecutionException:
Task slick.basic.BasicBackend$DaatabaseDef$@... rejected from slick.util.AsyncExecutorWithMetrics$$...
[Running, pool size = 25, active threads = 25, queued tasks = 1000, completed tasks = 181375]
It is likely that the database task queue is full. You can check this by inspecting the log message: if the logged
queued tasks
is equal to the limit for the database task queue, then the task queue is full. This error message does
not indicate that anything is broken, and the task will be retried after a delay. If the error occurs frequently,
consider increasing the number of parallel database connections.
Console Commands¶
I received an error saying that the DomainAlias I used was too long. Where I can see the limits of String types in Canton?¶
- Generally speaking, you don’t need to worry about too-long Strings as Canton will exit in a safe manner, and return an error message specifying the String you gave, its length and the maximum length allowed in the context the error occurred. Nonetheless, the known subclasses of LengthLimitedStringWrapper and the type aliases defined in the companion object of LengthLimitedString list the limits of String types in Canton.
Bootstrap Scripts¶
Why do you have an additional new line between each line in your example scripts?¶
- When we write
participant1 start
the scala compiler translates this intoparticipant1.start()
. This works great in the console when each line is parsed independently. However with a script all of it’s content is parsed at once, and in which case if there is anything on the line followingparticipant1 start
it will assume it is an argument forstart
and fail. An additional newline prevents this. Adding parenthesis would also work.
How can I use nested import statements to split my script into multiple files?¶
- Ammonite supports splitting scripts into several files using two mechanisms. The old one is
interp.load.module(..)
. The new one isimport $file.<fname>
. The former will compile the module as a whole, which means that variables defined in one module can not be used in another one as they are not available during compilation. Theimport $file.
syntax however will make all variables accessible in the importing script. However, it only works with relative paths as e.g.../path/to/foo/bar.sc
needs to be converted intoimport $file.^.path.to.foo.bar
and it only works if the script file is named with suffix.sc
.
How do I write data to a file and how do I read it back?¶
- Canton uses Protobuf for serialization and as a result, you can leverage Protobuf to write objects to a file. Here is a basic example:
// Obtain the last event.
val lastEvent: PossiblyIgnoredProtocolEvent =
participant1.testing.state_inspection
.findMessage(da.name, LatestUpto(CantonTimestamp.MaxValue))
.getOrElse(throw new NoSuchElementException("Unable to find last event."))
// Dump the last event to a file.
utils.write_to_file(lastEvent.toProtoV0, dumpFilePath)
// Read the last event back from the file.
val dumpedLastEventP: v0.PossiblyIgnoredSequencedEvent =
utils.read_first_message_from_file[v0.PossiblyIgnoredSequencedEvent](
dumpFilePath
)
val dumpedLastEventOrErr: Either[
ProtoDeserializationError,
PossiblyIgnoredProtocolEvent,
] =
PossiblyIgnoredSequencedEvent
.fromProtoV0(cryptoPureApi(participant1.config))(dumpedLastEventP)
- You can also dump several objects to the same file:
// Obtain all events.
val allEvents: Seq[PossiblyIgnoredProtocolEvent] =
participant1.testing.state_inspection.findMessages(da.name, None, None, None)
// Dump all events to a file.
utils.write_to_file(allEvents.map(_.toProtoV0), dumpFilePath)
// Read the dumped events back from the file.
val dumpedEventsP: Seq[v0.PossiblyIgnoredSequencedEvent] =
utils.read_all_messages_from_file[v0.PossiblyIgnoredSequencedEvent](
dumpFilePath
)
val dumpedEventsOrErr: Seq[Either[
ProtoDeserializationError,
PossiblyIgnoredProtocolEvent,
]] =
dumpedEventsP.map {
PossiblyIgnoredSequencedEvent.fromProtoV0(cryptoPureApi(participant1.config))(_)
}
- Some classes do not have a (public) ``toProto*`` method, but they can be serialized to a
`ByteString <https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/ByteString>`__
instead. You can dump the corresponding instances as follows:
// Obtain the last acs commitment.
val lastCommitment: AcsCommitment = participant1.commitments
.received(
da.name,
CantonTimestamp.MinValue.toInstant,
CantonTimestamp.MaxValue.toInstant,
)
.lastOption
.getOrElse(
throw new NoSuchElementException("Unable to find an acs commitment.")
)
.message
// Dump the commitment to a file.
utils.write_to_file(
lastCommitment.toByteString(ProtocolVersion.default),
dumpFilePath,
)
// Read the dumped commitment back from the file.
val dumpedLastCommitmentBytes: ByteString =
utils.read_byte_string_from_file(dumpFilePath)
val dumpedLastCommitmentOrErr: Either[
ProtoDeserializationError,
AcsCommitment,
] =
AcsCommitment.fromByteString(dumpedLastCommitmentBytes)
Why is Canton complaining about my database version?¶
Postgres¶
Canton is tested with Postgres 11, so this is the recommended version. Canton is also likely to work with higher versions, but will WARN when a higher version is encountered. By default, Canton will not start when the Postgres version is below 11.
Oracle¶
Canton Enterprise additionally supports using Oracle for storage. Only Oracle 19 has been tested, so by default Canton will not start if the Oracle version is not 19.
Note that Canton’s version checks use the v$$version
table so, for the version check to succeed,
this table must exist and the database user must have SELECT
privileges on the table.
Using non-standard database versions¶
Canton’s database version checks can be disabled with the following config option:
canton.parameters.non-standard-config = "yes"
Note that this will disable all “standard config” checks, not just those for the database.