From aeb817a2808ad5c444a413e01cdb0f7a280594b4 Mon Sep 17 00:00:00 2001 From: Sameer Ahmad Date: Tue, 21 May 2024 13:10:59 +0100 Subject: [PATCH] Add step function sync execution (#66) Co-authored-by: Sameer Ahmad --- .../scala/dev/joss/gatling/sfn/SfnDsl.scala | 4 ++ .../sfn/action/StartSyncExecutionAction.scala | 67 +++++++++++++++++++ .../StartSyncExecutionActionBuilder.scala | 24 +++++++ .../sfn/request/SfnDslBuilderBase.scala | 30 ++++++++- 4 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/main/scala/dev/joss/gatling/sfn/action/StartSyncExecutionAction.scala create mode 100644 src/main/scala/dev/joss/gatling/sfn/action/StartSyncExecutionActionBuilder.scala diff --git a/src/main/scala/dev/joss/gatling/sfn/SfnDsl.scala b/src/main/scala/dev/joss/gatling/sfn/SfnDsl.scala index 77c923d..1757483 100644 --- a/src/main/scala/dev/joss/gatling/sfn/SfnDsl.scala +++ b/src/main/scala/dev/joss/gatling/sfn/SfnDsl.scala @@ -44,6 +44,10 @@ trait SfnDsl { builder: StartExecutionDslBuilder ): ActionBuilder = builder.build + implicit def sfnDslBuilder2ActionBuilder( + builder: StartSyncExecutionActionBuilder + ): ActionBuilder = builder.build + implicit def sfnDslBuilder2ActionBuilder( builder: CheckSucceededDslBuilder ): ActionBuilder = builder.build diff --git a/src/main/scala/dev/joss/gatling/sfn/action/StartSyncExecutionAction.scala b/src/main/scala/dev/joss/gatling/sfn/action/StartSyncExecutionAction.scala new file mode 100644 index 0000000..f85a6b8 --- /dev/null +++ b/src/main/scala/dev/joss/gatling/sfn/action/StartSyncExecutionAction.scala @@ -0,0 +1,67 @@ +package uk.co.capitalone.services.decision.processor.utils + +import dev.joss.gatling.sfn.action.SfnActionBase +import dev.joss.gatling.sfn.request.attributes.SfnExecuteAttributes +import io.gatling.commons.util.Clock +import io.gatling.core.CoreComponents +import io.gatling.core.action.Action +import io.gatling.core.session._ +import io.gatling.core.stats.StatsEngine +import software.amazon.awssdk.services.sfn.SfnClient +import software.amazon.awssdk.services.sfn.model.StartSyncExecutionRequest + +case class StartSyncExecutionAction( + sfnClient: SfnClient, + coreComponents: CoreComponents, + next: Action, + id: String, + attributes: SfnExecuteAttributes +) extends SfnActionBase { + override def statsEngine: StatsEngine = coreComponents.statsEngine + override def clock: Clock = coreComponents.clock + override def name: String = "Step Function Sync Execution" + override def execute(session: Session): Unit = { + startSyncExecution(session) + } + + private def startSyncExecution( + session: Session + ): Unit = { + val request = StartSyncExecutionRequest.builder() + + var stateMachineArn = "" + attributes.stateMachineArn(session).map { arn => + request.stateMachineArn(arn) + stateMachineArn = arn + } + + attributes.input(session).map { arn => + request.input(arn) + } + + val tryStartExecutionResponse = + trySfnRequest(() => sfnClient.startSyncExecution(request.build())) + + val startTime = tryStartExecutionResponse.get.startDate().toEpochMilli + val endTime = tryStartExecutionResponse.get.stopDate().toEpochMilli + if (tryStartExecutionResponse.get.status().toString.equals("SUCCEEDED")) { + logSuccess( + name, + session, + startTime, + endTime, + "The step function successfully completed!" + ) + } else { + val failedMessage: String = + tryStartExecutionResponse.failed.get.getMessage + logFailure( + name, + session, + startTime, + endTime, + s"Could not execute step function with ARN: $stateMachineArn. Reason: $failedMessage" + ) + } + } +} diff --git a/src/main/scala/dev/joss/gatling/sfn/action/StartSyncExecutionActionBuilder.scala b/src/main/scala/dev/joss/gatling/sfn/action/StartSyncExecutionActionBuilder.scala new file mode 100644 index 0000000..2308727 --- /dev/null +++ b/src/main/scala/dev/joss/gatling/sfn/action/StartSyncExecutionActionBuilder.scala @@ -0,0 +1,24 @@ +package uk.co.capitalone.services.decision.processor.utils + +import dev.joss.gatling.sfn.action.SfnActionBuilderBase +import dev.joss.gatling.sfn.request.attributes.SfnExecuteAttributes +import io.gatling.core.action.Action +import io.gatling.core.structure.ScenarioContext +import io.gatling.core.util.NameGen + +case class StartSyncExecutionActionBuilder(attributes: SfnExecuteAttributes) + extends SfnActionBuilderBase + with NameGen { + override def build(ctx: ScenarioContext, next: Action): Action = { + val protocol = getProtocol(ctx) + val client = protocol.sfnClient + StartSyncExecutionAction( + client, + ctx.coreComponents, + next, + genName(""), + attributes + ) + } + +} diff --git a/src/main/scala/dev/joss/gatling/sfn/request/SfnDslBuilderBase.scala b/src/main/scala/dev/joss/gatling/sfn/request/SfnDslBuilderBase.scala index 5d82fac..9c7ec89 100644 --- a/src/main/scala/dev/joss/gatling/sfn/request/SfnDslBuilderBase.scala +++ b/src/main/scala/dev/joss/gatling/sfn/request/SfnDslBuilderBase.scala @@ -3,7 +3,8 @@ package dev.joss.gatling.sfn.request import dev.joss.gatling.sfn.action.{ CheckStateSucceededActionBuilder, CheckSucceededActionBuilder, - StartExecutionActionBuilder + StartExecutionActionBuilder, + StartSyncExecutionActionBuilder } import dev.joss.gatling.sfn.request.attributes.{ SfnCheckStateAttributes, @@ -16,6 +17,8 @@ import software.amazon.awssdk.services.sfn.model.HistoryEventType final class SfnDslBuilderBase(requestName: Expression[String]) { def startExecution: StartExecutionDslBuilder.Arn = new StartExecutionDslBuilder.Arn(requestName) + def startSyncExecution: StartSyncExecutionDslBuilder.Arn = + new StartSyncExecutionDslBuilder.Arn(requestName) def checkSucceeded: CheckSucceededDslBuilder = CheckSucceededDslBuilder(requestName, None) @@ -27,6 +30,31 @@ final class SfnDslBuilderBase(requestName: Expression[String]) { new CheckStateSucceededDslBuilder.StateName(requestName) } +object StartSyncExecutionDslBuilder { + final class Arn(requestName: Expression[String]) { + def arn(arn: Expression[String]): Payload = + new Payload(requestName, arn) + } + + final class Payload( + requestName: Expression[String], + executionArn: Expression[String] + ) { + def payload(payload: Expression[String]): StartSyncExecutionDslBuilder = + StartSyncExecutionDslBuilder( + SfnExecuteAttributes(requestName, executionArn, payload), + StartSyncExecutionActionBuilder + ) + } +} + +final case class StartSyncExecutionDslBuilder( + attributes: SfnExecuteAttributes, + factory: SfnExecuteAttributes => StartSyncExecutionActionBuilder +) { + def build: ActionBuilder = factory(attributes) +} + object StartExecutionDslBuilder { final class Arn(requestName: Expression[String]) { def arn(arn: Expression[String]): Payload =