mirror of
https://github.com/corda/corda.git
synced 2025-01-18 10:46:38 +00:00
CORDA-1007 - Tweak the way invocation context is integrated to reduce the pain for devs using the old API (#2447) (#2524)
Minor tweaks to the invocation context code. 1) Un-deprecate FlowInitiator, move the deprecation to the field. This eliminates large numbers of warnings and means developers are warned only once in the place where they obtain one. 2) Add documentation for StateMachineInfo and create a type alias to give it a better name in an ABI compatible way. 3) Improve markup on InvocationContext 4) Rename field from just "context" to "invocationContext" (Context is vague)
This commit is contained in:
parent
7d6f15b7ba
commit
f0e52e1eed
@ -90,21 +90,21 @@ public static final class net.corda.core.context.Actor$Companion extends java.la
|
||||
public String toString()
|
||||
##
|
||||
@net.corda.core.serialization.CordaSerializable public final class net.corda.core.context.InvocationContext extends java.lang.Object
|
||||
public <init>(net.corda.core.context.Origin, net.corda.core.context.Trace, net.corda.core.context.Actor, net.corda.core.context.Trace, net.corda.core.context.Actor)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.Origin component1()
|
||||
public <init>(net.corda.core.context.InvocationOrigin, net.corda.core.context.Trace, net.corda.core.context.Actor, net.corda.core.context.Trace, net.corda.core.context.Actor)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationOrigin component1()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.Trace component2()
|
||||
@org.jetbrains.annotations.Nullable public final net.corda.core.context.Actor component3()
|
||||
@org.jetbrains.annotations.Nullable public final net.corda.core.context.Trace component4()
|
||||
@org.jetbrains.annotations.Nullable public final net.corda.core.context.Actor component5()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationContext copy(net.corda.core.context.Origin, net.corda.core.context.Trace, net.corda.core.context.Actor, net.corda.core.context.Trace, net.corda.core.context.Actor)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationContext copy(net.corda.core.context.InvocationOrigin, net.corda.core.context.Trace, net.corda.core.context.Actor, net.corda.core.context.Trace, net.corda.core.context.Actor)
|
||||
public boolean equals(Object)
|
||||
@org.jetbrains.annotations.Nullable public final net.corda.core.context.Actor getActor()
|
||||
@org.jetbrains.annotations.Nullable public final net.corda.core.context.Trace getExternalTrace()
|
||||
@org.jetbrains.annotations.Nullable public final net.corda.core.context.Actor getImpersonatedActor()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.Origin getOrigin()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationOrigin getOrigin()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.Trace getTrace()
|
||||
public int hashCode()
|
||||
@kotlin.jvm.JvmStatic @org.jetbrains.annotations.NotNull public static final net.corda.core.context.InvocationContext newInstance(net.corda.core.context.Origin, net.corda.core.context.Trace, net.corda.core.context.Actor, net.corda.core.context.Trace, net.corda.core.context.Actor)
|
||||
@kotlin.jvm.JvmStatic @org.jetbrains.annotations.NotNull public static final net.corda.core.context.InvocationContext newInstance(net.corda.core.context.InvocationOrigin, net.corda.core.context.Trace, net.corda.core.context.Actor, net.corda.core.context.Trace, net.corda.core.context.Actor)
|
||||
@kotlin.jvm.JvmStatic @org.jetbrains.annotations.NotNull public static final net.corda.core.context.InvocationContext peer(net.corda.core.identity.CordaX500Name, net.corda.core.context.Trace, net.corda.core.context.Trace, net.corda.core.context.Actor)
|
||||
@org.jetbrains.annotations.NotNull public final java.security.Principal principal()
|
||||
@kotlin.jvm.JvmStatic @org.jetbrains.annotations.NotNull public static final net.corda.core.context.InvocationContext rpc(net.corda.core.context.Actor, net.corda.core.context.Trace, net.corda.core.context.Trace, net.corda.core.context.Actor)
|
||||
@ -115,49 +115,49 @@ public static final class net.corda.core.context.Actor$Companion extends java.la
|
||||
public static final net.corda.core.context.InvocationContext$Companion Companion
|
||||
##
|
||||
public static final class net.corda.core.context.InvocationContext$Companion extends java.lang.Object
|
||||
@kotlin.jvm.JvmStatic @org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationContext newInstance(net.corda.core.context.Origin, net.corda.core.context.Trace, net.corda.core.context.Actor, net.corda.core.context.Trace, net.corda.core.context.Actor)
|
||||
@kotlin.jvm.JvmStatic @org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationContext newInstance(net.corda.core.context.InvocationOrigin, net.corda.core.context.Trace, net.corda.core.context.Actor, net.corda.core.context.Trace, net.corda.core.context.Actor)
|
||||
@kotlin.jvm.JvmStatic @org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationContext peer(net.corda.core.identity.CordaX500Name, net.corda.core.context.Trace, net.corda.core.context.Trace, net.corda.core.context.Actor)
|
||||
@kotlin.jvm.JvmStatic @org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationContext rpc(net.corda.core.context.Actor, net.corda.core.context.Trace, net.corda.core.context.Trace, net.corda.core.context.Actor)
|
||||
@kotlin.jvm.JvmStatic @org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationContext scheduled(net.corda.core.contracts.ScheduledStateRef, net.corda.core.context.Trace, net.corda.core.context.Trace)
|
||||
@kotlin.jvm.JvmStatic @org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationContext service(String, net.corda.core.identity.CordaX500Name, net.corda.core.context.Trace, net.corda.core.context.Trace)
|
||||
@kotlin.jvm.JvmStatic @org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationContext shell(net.corda.core.context.Trace, net.corda.core.context.Trace)
|
||||
##
|
||||
@net.corda.core.serialization.CordaSerializable public abstract class net.corda.core.context.Origin extends java.lang.Object
|
||||
@net.corda.core.serialization.CordaSerializable public abstract class net.corda.core.context.InvocationOrigin extends java.lang.Object
|
||||
@org.jetbrains.annotations.NotNull public abstract java.security.Principal principal()
|
||||
##
|
||||
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.context.Origin$Peer extends net.corda.core.context.Origin
|
||||
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.context.InvocationOrigin$Peer extends net.corda.core.context.InvocationOrigin
|
||||
public <init>(net.corda.core.identity.CordaX500Name)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.identity.CordaX500Name component1()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.Origin$Peer copy(net.corda.core.identity.CordaX500Name)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationOrigin$Peer copy(net.corda.core.identity.CordaX500Name)
|
||||
public boolean equals(Object)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.identity.CordaX500Name getParty()
|
||||
public int hashCode()
|
||||
@org.jetbrains.annotations.NotNull public java.security.Principal principal()
|
||||
public String toString()
|
||||
##
|
||||
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.context.Origin$RPC extends net.corda.core.context.Origin
|
||||
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.context.InvocationOrigin$RPC extends net.corda.core.context.InvocationOrigin
|
||||
public <init>(net.corda.core.context.Actor)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.Origin$RPC copy(net.corda.core.context.Actor)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationOrigin$RPC copy(net.corda.core.context.Actor)
|
||||
public boolean equals(Object)
|
||||
public int hashCode()
|
||||
@org.jetbrains.annotations.NotNull public java.security.Principal principal()
|
||||
public String toString()
|
||||
##
|
||||
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.context.Origin$Scheduled extends net.corda.core.context.Origin
|
||||
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.context.InvocationOrigin$Scheduled extends net.corda.core.context.InvocationOrigin
|
||||
public <init>(net.corda.core.contracts.ScheduledStateRef)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.contracts.ScheduledStateRef component1()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.Origin$Scheduled copy(net.corda.core.contracts.ScheduledStateRef)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationOrigin$Scheduled copy(net.corda.core.contracts.ScheduledStateRef)
|
||||
public boolean equals(Object)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.contracts.ScheduledStateRef getScheduledState()
|
||||
public int hashCode()
|
||||
@org.jetbrains.annotations.NotNull public java.security.Principal principal()
|
||||
public String toString()
|
||||
##
|
||||
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.context.Origin$Service extends net.corda.core.context.Origin
|
||||
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.context.InvocationOrigin$Service extends net.corda.core.context.InvocationOrigin
|
||||
public <init>(String, net.corda.core.identity.CordaX500Name)
|
||||
@org.jetbrains.annotations.NotNull public final String component1()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.identity.CordaX500Name component2()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.Origin$Service copy(String, net.corda.core.identity.CordaX500Name)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationOrigin$Service copy(String, net.corda.core.identity.CordaX500Name)
|
||||
public boolean equals(Object)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.identity.CordaX500Name getOwningLegalIdentity()
|
||||
@org.jetbrains.annotations.NotNull public final String getServiceClassName()
|
||||
@ -165,9 +165,9 @@ public static final class net.corda.core.context.InvocationContext$Companion ext
|
||||
@org.jetbrains.annotations.NotNull public java.security.Principal principal()
|
||||
public String toString()
|
||||
##
|
||||
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.context.Origin$Shell extends net.corda.core.context.Origin
|
||||
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.context.InvocationOrigin$Shell extends net.corda.core.context.InvocationOrigin
|
||||
@org.jetbrains.annotations.NotNull public java.security.Principal principal()
|
||||
public static final net.corda.core.context.Origin$Shell INSTANCE
|
||||
public static final net.corda.core.context.InvocationOrigin$Shell INSTANCE
|
||||
##
|
||||
@net.corda.core.serialization.CordaSerializable public final class net.corda.core.context.Trace extends java.lang.Object
|
||||
public <init>(net.corda.core.context.Trace$InvocationId, net.corda.core.context.Trace$SessionId)
|
||||
@ -1160,6 +1160,7 @@ public static final class net.corda.core.flows.FinalityFlow$Companion extends ja
|
||||
public String toString()
|
||||
##
|
||||
@net.corda.core.serialization.CordaSerializable public abstract class net.corda.core.flows.FlowInitiator extends java.lang.Object implements java.security.Principal
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationContext getInvocationContext()
|
||||
##
|
||||
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.flows.FlowInitiator$Peer extends net.corda.core.flows.FlowInitiator
|
||||
public <init>(net.corda.core.identity.Party)
|
||||
@ -1628,15 +1629,14 @@ public @interface net.corda.core.messaging.RPCReturnsObservables
|
||||
@org.jetbrains.annotations.NotNull public final String component2()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.flows.FlowInitiator component3()
|
||||
@org.jetbrains.annotations.Nullable public final net.corda.core.messaging.DataFeed component4()
|
||||
@org.jetbrains.annotations.Nullable public final net.corda.core.context.InvocationContext component5()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationContext context()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationContext component5()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.messaging.StateMachineInfo copy(net.corda.core.flows.StateMachineRunId, String, net.corda.core.flows.FlowInitiator, net.corda.core.messaging.DataFeed)
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.messaging.StateMachineInfo copy(net.corda.core.flows.StateMachineRunId, String, net.corda.core.flows.FlowInitiator, net.corda.core.messaging.DataFeed, net.corda.core.context.InvocationContext)
|
||||
public boolean equals(Object)
|
||||
@org.jetbrains.annotations.Nullable public final net.corda.core.context.InvocationContext getContext()
|
||||
@org.jetbrains.annotations.NotNull public final String getFlowLogicClassName()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.flows.StateMachineRunId getId()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.flows.FlowInitiator getInitiator()
|
||||
@org.jetbrains.annotations.NotNull public final net.corda.core.context.InvocationContext getInvocationContext()
|
||||
@org.jetbrains.annotations.Nullable public final net.corda.core.messaging.DataFeed getProgressTrackerStepAndUpdates()
|
||||
public int hashCode()
|
||||
@org.jetbrains.annotations.NotNull public String toString()
|
||||
|
@ -2,7 +2,7 @@ package net.corda.client.jfx
|
||||
|
||||
import net.corda.client.jfx.model.NodeMonitorModel
|
||||
import net.corda.client.jfx.model.ProgressTrackingEvent
|
||||
import net.corda.core.context.Origin
|
||||
import net.corda.core.context.InvocationOrigin
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.crypto.isFulfilledBy
|
||||
@ -148,8 +148,8 @@ class NodeMonitorModelTest {
|
||||
// ISSUE
|
||||
expect { add: StateMachineUpdate.Added ->
|
||||
issueSmId = add.id
|
||||
val context = add.stateMachineInfo.context()
|
||||
require(context.origin is Origin.RPC && context.principal().name == "user1")
|
||||
val context = add.stateMachineInfo.invocationContext
|
||||
require(context.origin is InvocationOrigin.RPC && context.principal().name == "user1")
|
||||
},
|
||||
expect { remove: StateMachineUpdate.Removed ->
|
||||
require(remove.id == issueSmId)
|
||||
@ -157,8 +157,8 @@ class NodeMonitorModelTest {
|
||||
// MOVE - N.B. There are other framework flows that happen in parallel for the remote resolve transactions flow
|
||||
expect(match = { it.stateMachineInfo.flowLogicClassName == CashPaymentFlow::class.java.name }) { add: StateMachineUpdate.Added ->
|
||||
moveSmId = add.id
|
||||
val context = add.stateMachineInfo.context()
|
||||
require(context.origin is Origin.RPC && context.principal().name == "user1")
|
||||
val context = add.stateMachineInfo.invocationContext
|
||||
require(context.origin is InvocationOrigin.RPC && context.principal().name == "user1")
|
||||
},
|
||||
expect(match = { it is StateMachineUpdate.Removed && it.id == moveSmId }) {
|
||||
}
|
||||
@ -169,8 +169,8 @@ class NodeMonitorModelTest {
|
||||
sequence(
|
||||
// MOVE
|
||||
expect { add: StateMachineUpdate.Added ->
|
||||
val context = add.stateMachineInfo.context()
|
||||
require(context.origin is Origin.Peer && aliceNode.isLegalIdentity(aliceNode.identityFromX500Name((context.origin as Origin.Peer).party)))
|
||||
val context = add.stateMachineInfo.invocationContext
|
||||
require(context.origin is InvocationOrigin.Peer && aliceNode.isLegalIdentity(aliceNode.identityFromX500Name((context.origin as InvocationOrigin.Peer).party)))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -154,11 +154,11 @@ class CordaRPCClientTest : NodeBasedTest(listOf("net.corda.finance.contracts", C
|
||||
},
|
||||
expect { update: StateMachineUpdate.Added ->
|
||||
checkRpcNotification(update.stateMachineInfo, rpcUser.username, historicalIds, externalTrace, impersonatedActor)
|
||||
sessionId = update.stateMachineInfo.context().trace.sessionId
|
||||
sessionId = update.stateMachineInfo.invocationContext.trace.sessionId
|
||||
},
|
||||
expect { update: StateMachineUpdate.Added ->
|
||||
checkRpcNotification(update.stateMachineInfo, rpcUser.username, historicalIds, externalTrace, impersonatedActor)
|
||||
assertThat(update.stateMachineInfo.context().trace.sessionId).isEqualTo(sessionId)
|
||||
assertThat(update.stateMachineInfo.invocationContext.trace.sessionId).isEqualTo(sessionId)
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -166,15 +166,13 @@ class CordaRPCClientTest : NodeBasedTest(listOf("net.corda.finance.contracts", C
|
||||
}
|
||||
|
||||
private fun checkShellNotification(info: StateMachineInfo) {
|
||||
|
||||
val context = info.context()
|
||||
assertThat(context.origin).isInstanceOf(Origin.Shell::class.java)
|
||||
val context = info.invocationContext
|
||||
assertThat(context.origin).isInstanceOf(InvocationOrigin.Shell::class.java)
|
||||
}
|
||||
|
||||
private fun checkRpcNotification(info: StateMachineInfo, rpcUsername: String, historicalIds: MutableSet<Trace.InvocationId>, externalTrace: Trace?, impersonatedActor: Actor?) {
|
||||
|
||||
val context = info.context()
|
||||
assertThat(context.origin).isInstanceOf(Origin.RPC::class.java)
|
||||
val context = info.invocationContext
|
||||
assertThat(context.origin).isInstanceOf(InvocationOrigin.RPC::class.java)
|
||||
assertThat(context.externalTrace).isEqualTo(externalTrace)
|
||||
assertThat(context.impersonatedActor).isEqualTo(impersonatedActor)
|
||||
assertThat(context.actor?.id?.value).isEqualTo(rpcUsername)
|
||||
|
@ -1,9 +0,0 @@
|
||||
package net.corda.core.context
|
||||
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
|
||||
/**
|
||||
* Authentication / Authorisation Service ID.
|
||||
*/
|
||||
@CordaSerializable
|
||||
data class AuthServiceId(val value: String)
|
@ -9,52 +9,50 @@ import java.security.Principal
|
||||
* Models the information needed to trace an invocation in Corda.
|
||||
* Includes initiating actor, origin, trace information, and optional external trace information to correlate clients' IDs.
|
||||
*
|
||||
* @param origin origin of the invocation.
|
||||
* @param trace Corda invocation trace.
|
||||
* @param actor acting agent of the invocation, used to derive the security principal.
|
||||
* @param externalTrace optional external invocation trace for cross-system logs correlation.
|
||||
* @param impersonatedActor optional impersonated actor, used for logging but not for authorisation.
|
||||
* @property origin Origin of the invocation.
|
||||
* @property trace Corda invocation trace.
|
||||
* @property actor Acting agent of the invocation, used to derive the security principal.
|
||||
* @property externalTrace Optional external invocation trace for cross-system logs correlation.
|
||||
* @property impersonatedActor Optional impersonated actor, used for logging but not for authorisation.
|
||||
*/
|
||||
@CordaSerializable
|
||||
data class InvocationContext(val origin: Origin, val trace: Trace, val actor: Actor?, val externalTrace: Trace? = null, val impersonatedActor: Actor? = null) {
|
||||
|
||||
data class InvocationContext(val origin: InvocationOrigin, val trace: Trace, val actor: Actor?, val externalTrace: Trace? = null, val impersonatedActor: Actor? = null) {
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* Creates an [InvocationContext] with a [Trace] that defaults to a [java.util.UUID] as value and [java.time.Instant.now] timestamp.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun newInstance(origin: Origin, trace: Trace = Trace.newInstance(), actor: Actor? = null, externalTrace: Trace? = null, impersonatedActor: Actor? = null) = InvocationContext(origin, trace, actor, externalTrace, impersonatedActor)
|
||||
fun newInstance(origin: InvocationOrigin, trace: Trace = Trace.newInstance(), actor: Actor? = null, externalTrace: Trace? = null, impersonatedActor: Actor? = null) = InvocationContext(origin, trace, actor, externalTrace, impersonatedActor)
|
||||
|
||||
/**
|
||||
* Creates an [InvocationContext] with [Origin.RPC] origin.
|
||||
* Creates an [InvocationContext] with [InvocationOrigin.RPC] origin.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun rpc(actor: Actor, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null, impersonatedActor: Actor? = null): InvocationContext = newInstance(Origin.RPC(actor), trace, actor, externalTrace, impersonatedActor)
|
||||
fun rpc(actor: Actor, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null, impersonatedActor: Actor? = null): InvocationContext = newInstance(InvocationOrigin.RPC(actor), trace, actor, externalTrace, impersonatedActor)
|
||||
|
||||
/**
|
||||
* Creates an [InvocationContext] with [Origin.Peer] origin.
|
||||
* Creates an [InvocationContext] with [InvocationOrigin.Peer] origin.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun peer(party: CordaX500Name, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null, impersonatedActor: Actor? = null): InvocationContext = newInstance(Origin.Peer(party), trace, null, externalTrace, impersonatedActor)
|
||||
fun peer(party: CordaX500Name, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null, impersonatedActor: Actor? = null): InvocationContext = newInstance(InvocationOrigin.Peer(party), trace, null, externalTrace, impersonatedActor)
|
||||
|
||||
/**
|
||||
* Creates an [InvocationContext] with [Origin.Service] origin.
|
||||
* Creates an [InvocationContext] with [InvocationOrigin.Service] origin.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun service(serviceClassName: String, owningLegalIdentity: CordaX500Name, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null): InvocationContext = newInstance(Origin.Service(serviceClassName, owningLegalIdentity), trace, null, externalTrace)
|
||||
fun service(serviceClassName: String, owningLegalIdentity: CordaX500Name, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null): InvocationContext = newInstance(InvocationOrigin.Service(serviceClassName, owningLegalIdentity), trace, null, externalTrace)
|
||||
|
||||
/**
|
||||
* Creates an [InvocationContext] with [Origin.Scheduled] origin.
|
||||
* Creates an [InvocationContext] with [InvocationOrigin.Scheduled] origin.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun scheduled(scheduledState: ScheduledStateRef, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null): InvocationContext = newInstance(Origin.Scheduled(scheduledState), trace, null, externalTrace)
|
||||
fun scheduled(scheduledState: ScheduledStateRef, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null): InvocationContext = newInstance(InvocationOrigin.Scheduled(scheduledState), trace, null, externalTrace)
|
||||
|
||||
/**
|
||||
* Creates an [InvocationContext] with [Origin.Shell] origin.
|
||||
* Creates an [InvocationContext] with [InvocationOrigin.Shell] origin.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun shell(trace: Trace = Trace.newInstance(), externalTrace: Trace? = null): InvocationContext = InvocationContext(Origin.Shell, trace, null, externalTrace)
|
||||
fun shell(trace: Trace = Trace.newInstance(), externalTrace: Trace? = null): InvocationContext = InvocationContext(InvocationOrigin.Shell, trace, null, externalTrace)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,11 +81,10 @@ data class Actor(val id: Id, val serviceId: AuthServiceId, val owningLegalIdenti
|
||||
}
|
||||
|
||||
/**
|
||||
* Invocation origin for tracing purposes.
|
||||
* Represents the source of an action such as a flow start, an RPC, a shell command etc.
|
||||
*/
|
||||
@CordaSerializable
|
||||
sealed class Origin {
|
||||
|
||||
sealed class InvocationOrigin {
|
||||
/**
|
||||
* Returns the [Principal] for a given [Actor].
|
||||
*/
|
||||
@ -96,32 +93,28 @@ sealed class Origin {
|
||||
/**
|
||||
* Origin was an RPC call.
|
||||
*/
|
||||
data class RPC(private val actor: Actor) : Origin() {
|
||||
|
||||
data class RPC(private val actor: Actor) : InvocationOrigin() {
|
||||
override fun principal() = Principal { actor.id.value }
|
||||
}
|
||||
|
||||
/**
|
||||
* Origin was a message sent by a [Peer].
|
||||
*/
|
||||
data class Peer(val party: CordaX500Name) : Origin() {
|
||||
|
||||
data class Peer(val party: CordaX500Name) : InvocationOrigin() {
|
||||
override fun principal() = Principal { party.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Origin was a Corda Service.
|
||||
*/
|
||||
data class Service(val serviceClassName: String, val owningLegalIdentity: CordaX500Name) : Origin() {
|
||||
|
||||
data class Service(val serviceClassName: String, val owningLegalIdentity: CordaX500Name) : InvocationOrigin() {
|
||||
override fun principal() = Principal { serviceClassName }
|
||||
}
|
||||
|
||||
/**
|
||||
* Origin was a scheduled activity.
|
||||
*/
|
||||
data class Scheduled(val scheduledState: ScheduledStateRef) : Origin() {
|
||||
|
||||
data class Scheduled(val scheduledState: ScheduledStateRef) : InvocationOrigin() {
|
||||
override fun principal() = Principal { "Scheduler" }
|
||||
}
|
||||
|
||||
@ -129,8 +122,13 @@ sealed class Origin {
|
||||
/**
|
||||
* Origin was the Shell.
|
||||
*/
|
||||
object Shell : Origin() {
|
||||
|
||||
object Shell : InvocationOrigin() {
|
||||
override fun principal() = Principal { "Shell User" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authentication / Authorisation Service ID.
|
||||
*/
|
||||
@CordaSerializable
|
||||
data class AuthServiceId(val value: String)
|
@ -1,45 +1,69 @@
|
||||
package net.corda.core.flows
|
||||
|
||||
import net.corda.core.context.Actor
|
||||
import net.corda.core.context.AuthServiceId
|
||||
import net.corda.core.context.InvocationContext
|
||||
import net.corda.core.context.InvocationOrigin
|
||||
import net.corda.core.contracts.ScheduledStateRef
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import java.security.Principal
|
||||
|
||||
/**
|
||||
* FlowInitiator holds information on who started the flow. We have different ways of doing that: via RPC [FlowInitiator.RPC],
|
||||
* communication started by peer node [FlowInitiator.Peer], scheduled flows [FlowInitiator.Scheduled]
|
||||
* or via the Corda Shell [FlowInitiator.Shell].
|
||||
* Please note that [FlowInitiator] has been superceded by [net.corda.core.context.InvocationContext], which offers
|
||||
* more detail for the same event.
|
||||
*
|
||||
* FlowInitiator holds information on who started the flow. We have different ways of doing that: via [FlowInitiator.RPC],
|
||||
* communication started by peer nodes ([FlowInitiator.Peer]), scheduled flows ([FlowInitiator.Scheduled])
|
||||
* or via the Corda Shell ([FlowInitiator.Shell]).
|
||||
*/
|
||||
@Deprecated("Do not use these types. Future releases might remove them.")
|
||||
@CordaSerializable
|
||||
sealed class FlowInitiator : Principal {
|
||||
/** Started using [net.corda.core.messaging.CordaRPCOps.startFlowDynamic]. */
|
||||
@Deprecated("Do not use this type. Future releases might remove it.")
|
||||
data class RPC(val username: String) : FlowInitiator() {
|
||||
override fun getName(): String = username
|
||||
}
|
||||
|
||||
/** Started when we get new session initiation request. */
|
||||
@Deprecated("Do not use this type. Future releases might remove it.")
|
||||
data class Peer(val party: Party) : FlowInitiator() {
|
||||
override fun getName(): String = party.name.toString()
|
||||
}
|
||||
|
||||
/** Started by a CordaService. */
|
||||
@Deprecated("Do not use this type. Future releases might remove it.")
|
||||
data class Service(val serviceClassName: String) : FlowInitiator() {
|
||||
override fun getName(): String = serviceClassName
|
||||
}
|
||||
|
||||
/** Started as scheduled activity. */
|
||||
@Deprecated("Do not use this type. Future releases might remove it.")
|
||||
data class Scheduled(val scheduledState: ScheduledStateRef) : FlowInitiator() {
|
||||
override fun getName(): String = "Scheduler"
|
||||
}
|
||||
|
||||
// TODO When proper ssh access enabled, add username/use RPC?
|
||||
@Deprecated("Do not use this type. Future releases might remove it.")
|
||||
object Shell : FlowInitiator() {
|
||||
override fun getName(): String = "Shell User"
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an [InvocationContext], which is equivalent to this object but expressed using the successor to this
|
||||
* class hierarchy (which is now deprecated). The returned object has less information than it could have, so
|
||||
* prefer to use fetch an invocation context directly if you can (e.g. in [net.corda.core.messaging.StateMachineInfo])
|
||||
*/
|
||||
val invocationContext: InvocationContext get() {
|
||||
val unknownName = CordaX500Name("UNKNOWN", "UNKNOWN", "GB")
|
||||
var actor: Actor? = null
|
||||
val origin: InvocationOrigin
|
||||
when (this) {
|
||||
is FlowInitiator.RPC -> {
|
||||
actor = Actor(Actor.Id(this.username), AuthServiceId("UNKNOWN"), unknownName)
|
||||
origin = InvocationOrigin.RPC(actor)
|
||||
}
|
||||
is FlowInitiator.Peer -> origin = InvocationOrigin.Peer(this.party.name)
|
||||
is FlowInitiator.Service -> origin = InvocationOrigin.Service(this.serviceClassName, unknownName)
|
||||
FlowInitiator.Shell -> origin = InvocationOrigin.Shell
|
||||
is FlowInitiator.Scheduled -> origin = InvocationOrigin.Scheduled(this.scheduledState)
|
||||
}
|
||||
return InvocationContext.newInstance(origin = origin, actor = actor)
|
||||
}
|
||||
}
|
@ -43,7 +43,7 @@ import java.time.Instant
|
||||
* also has a version property to allow you to version your flow and enables a node to restrict support for the flow to
|
||||
* that particular version.
|
||||
*
|
||||
* Functions that suspend the flow (including all functions on [FlowSession]) accept a [maySkipCheckpoint] parameter
|
||||
* Functions that suspend the flow (including all functions on [FlowSession]) accept a maySkipCheckpoint parameter
|
||||
* defaulting to false, false meaning a checkpoint should always be created on suspend. This parameter may be set to
|
||||
* true which allows the implementation to potentially optimise away the checkpoint, saving a roundtrip to the database.
|
||||
*
|
||||
@ -53,6 +53,7 @@ import java.time.Instant
|
||||
* parameter the flow must be prepared for scenarios where a previous running of the flow *already committed its
|
||||
* relevant database transactions*. Only set this option to true if you know what you're doing.
|
||||
*/
|
||||
@Suppress("DEPRECATION", "DeprecatedCallableAddReplaceWith")
|
||||
abstract class FlowLogic<out T> {
|
||||
/** This is where you should log things to. */
|
||||
val logger: Logger get() = stateMachine.logger
|
||||
@ -61,14 +62,14 @@ abstract class FlowLogic<out T> {
|
||||
/**
|
||||
* Return the outermost [FlowLogic] instance, or null if not in a flow.
|
||||
*/
|
||||
@JvmStatic
|
||||
@Suppress("unused") @JvmStatic
|
||||
val currentTopLevel: FlowLogic<*>? get() = (Strand.currentStrand() as? FlowStateMachine<*>)?.logic
|
||||
|
||||
/**
|
||||
* If on a flow, suspends the flow and only wakes it up after at least [duration] time has passed. Otherwise,
|
||||
* just sleep for [duration]. This sleep function is not designed to aid scheduling, for which you should
|
||||
* consider using [SchedulableState]. It is designed to aid with managing contention for which you have not
|
||||
* managed via another means.
|
||||
* consider using [net.corda.core.contracts.SchedulableState]. It is designed to aid with managing contention
|
||||
* for which you have not managed via another means.
|
||||
*
|
||||
* Warning: long sleeps and in general long running flows are highly discouraged, as there is currently no
|
||||
* support for flow migration! This method will throw an exception if you attempt to sleep for longer than
|
||||
@ -78,7 +79,7 @@ abstract class FlowLogic<out T> {
|
||||
@JvmStatic
|
||||
@Throws(FlowException::class)
|
||||
fun sleep(duration: Duration) {
|
||||
if (duration.compareTo(Duration.ofMinutes(5)) > 0) {
|
||||
if (duration > Duration.ofMinutes(5)) {
|
||||
throw FlowException("Attempt to sleep for longer than 5 minutes is not supported. Consider using SchedulableState.")
|
||||
}
|
||||
(Strand.currentStrand() as? FlowStateMachine<*>)?.sleepUntil(Instant.now() + duration) ?: Strand.sleep(duration.toMillis())
|
||||
@ -428,6 +429,7 @@ abstract class FlowLogic<out T> {
|
||||
|
||||
// This is the flow used for managing sessions. It defaults to the current flow but if this is an inlined sub-flow
|
||||
// then it will point to the flow it's been inlined to.
|
||||
@Suppress("LeakingThis")
|
||||
private var flowUsedForSessions: FlowLogic<*> = this
|
||||
|
||||
private fun maybeWireUpProgressTracking(subLogic: FlowLogic<*>) {
|
||||
|
@ -4,7 +4,7 @@ import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.context.Actor
|
||||
import net.corda.core.context.AuthServiceId
|
||||
import net.corda.core.context.InvocationContext
|
||||
import net.corda.core.context.Origin
|
||||
import net.corda.core.context.InvocationOrigin
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.flows.FlowInitiator
|
||||
@ -29,44 +29,40 @@ import java.io.InputStream
|
||||
import java.security.PublicKey
|
||||
import java.time.Instant
|
||||
|
||||
private val unknownName = CordaX500Name("UNKNOWN", "UNKNOWN", "GB")
|
||||
|
||||
/**
|
||||
* Represents information about a flow (the name "state machine" is legacy, Kotlin users can use the [FlowInfo] type
|
||||
* alias). You can access progress tracking, information about why the flow was started and so on.
|
||||
*/
|
||||
@CordaSerializable
|
||||
data class StateMachineInfo @JvmOverloads constructor(
|
||||
/** A univerally unique ID ([java.util.UUID]) representing this particular instance of the named flow. */
|
||||
val id: StateMachineRunId,
|
||||
/** The JVM class name of the flow code. */
|
||||
val flowLogicClassName: String,
|
||||
val initiator: FlowInitiator,
|
||||
/**
|
||||
* An object representing information about the initiator of the flow. Note that this field is
|
||||
* superceded by the [invocationContext] property, which has more detail.
|
||||
*/
|
||||
@Deprecated("There is more info available using 'context'") val initiator: FlowInitiator,
|
||||
/** A [DataFeed] of the current progress step as a human readable string, and updates to that string. */
|
||||
val progressTrackerStepAndUpdates: DataFeed<String, String>?,
|
||||
val context: InvocationContext? = null
|
||||
/** An [InvocationContext] describing why and by whom the flow was started. */
|
||||
val invocationContext: InvocationContext = initiator.invocationContext
|
||||
) {
|
||||
fun context(): InvocationContext = context ?: contextFrom(initiator)
|
||||
|
||||
private fun contextFrom(initiator: FlowInitiator): InvocationContext {
|
||||
var actor: Actor? = null
|
||||
val origin: Origin
|
||||
when (initiator) {
|
||||
is FlowInitiator.RPC -> {
|
||||
actor = Actor(Actor.Id(initiator.username), AuthServiceId("UNKNOWN"), unknownName)
|
||||
origin = Origin.RPC(actor)
|
||||
}
|
||||
is FlowInitiator.Peer -> origin = Origin.Peer(initiator.party.name)
|
||||
is FlowInitiator.Service -> origin = Origin.Service(initiator.serviceClassName, unknownName)
|
||||
is FlowInitiator.Shell -> origin = Origin.Shell
|
||||
is FlowInitiator.Scheduled -> origin = Origin.Scheduled(initiator.scheduledState)
|
||||
}
|
||||
return InvocationContext.newInstance(origin = origin, actor = actor)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun copy(id: StateMachineRunId = this.id,
|
||||
flowLogicClassName: String = this.flowLogicClassName,
|
||||
initiator: FlowInitiator = this.initiator,
|
||||
progressTrackerStepAndUpdates: DataFeed<String, String>? = this.progressTrackerStepAndUpdates): StateMachineInfo {
|
||||
return copy(id = id, flowLogicClassName = flowLogicClassName, initiator = initiator, progressTrackerStepAndUpdates = progressTrackerStepAndUpdates, context = context)
|
||||
return copy(id = id, flowLogicClassName = flowLogicClassName, initiator = initiator, progressTrackerStepAndUpdates = progressTrackerStepAndUpdates, invocationContext = invocationContext)
|
||||
}
|
||||
|
||||
override fun toString(): String = "${javaClass.simpleName}($id, $flowLogicClassName)"
|
||||
}
|
||||
|
||||
/** An alias for [StateMachineInfo] which uses more modern terminology. */
|
||||
typealias FlowInfo = StateMachineInfo
|
||||
|
||||
@CordaSerializable
|
||||
sealed class StateMachineUpdate {
|
||||
abstract val id: StateMachineRunId
|
||||
|
@ -3,7 +3,7 @@ package net.corda.node.internal
|
||||
import net.corda.client.rpc.notUsed
|
||||
import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.context.InvocationContext
|
||||
import net.corda.core.context.Origin
|
||||
import net.corda.core.context.InvocationOrigin
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.flows.FlowInitiator
|
||||
@ -311,15 +311,15 @@ internal class CordaRPCOpsImpl(
|
||||
|
||||
val principal = origin.principal().name
|
||||
return when (origin) {
|
||||
is Origin.RPC -> FlowInitiator.RPC(principal)
|
||||
is Origin.Peer -> services.identityService.wellKnownPartyFromX500Name((origin as Origin.Peer).party)?.let { FlowInitiator.Peer(it) } ?: throw IllegalStateException("Unknown peer with name ${(origin as Origin.Peer).party}.")
|
||||
is Origin.Service -> FlowInitiator.Service(principal)
|
||||
Origin.Shell -> FlowInitiator.Shell
|
||||
is Origin.Scheduled -> FlowInitiator.Scheduled((origin as Origin.Scheduled).scheduledState)
|
||||
is InvocationOrigin.RPC -> FlowInitiator.RPC(principal)
|
||||
is InvocationOrigin.Peer -> services.identityService.wellKnownPartyFromX500Name((origin as InvocationOrigin.Peer).party)?.let { FlowInitiator.Peer(it) } ?: throw IllegalStateException("Unknown peer with name ${(origin as InvocationOrigin.Peer).party}.")
|
||||
is InvocationOrigin.Service -> FlowInitiator.Service(principal)
|
||||
is InvocationOrigin.Shell -> FlowInitiator.Shell
|
||||
is InvocationOrigin.Scheduled -> FlowInitiator.Scheduled((origin as InvocationOrigin.Scheduled).scheduledState)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = contextLogger()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package net.corda.node.services.events
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import net.corda.core.context.InvocationContext
|
||||
import net.corda.core.context.Origin
|
||||
import net.corda.core.context.InvocationOrigin
|
||||
import net.corda.core.contracts.SchedulableState
|
||||
import net.corda.core.contracts.ScheduledActivity
|
||||
import net.corda.core.contracts.ScheduledStateRef
|
||||
@ -256,7 +256,7 @@ class NodeSchedulerService(private val clock: CordaClock,
|
||||
if (scheduledFlow != null) {
|
||||
flowName = scheduledFlow.javaClass.name
|
||||
// TODO refactor the scheduler to store and propagate the original invocation context
|
||||
val context = InvocationContext.newInstance(Origin.Scheduled(scheduledState))
|
||||
val context = InvocationContext.newInstance(InvocationOrigin.Scheduled(scheduledState))
|
||||
val future = flowStarter.startFlow(scheduledFlow, context).flatMap { it.resultFuture }
|
||||
future.then {
|
||||
unfinishedSchedules.countDown()
|
||||
|
@ -72,7 +72,7 @@ class FlowWatchPrintingSubscriber(private val toStream: RenderPrintWriter) : Sub
|
||||
table.add(RowElement().add(
|
||||
LabelElement(formatFlowId(smmUpdate.id)),
|
||||
LabelElement(formatFlowName(smmUpdate.stateMachineInfo.flowLogicClassName)),
|
||||
LabelElement(formatInvocationContext(smmUpdate.stateMachineInfo.context())),
|
||||
LabelElement(formatInvocationContext(smmUpdate.stateMachineInfo.invocationContext)),
|
||||
LabelElement("In progress")
|
||||
).style(stateColor(smmUpdate).fg()))
|
||||
indexMap[smmUpdate.id] = table.rows.size - 1
|
||||
|
@ -4,7 +4,7 @@ import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.StartableByService
|
||||
import net.corda.core.context.InvocationContext
|
||||
import net.corda.core.context.Origin
|
||||
import net.corda.core.context.InvocationOrigin
|
||||
import net.corda.core.node.AppServiceHub
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.node.services.CordaService
|
||||
@ -46,7 +46,7 @@ class TestCordaService(val appServiceHub: AppServiceHub): SingletonSerializeAsTo
|
||||
fun startServiceFlow() {
|
||||
val handle = appServiceHub.startFlow(DummyServiceFlow())
|
||||
val context = handle.returnValue.get()
|
||||
assertEquals(this.javaClass.name, (context.origin as Origin.Service).serviceClassName)
|
||||
assertEquals(this.javaClass.name, (context.origin as InvocationOrigin.Service).serviceClassName)
|
||||
}
|
||||
|
||||
fun startServiceFlowAndTrack() {
|
||||
|
@ -2,7 +2,7 @@ package net.corda.node.services.events
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.context.Origin
|
||||
import net.corda.core.context.InvocationOrigin
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.flows.FinalityFlow
|
||||
import net.corda.core.flows.FlowLogic
|
||||
@ -122,7 +122,7 @@ class ScheduledFlowTests {
|
||||
aliceNode.smm.track().updates.subscribe {
|
||||
if (it is StateMachineManager.Change.Add) {
|
||||
val context = it.logic.stateMachine.context
|
||||
if (context.origin is Origin.Scheduled)
|
||||
if (context.origin is InvocationOrigin.Scheduled)
|
||||
countScheduledFlows++
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.context.Actor
|
||||
import net.corda.core.context.AuthServiceId
|
||||
import net.corda.core.context.InvocationContext
|
||||
import net.corda.core.context.Origin
|
||||
import net.corda.core.context.InvocationOrigin
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
@ -65,7 +65,8 @@ fun testActor(owningLegalIdentity: CordaX500Name = CordaX500Name("Test Company I
|
||||
fun testContext(owningLegalIdentity: CordaX500Name = CordaX500Name("Test Company Inc.", "London", "GB")) = InvocationContext.rpc(testActor(owningLegalIdentity))
|
||||
|
||||
/**
|
||||
* Creates a new [InvocationContext] for testing purposes.
|
||||
* Starts an already constructed flow. Note that you must be on the server thread to call this method. [InvocationContext]
|
||||
* has origin [InvocationOrigin.RPC] and actor with id "Only For Testing".
|
||||
*/
|
||||
fun StartedNodeServices.newContext() = testContext(myInfo.chooseIdentity().name)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user