mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Cleaned up TimeWindow and added a bit more docs.
This commit is contained in:
parent
bf98f64269
commit
e702025f62
2
.gitignore
vendored
2
.gitignore
vendored
@ -67,7 +67,7 @@ lib/dokka.jar
|
||||
## Plugin-specific files:
|
||||
|
||||
# IntelliJ
|
||||
/out/
|
||||
**/out/
|
||||
/classes/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
|
@ -21,7 +21,6 @@ import java.math.BigDecimal
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.time.Duration
|
||||
import java.time.temporal.Temporal
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.ExecutionException
|
||||
import java.util.concurrent.Future
|
||||
@ -95,9 +94,6 @@ fun <A> ListenableFuture<out A>.toObservable(): Observable<A> {
|
||||
}
|
||||
}
|
||||
|
||||
// Simple infix function to add back null safety that the JDK lacks: timeA until timeB
|
||||
infix fun Temporal.until(endExclusive: Temporal): Duration = Duration.between(this, endExclusive)
|
||||
|
||||
/** Returns the index of the given item or throws [IllegalArgumentException] if not found. */
|
||||
fun <T> List<T>.indexOfOrThrow(item: T): Int {
|
||||
val i = indexOf(item)
|
||||
|
@ -17,7 +17,6 @@ import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.security.PublicKey
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
import java.util.jar.JarInputStream
|
||||
|
||||
@ -328,63 +327,6 @@ data class AuthenticatedObject<out T : Any>(
|
||||
)
|
||||
// DOCEND 6
|
||||
|
||||
/**
|
||||
* A time-window is required for validation/notarization purposes.
|
||||
* If present in a transaction, contains a time that was verified by the uniqueness service. The true time must be
|
||||
* between (fromTime, untilTime).
|
||||
* Usually, a time-window is required to have both sides set (fromTime, untilTime).
|
||||
* However, some apps may require that a time-window has a start [Instant] (fromTime), but no end [Instant] (untilTime) and vice versa.
|
||||
* TODO: Consider refactoring using TimeWindow abstraction like TimeWindow.From, TimeWindow.Until, TimeWindow.Between.
|
||||
*/
|
||||
@CordaSerializable
|
||||
class TimeWindow private constructor(
|
||||
/** The time at which this transaction is said to have occurred is after this moment. */
|
||||
val fromTime: Instant?,
|
||||
/** The time at which this transaction is said to have occurred is before this moment. */
|
||||
val untilTime: Instant?
|
||||
) {
|
||||
companion object {
|
||||
/** Use when the left-side [fromTime] of a [TimeWindow] is only required and we don't need an end instant (untilTime). */
|
||||
@JvmStatic
|
||||
fun fromOnly(fromTime: Instant) = TimeWindow(fromTime, null)
|
||||
|
||||
/** Use when the right-side [untilTime] of a [TimeWindow] is only required and we don't need a start instant (fromTime). */
|
||||
@JvmStatic
|
||||
fun untilOnly(untilTime: Instant) = TimeWindow(null, untilTime)
|
||||
|
||||
/** Use when both sides of a [TimeWindow] must be set ([fromTime], [untilTime]). */
|
||||
@JvmStatic
|
||||
fun between(fromTime: Instant, untilTime: Instant): TimeWindow {
|
||||
require(fromTime < untilTime) { "fromTime should be earlier than untilTime" }
|
||||
return TimeWindow(fromTime, untilTime)
|
||||
}
|
||||
|
||||
/** Use when we have a start time and a period of validity. */
|
||||
@JvmStatic
|
||||
fun fromStartAndDuration(fromTime: Instant, duration: Duration): TimeWindow = between(fromTime, fromTime + duration)
|
||||
|
||||
/**
|
||||
* When we need to create a [TimeWindow] based on a specific time [Instant] and some tolerance in both sides of this instant.
|
||||
* The result will be the following time-window: ([time] - [tolerance], [time] + [tolerance]).
|
||||
*/
|
||||
@JvmStatic
|
||||
fun withTolerance(time: Instant, tolerance: Duration) = between(time - tolerance, time + tolerance)
|
||||
}
|
||||
|
||||
/** The midpoint is calculated as fromTime + (untilTime - fromTime)/2. Note that it can only be computed if both sides are set. */
|
||||
val midpoint: Instant get() = fromTime!! + Duration.between(fromTime, untilTime!!).dividedBy(2)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is TimeWindow) return false
|
||||
return (fromTime == other.fromTime && untilTime == other.untilTime)
|
||||
}
|
||||
|
||||
override fun hashCode() = 31 * (fromTime?.hashCode() ?: 0) + (untilTime?.hashCode() ?: 0)
|
||||
|
||||
override fun toString() = "TimeWindow(fromTime=$fromTime, untilTime=$untilTime)"
|
||||
}
|
||||
|
||||
// DOCSTART 5
|
||||
/**
|
||||
* Implemented by a program that implements business logic on the shared ledger. All participants run this code for
|
||||
|
87
core/src/main/kotlin/net/corda/core/contracts/TimeWindow.kt
Normal file
87
core/src/main/kotlin/net/corda/core/contracts/TimeWindow.kt
Normal file
@ -0,0 +1,87 @@
|
||||
package net.corda.core.contracts
|
||||
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.until
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
|
||||
/**
|
||||
* A time-window is required for validation/notarization purposes. If present in a transaction, contains a time that was
|
||||
* verified by the uniqueness service. The true time must be in the time interval `[fromTime, untilTime)`.
|
||||
*
|
||||
* Usually a time-window is required to have both sides defined. However some apps may require a time-window which is
|
||||
* open-ended on one of the two sides.
|
||||
*/
|
||||
@CordaSerializable
|
||||
abstract class TimeWindow {
|
||||
companion object {
|
||||
/** Creates a [TimeWindow] with null [untilTime], i.e. the time interval `[fromTime, ∞]`. [midpoint] will return null. */
|
||||
@JvmStatic
|
||||
fun fromOnly(fromTime: Instant): TimeWindow = From(fromTime)
|
||||
|
||||
/** Creates a [TimeWindow] with null [fromTime], i.e. the time interval `[∞, untilTime)`. [midpoint] will return null. */
|
||||
@JvmStatic
|
||||
fun untilOnly(untilTime: Instant): TimeWindow = Until(untilTime)
|
||||
|
||||
/**
|
||||
* Creates a [TimeWindow] with the time interval `[fromTime, untilTime)`. [midpoint] will return
|
||||
* `fromTime + (untilTime - fromTime) / 2`.
|
||||
* @throws IllegalArgumentException If [fromTime] ≥ [untilTime]
|
||||
*/
|
||||
@JvmStatic
|
||||
fun between(fromTime: Instant, untilTime: Instant): TimeWindow = Between(fromTime, untilTime)
|
||||
|
||||
/**
|
||||
* Creates a [TimeWindow] with the time interval `[fromTime, fromTime + duration)`. [midpoint] will return
|
||||
* `fromTime + duration / 2`
|
||||
*/
|
||||
@JvmStatic
|
||||
fun fromStartAndDuration(fromTime: Instant, duration: Duration): TimeWindow = between(fromTime, fromTime + duration)
|
||||
|
||||
/**
|
||||
* Creates a [TimeWindow] which is centered around [instant] with the given [tolerance] on both sides, i.e the
|
||||
* time interval `[instant - tolerance, instant + tolerance)`. [midpoint] will return [instant].
|
||||
*/
|
||||
@JvmStatic
|
||||
fun withTolerance(instant: Instant, tolerance: Duration) = between(instant - tolerance, instant + tolerance)
|
||||
}
|
||||
|
||||
/** Returns the inclusive lower-bound of this [TimeWindow]'s interval, with null implying infinity. */
|
||||
abstract val fromTime: Instant?
|
||||
|
||||
/** Returns the exclusive upper-bound of this [TimeWindow]'s interval, with null implying infinity. */
|
||||
abstract val untilTime: Instant?
|
||||
|
||||
/**
|
||||
* Returns the midpoint of [fromTime] and [untilTime] if both are non-null, calculated as
|
||||
* `fromTime + (untilTime - fromTime)/2`, otherwise returns null.
|
||||
*/
|
||||
abstract val midpoint: Instant?
|
||||
|
||||
/** Returns true iff the given [instant] is within the time interval of this [TimeWindow]. */
|
||||
abstract operator fun contains(instant: Instant): Boolean
|
||||
|
||||
private data class From(override val fromTime: Instant) : TimeWindow() {
|
||||
override val untilTime: Instant? get() = null
|
||||
override val midpoint: Instant? get() = null
|
||||
override fun contains(instant: Instant): Boolean = instant >= fromTime
|
||||
override fun toString(): String = "[$fromTime, ∞]"
|
||||
}
|
||||
|
||||
private data class Until(override val untilTime: Instant) : TimeWindow() {
|
||||
override val fromTime: Instant? get() = null
|
||||
override val midpoint: Instant? get() = null
|
||||
override fun contains(instant: Instant): Boolean = instant < untilTime
|
||||
override fun toString(): String = "[∞, $untilTime)"
|
||||
}
|
||||
|
||||
private data class Between(override val fromTime: Instant, override val untilTime: Instant) : TimeWindow() {
|
||||
init {
|
||||
require(fromTime < untilTime) { "fromTime must be earlier than untilTime" }
|
||||
}
|
||||
override val midpoint: Instant get() = fromTime + (fromTime until untilTime) / 2
|
||||
override fun contains(instant: Instant): Boolean = instant >= fromTime && instant < untilTime
|
||||
override fun toString(): String = "[$fromTime, $untilTime)"
|
||||
}
|
||||
}
|
@ -7,9 +7,16 @@ import java.nio.charset.Charset
|
||||
import java.nio.charset.StandardCharsets.UTF_8
|
||||
import java.nio.file.*
|
||||
import java.nio.file.attribute.FileAttribute
|
||||
import java.time.Duration
|
||||
import java.time.temporal.Temporal
|
||||
import java.util.stream.Stream
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
infix fun Temporal.until(endExclusive: Temporal): Duration = Duration.between(this, endExclusive)
|
||||
|
||||
operator fun Duration.div(divider: Long): Duration = dividedBy(divider)
|
||||
operator fun Duration.times(multiplicand: Long): Duration = multipliedBy(multiplicand)
|
||||
|
||||
/**
|
||||
* Allows you to write code like: Paths.get("someDir") / "subdir" / "filename" but using the Paths API to avoid platform
|
||||
* separator problems.
|
||||
|
@ -7,16 +7,5 @@ import java.time.Clock
|
||||
* Checks if the current instant provided by the input clock falls within the provided time-window.
|
||||
*/
|
||||
class TimeWindowChecker(val clock: Clock = Clock.systemUTC()) {
|
||||
fun isValid(timeWindow: TimeWindow): Boolean {
|
||||
val fromTime = timeWindow.fromTime
|
||||
val untilTime = timeWindow.untilTime
|
||||
|
||||
val now = clock.instant()
|
||||
|
||||
// We don't need to test for (fromTime == null && untilTime == null) or backwards bounds because the TimeWindow
|
||||
// constructor already checks that.
|
||||
if (fromTime != null && now < fromTime) return false
|
||||
if (untilTime != null && now > untilTime) return false
|
||||
return true
|
||||
}
|
||||
fun isValid(timeWindow: TimeWindow): Boolean = clock.instant() in timeWindow
|
||||
}
|
||||
|
@ -0,0 +1,67 @@
|
||||
package net.corda.core.contracts
|
||||
|
||||
import net.corda.core.utilities.millis
|
||||
import net.corda.core.utilities.minutes
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.ZoneOffset.UTC
|
||||
|
||||
class TimeWindowTest {
|
||||
private val now = Instant.now()
|
||||
|
||||
@Test
|
||||
fun fromOnly() {
|
||||
val timeWindow = TimeWindow.fromOnly(now)
|
||||
assertThat(timeWindow.fromTime).isEqualTo(now)
|
||||
assertThat(timeWindow.untilTime).isNull()
|
||||
assertThat(timeWindow.midpoint).isNull()
|
||||
assertThat(timeWindow.contains(now - 1.millis)).isFalse()
|
||||
assertThat(timeWindow.contains(now)).isTrue()
|
||||
assertThat(timeWindow.contains(now + 1.millis)).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun untilOnly() {
|
||||
val timeWindow = TimeWindow.untilOnly(now)
|
||||
assertThat(timeWindow.fromTime).isNull()
|
||||
assertThat(timeWindow.untilTime).isEqualTo(now)
|
||||
assertThat(timeWindow.midpoint).isNull()
|
||||
assertThat(timeWindow.contains(now - 1.millis)).isTrue()
|
||||
assertThat(timeWindow.contains(now)).isFalse()
|
||||
assertThat(timeWindow.contains(now + 1.millis)).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun between() {
|
||||
val today = LocalDate.now()
|
||||
val fromTime = today.atTime(12, 0).toInstant(UTC)
|
||||
val untilTime = today.atTime(12, 30).toInstant(UTC)
|
||||
val timeWindow = TimeWindow.between(fromTime, untilTime)
|
||||
assertThat(timeWindow.fromTime).isEqualTo(fromTime)
|
||||
assertThat(timeWindow.untilTime).isEqualTo(untilTime)
|
||||
assertThat(timeWindow.midpoint).isEqualTo(today.atTime(12, 15).toInstant(UTC))
|
||||
assertThat(timeWindow.contains(fromTime - 1.millis)).isFalse()
|
||||
assertThat(timeWindow.contains(fromTime)).isTrue()
|
||||
assertThat(timeWindow.contains(fromTime + 1.millis)).isTrue()
|
||||
assertThat(timeWindow.contains(untilTime)).isFalse()
|
||||
assertThat(timeWindow.contains(untilTime + 1.millis)).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fromStartAndDuration() {
|
||||
val timeWindow = TimeWindow.fromStartAndDuration(now, 10.minutes)
|
||||
assertThat(timeWindow.fromTime).isEqualTo(now)
|
||||
assertThat(timeWindow.untilTime).isEqualTo(now + 10.minutes)
|
||||
assertThat(timeWindow.midpoint).isEqualTo(now + 5.minutes)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun withTolerance() {
|
||||
val timeWindow = TimeWindow.withTolerance(now, 10.minutes)
|
||||
assertThat(timeWindow.fromTime).isEqualTo(now - 10.minutes)
|
||||
assertThat(timeWindow.untilTime).isEqualTo(now + 10.minutes)
|
||||
assertThat(timeWindow.midpoint).isEqualTo(now)
|
||||
}
|
||||
}
|
@ -5,12 +5,12 @@ import net.corda.core.utilities.seconds
|
||||
import org.junit.Test
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
import java.time.ZoneOffset
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class TimeWindowCheckerTests {
|
||||
val clock = Clock.fixed(Instant.now(), ZoneId.systemDefault())
|
||||
val clock: Clock = Clock.fixed(Instant.now(), ZoneOffset.UTC)
|
||||
val timeWindowChecker = TimeWindowChecker(clock)
|
||||
|
||||
@Test
|
||||
|
@ -72,7 +72,7 @@ data class TradeApprovalContract(override val legalContractReference: SecureHash
|
||||
*/
|
||||
override fun verify(tx: LedgerTransaction) {
|
||||
val command = tx.commands.requireSingleCommand<TradeApprovalContract.Commands>()
|
||||
require(tx.timeWindow?.midpoint != null) { "must have a time-window" }
|
||||
requireNotNull(tx.timeWindow) { "must have a time-window" }
|
||||
when (command.value) {
|
||||
is Commands.Issue -> {
|
||||
requireThat {
|
||||
|
@ -2,8 +2,10 @@ package net.corda.services.messaging
|
||||
|
||||
import com.google.common.util.concurrent.Futures
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import net.corda.core.*
|
||||
import net.corda.core.crypto.random63BitValue
|
||||
import net.corda.core.elapsedTime
|
||||
import net.corda.core.getOrThrow
|
||||
import net.corda.core.internal.times
|
||||
import net.corda.core.messaging.MessageRecipients
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
@ -43,7 +45,7 @@ class P2PMessagingTest : NodeBasedTest() {
|
||||
// Start the network map a second time - this will restore message queues from the journal.
|
||||
// This will hang and fail prior the fix. https://github.com/corda/corda/issues/37
|
||||
stopAllNodes()
|
||||
startNodes().getOrThrow(timeout = startUpDuration.multipliedBy(3))
|
||||
startNodes().getOrThrow(timeout = startUpDuration * 3)
|
||||
}
|
||||
|
||||
// https://github.com/corda/corda/issues/71
|
||||
|
@ -3,12 +3,12 @@ package net.corda.node.utilities
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import co.paralleluniverse.strands.SettableFuture
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import net.corda.core.internal.until
|
||||
import net.corda.core.then
|
||||
import rx.Observable
|
||||
import rx.Subscriber
|
||||
import rx.subscriptions.Subscriptions
|
||||
import java.time.Clock
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
import java.util.concurrent.*
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
@ -80,7 +80,7 @@ fun Clock.awaitWithDeadline(deadline: Instant, future: Future<*> = GuavaSettable
|
||||
} else {
|
||||
null
|
||||
}
|
||||
nanos = Duration.between(this.instant(), deadline).toNanos()
|
||||
nanos = (instant() until deadline).toNanos()
|
||||
if (nanos > 0) {
|
||||
try {
|
||||
// This will return when it times out, or when the clock mutates or when when the original future completes.
|
||||
|
@ -1,10 +1,13 @@
|
||||
package net.corda.node.utilities
|
||||
|
||||
import net.corda.core.internal.until
|
||||
import net.corda.core.serialization.SerializeAsToken
|
||||
import net.corda.core.serialization.SerializeAsTokenContext
|
||||
import net.corda.core.serialization.SingletonSerializationToken
|
||||
import net.corda.core.serialization.SingletonSerializationToken.Companion.singletonSerializationToken
|
||||
import java.time.*
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.ZoneId
|
||||
import javax.annotation.concurrent.ThreadSafe
|
||||
|
||||
/**
|
||||
@ -21,7 +24,7 @@ class TestClock(private var delegateClock: Clock = Clock.systemUTC()) : MutableC
|
||||
val currentDate = LocalDate.now(this)
|
||||
if (currentDate.isBefore(date)) {
|
||||
// It's ok to increment
|
||||
delegateClock = Clock.offset(delegateClock, Duration.between(currentDate.atStartOfDay(), date.atStartOfDay()))
|
||||
delegateClock = Clock.offset(delegateClock, currentDate.atStartOfDay() until date.atStartOfDay())
|
||||
notifyMutationObservers()
|
||||
return true
|
||||
}
|
||||
|
@ -522,7 +522,7 @@ class InterestRateSwap : Contract {
|
||||
outputs: List<ContractState>,
|
||||
commands: List<AuthenticatedObject<Commands>>,
|
||||
groupingKey: Unit?): Set<Commands> {
|
||||
require(tx.timeWindow?.midpoint != null) { "must be have a time-window)" }
|
||||
requireNotNull(tx.timeWindow) { "must be have a time-window)" }
|
||||
// We return an empty set because we don't process any commands
|
||||
return emptySet()
|
||||
}
|
||||
@ -584,8 +584,7 @@ class InterestRateSwap : Contract {
|
||||
"There is only one change in the IRS floating leg payment schedule" using (paymentDifferences.size == 1)
|
||||
}
|
||||
|
||||
val changedRates = paymentDifferences.single().second // Ignore the date of the changed rate (we checked that earlier).
|
||||
val (oldFloatingRatePaymentEvent, newFixedRatePaymentEvent) = changedRates
|
||||
val (oldFloatingRatePaymentEvent, newFixedRatePaymentEvent) = paymentDifferences.single().second // Ignore the date of the changed rate (we checked that earlier).
|
||||
val fixValue = command.value.fix
|
||||
// Need to check that everything is the same apart from the new fixed rate entry.
|
||||
requireThat {
|
||||
|
@ -23,7 +23,7 @@ data class OGTrade(override val legalContractReference: SecureHash = SecureHash.
|
||||
outputs: List<ContractState>,
|
||||
commands: List<AuthenticatedObject<Commands>>,
|
||||
groupingKey: Unit?): Set<Commands> {
|
||||
require(tx.timeWindow?.midpoint != null) { "must have a time-window" }
|
||||
requireNotNull(tx.timeWindow) { "must have a time-window" }
|
||||
// We return an empty set because we don't process any commands
|
||||
return emptySet()
|
||||
}
|
||||
@ -43,7 +43,7 @@ data class OGTrade(override val legalContractReference: SecureHash = SecureHash.
|
||||
groupingKey: UniqueIdentifier?): Set<Commands> {
|
||||
val command = tx.commands.requireSingleCommand<Commands.Agree>()
|
||||
|
||||
require(inputs.size == 0) { "Inputs must be empty" }
|
||||
require(inputs.isEmpty()) { "Inputs must be empty" }
|
||||
require(outputs.size == 1) { "" }
|
||||
require(outputs[0].buyer != outputs[0].seller)
|
||||
require(outputs[0].participants.containsAll(outputs[0].participants))
|
||||
|
@ -25,7 +25,7 @@ data class PortfolioSwap(override val legalContractReference: SecureHash = Secur
|
||||
outputs: List<ContractState>,
|
||||
commands: List<AuthenticatedObject<Commands>>,
|
||||
groupingKey: Unit?): Set<Commands> {
|
||||
require(tx.timeWindow?.midpoint != null) { "must have a time-window)" }
|
||||
requireNotNull(tx.timeWindow) { "must have a time-window)" }
|
||||
// We return an empty set because we don't process any commands
|
||||
return emptySet()
|
||||
}
|
||||
@ -69,7 +69,7 @@ data class PortfolioSwap(override val legalContractReference: SecureHash = Secur
|
||||
val command = tx.commands.requireSingleCommand<Commands.Agree>()
|
||||
|
||||
requireThat {
|
||||
"there are no inputs" using (inputs.size == 0)
|
||||
"there are no inputs" using (inputs.isEmpty())
|
||||
"there is one output" using (outputs.size == 1)
|
||||
"valuer must be a party" using (outputs[0].participants.contains(outputs[0].valuer))
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import net.corda.core.crypto.appendToCommonName
|
||||
import net.corda.core.crypto.commonName
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.times
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
@ -348,7 +349,7 @@ fun <A> poll(
|
||||
override fun run() {
|
||||
if (resultFuture.isCancelled) return // Give up, caller can no longer get the result.
|
||||
if (++counter == warnCount) {
|
||||
log.warn("Been polling $pollName for ${pollInterval.multipliedBy(warnCount.toLong()).seconds} seconds...")
|
||||
log.warn("Been polling $pollName for ${(pollInterval * warnCount.toLong()).seconds} seconds...")
|
||||
}
|
||||
try {
|
||||
val checkResult = check()
|
||||
|
@ -1,8 +1,8 @@
|
||||
package net.corda.testing.node
|
||||
|
||||
import net.corda.core.internal.until
|
||||
import net.corda.core.serialization.SerializeAsToken
|
||||
import net.corda.core.serialization.SerializeAsTokenContext
|
||||
import net.corda.core.serialization.SingletonSerializationToken
|
||||
import net.corda.core.serialization.SingletonSerializationToken.Companion.singletonSerializationToken
|
||||
import net.corda.node.utilities.MutableClock
|
||||
import java.time.Clock
|
||||
@ -35,7 +35,7 @@ class TestClock(private var delegateClock: Clock = Clock.systemUTC()) : MutableC
|
||||
*
|
||||
* This will only be approximate due to the time ticking away, but will be some time shortly after the requested [Instant].
|
||||
*/
|
||||
@Synchronized fun setTo(newInstant: Instant) = advanceBy(Duration.between(instant(), newInstant))
|
||||
@Synchronized fun setTo(newInstant: Instant) = advanceBy(instant() until newInstant)
|
||||
|
||||
@Synchronized override fun instant(): Instant {
|
||||
return delegateClock.instant()
|
||||
|
@ -5,7 +5,7 @@ import com.google.common.util.concurrent.RateLimiter
|
||||
import com.google.common.util.concurrent.SettableFuture
|
||||
import net.corda.core.catch
|
||||
import net.corda.core.utilities.minutes
|
||||
import net.corda.core.until
|
||||
import net.corda.core.internal.until
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.demobench.model.NodeConfig
|
||||
import net.corda.demobench.readErrorLines
|
||||
|
Loading…
Reference in New Issue
Block a user