mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-04 22:50:18 +00:00
feat(compiler): Handle error function exit in tracing mode [LNG-250] (#921)
* Wrap function calls with xor * Do not detach tracing call in case of error exit * Fix comment
This commit is contained in:
parent
030a0d464b
commit
03d23eb577
@ -25,11 +25,16 @@ object ValueModel {
|
|||||||
def errorCode(error: VarModel): Option[VarModel] =
|
def errorCode(error: VarModel): Option[VarModel] =
|
||||||
error.intoField("error_code")
|
error.intoField("error_code")
|
||||||
|
|
||||||
|
def errorMessage(error: VarModel): Option[VarModel] =
|
||||||
|
error.intoField("message")
|
||||||
|
|
||||||
val error = VarModel.fromVarRaw(ValueRaw.error)
|
val error = VarModel.fromVarRaw(ValueRaw.error)
|
||||||
val errorType = ValueRaw.errorType
|
val errorType = ValueRaw.errorType
|
||||||
|
|
||||||
// NOTE: It should be safe as `:error:` should have `error_code` field
|
// NOTE: It should be safe as `:error:` should have `error_code` field
|
||||||
val lastErrorCode = errorCode(error).get
|
val lastErrorCode = errorCode(error).get
|
||||||
|
// NOTE: It should be safe as `:error:` should have `message` field
|
||||||
|
val lastErrorMessage = errorMessage(error).get
|
||||||
|
|
||||||
implicit object ValueModelEq extends Eq[ValueModel] {
|
implicit object ValueModelEq extends Eq[ValueModel] {
|
||||||
override def eqv(x: ValueModel, y: ValueModel): Boolean = x == y
|
override def eqv(x: ValueModel, y: ValueModel): Boolean = x == y
|
||||||
|
@ -1,23 +1,15 @@
|
|||||||
package aqua.model.transform.funcop
|
package aqua.model.transform.funcop
|
||||||
|
|
||||||
import cats.data.Chain
|
import aqua.model.*
|
||||||
|
|
||||||
import cats.Eval
|
|
||||||
|
|
||||||
import aqua.model.{
|
|
||||||
CallModel,
|
|
||||||
CallServiceModel,
|
|
||||||
LiteralModel,
|
|
||||||
MetaModel,
|
|
||||||
OpModel,
|
|
||||||
SeqModel,
|
|
||||||
ValueModel
|
|
||||||
}
|
|
||||||
import aqua.model.transform.pre.InitPeerCallable
|
import aqua.model.transform.pre.InitPeerCallable
|
||||||
import aqua.model.ParModel
|
import aqua.model.ParModel
|
||||||
import aqua.model.DetachModel
|
import aqua.model.DetachModel
|
||||||
import aqua.model.transform.TransformConfig.TracingConfig
|
import aqua.model.transform.TransformConfig.TracingConfig
|
||||||
|
|
||||||
|
import cats.data.Chain
|
||||||
|
import cats.Eval
|
||||||
|
import aqua.types.ScalarType
|
||||||
|
|
||||||
final case class Tracing(
|
final case class Tracing(
|
||||||
enabledConfig: Option[TracingConfig],
|
enabledConfig: Option[TracingConfig],
|
||||||
initCallable: InitPeerCallable
|
initCallable: InitPeerCallable
|
||||||
@ -41,20 +33,41 @@ final case class Tracing(
|
|||||||
.fold(child)(traceCall =>
|
.fold(child)(traceCall =>
|
||||||
/* seq:
|
/* seq:
|
||||||
detach: call tracing enter
|
detach: call tracing enter
|
||||||
|
xor:
|
||||||
|
seq:
|
||||||
<call-arrow-code>
|
<call-arrow-code>
|
||||||
detach: call tracing exit */
|
detach: call tracing exit
|
||||||
|
seq:
|
||||||
|
call tracing error exit
|
||||||
|
rethrow error
|
||||||
|
*/
|
||||||
SeqModel.wrap(
|
SeqModel.wrap(
|
||||||
DetachModel.wrap(
|
DetachModel.wrap(
|
||||||
initCallable.onInitPeer.wrap(
|
initCallable.onInitPeer.wrap(
|
||||||
traceCall(Event.Enter)
|
traceCall(Event.Enter)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
XorModel.wrap(
|
||||||
|
SeqModel.wrap(
|
||||||
child,
|
child,
|
||||||
DetachModel.wrap(
|
DetachModel.wrap(
|
||||||
initCallable.onInitPeer.wrap(
|
initCallable.onInitPeer.wrap(
|
||||||
traceCall(Event.Exit)
|
traceCall(Event.Exit)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
),
|
||||||
|
SeqModel.wrap(
|
||||||
|
/**
|
||||||
|
* NOTE: Here we don't wrap trace call
|
||||||
|
* with detach because Aqua VM ignores
|
||||||
|
* it if it is detached.
|
||||||
|
*/
|
||||||
|
initCallable.onInitPeer.wrap(
|
||||||
|
traceCall(Event.ErrorExit)
|
||||||
|
),
|
||||||
|
FailModel(ValueModel.error).leaf
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -64,23 +77,47 @@ final case class Tracing(
|
|||||||
object Tracing {
|
object Tracing {
|
||||||
|
|
||||||
enum Event {
|
enum Event {
|
||||||
case Enter, Exit
|
case Enter, Exit, ErrorExit
|
||||||
|
|
||||||
def toArg: ValueModel = LiteralModel.quote(this match {
|
def toArg(suffix: String = ""): ValueModel = LiteralModel.quote((this match {
|
||||||
case Enter => "enter"
|
case Enter => "enter"
|
||||||
case Exit => "exit"
|
case Exit => "exit"
|
||||||
})
|
case ErrorExit => "exit with error"
|
||||||
|
}) + suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
def traceCallModel(config: TracingConfig, arrowName: String)(
|
private def traceCallModel(config: TracingConfig, arrowName: String)(
|
||||||
event: Event
|
event: Event
|
||||||
): OpModel.Tree =
|
): OpModel.Tree = {
|
||||||
|
val serviceCall = (msg: ValueModel) =>
|
||||||
CallServiceModel(
|
CallServiceModel(
|
||||||
LiteralModel.quote(config.serviceId),
|
LiteralModel.quote(config.serviceId),
|
||||||
config.serviceFuncName,
|
config.serviceFuncName,
|
||||||
CallModel(
|
CallModel(
|
||||||
args = List(LiteralModel.quote(arrowName), event.toArg),
|
args = List(LiteralModel.quote(arrowName), msg),
|
||||||
exportTo = Nil
|
exportTo = Nil
|
||||||
)
|
)
|
||||||
).leaf
|
).leaf
|
||||||
|
|
||||||
|
event match {
|
||||||
|
case Event.ErrorExit =>
|
||||||
|
val errorName = "-return-error-msg-"
|
||||||
|
|
||||||
|
RestrictionModel(
|
||||||
|
errorName,
|
||||||
|
ScalarType.string
|
||||||
|
).wrap(
|
||||||
|
CallServiceModel(
|
||||||
|
LiteralModel.quote("op"),
|
||||||
|
"concat_strings",
|
||||||
|
CallModel(
|
||||||
|
args = List(event.toArg(": "), ValueModel.lastErrorMessage),
|
||||||
|
exportTo = List(CallModel.Export(errorName, ScalarType.string))
|
||||||
|
)
|
||||||
|
).leaf,
|
||||||
|
serviceCall(VarModel(errorName, ScalarType.string))
|
||||||
|
)
|
||||||
|
case _ => serviceCall(event.toArg())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user