Skip to content

Commit

Permalink
Added Simulation documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
pme123 committed Dec 27, 2024
1 parent f948cbe commit 2de4306
Show file tree
Hide file tree
Showing 22 changed files with 642 additions and 532 deletions.
2 changes: 1 addition & 1 deletion 00-docs/src/docs/company/03-dmn.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,4 @@ dmnPaths: Seq[os.Path] = Seq(
exposedPort: Int = 8883,
// the image version of the DMN Tester
imageVersion: String = "latest"
```
```
105 changes: 104 additions & 1 deletion 00-docs/src/docs/company/03-simulation.md
Original file line number Diff line number Diff line change
@@ -1 +1,104 @@
# 03-simulation
# 03-simulation
Use this to add Company specific Simulation stuff like the configuration of the auth method.

The following structure is generated by `./helperCompany.scala init`:

```bash
03-simulation/src
| main/resources
| main/scala/company/simulation
| | CompanySimulation.scala
| test/scala/company/simulation
```
## CompanySimulation
The Company's base class to run the Simulations.

Example (generated by `./helperCompany.scala init`):

```scala
package mycompany.camundala.simulation

import camundala.simulation.custom.*

/**
* Add here company specific stuff, to run the Simulations.
*/
trait CompanySimulation extends BasicSimulationDsl:

override def config =
super.config //TODO Adjust config if needed

end CompanySimulation
```

## SimulationConfig
You can customize the Simulation Configuration.

```scala
super.config
.withTenantId("myTenant")
```
### Default Config

```scala
// define tenant if you have one
tenantId: Option[String] = None,
// the Camunda Port
// there are Requests that wait until the process is ready - like getTask.
// the Simulation waits 1 second between the Requests.
// so with a timeout of 10 sec it will try 10 times (retryDuration = 1.second)
maxCount: Int = 10,
// REST endpoint of Camunda
endpoint: String = "http://localhost:8080/engine-rest",
// you can add authentication with this - default there is none.
// see BasicSimulationDsl / OAuthSimulationDsl for examples
authHeader: B => B = (b: B) => b,
// the maximum LogLevel you want to print the LogEntries.
logLevel: LogLevel = LogLevel.INFO
```


## Authentication
We provide at the moment the following authentication methods:

### Basic Authentication

```scala
import camundala.simulation.custom.*

trait CompanySimulation extends BasicSimulationDsl:

override lazy val username = sys.env.getOrElse("CAMUNDA_USER", "demo")
override lazy val password = sys.env.getOrElse("CAMUNDA_PASSWORD", "demo")
//...
```

You can override the `username` and `password` to use your credentials,
default is `demo`/`demo`.

### OAuth2 Authentication

```scala
import camundala.simulation.custom.*

trait CompanySimulation extends OAuthSimulationDsl:

lazy val fsso: Fsso = Fsso(
s"$fssoBaseUrl/auth/realms/${config.tenantId.get}/protocol/openid-connect",
Map(
"grant_type" -> "password",
"client_id" -> "bpf",
"client_secret" -> fssoClientSecret,
"username" -> fssoUser,
"password" -> fssoPassword,
"scope" -> "fcs"
))
//...
private lazy val fssoBaseUrl = sys.env.getOrElse("FSSO_BASE_URL", "http://host.lima.internal:8090")
//...
```

Here you have to provide the FSSO configuration.
- `Fsso.url` is the URL of the FSSO Server.
- `Fsso.bodyForm` is the body of the POST request to get the token.

87 changes: 41 additions & 46 deletions 00-docs/src/docs/functionalityDsls/simulation.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ The diagrams must be deployed.

@:callout(info)
For the deployment I created a script that also starts the Simulation.

See [deploy](../development/projectDev.md#deploy).
@:@

## Why
Expand Down Expand Up @@ -42,15 +44,10 @@ Let's start with a basic example:
// put your simulations in the simulation package of your project (it)
package camundala.examples.invoice.simulation
// import the projects bpmns (Processes, UserTasks etc.)

import camundala.examples.invoice.bpmn.*
// import Camundala simulation DSL - for now this is the one and only
import camundala.simulation.custom.CustomSimulation

// define a class that extends from a simulation DSL
class InvoiceSimulation extends CustomSimulation

:
class InvoiceSimulation extends CompanySimulation:

simulate(
// add scenarios (comma separated)
Expand All @@ -71,6 +68,10 @@ class InvoiceSimulation extends CustomSimulation
end InvoiceSimulation
```

@:callout(info)
This class is automatically created with `./helper.scala process <processName>` - see [development > process](../development/projectDev.md#process).
@:@

#### simulate

This is the entry point for your Simulation.
Expand All @@ -89,11 +90,11 @@ In your _sbt-console_:

- run all simulations:

`It/test`
`simulation/test`

- run some simulations:

`It/testOnly *MySimulation`
`simulation/testOnly *MySimulation`

You can use any pattern, where `*` is wildcard for any characters.

Expand Down Expand Up @@ -172,36 +173,21 @@ These names are then used in the output Log:

### Configuration

The following is the default configuration:

```scala
case class SimulationConfig[B](
// define tenant if you have one
tenantId: Option[String] = None,
// the Camunda Port
// there are Requests that wait until the process is ready - like getTask.
// the Simulation waits 1 second between the Requests.
// so with a timeout of 10 sec it will try 10 times (retryDuration = 1.second)
maxCount: Int = 10,
// REST endpoint of Camunda
endpoint: String = "http://localhost:8080/engine-rest",
// you can add authentication with this - default there is none.
// see BasicSimulationDsl / OAuthSimulationDsl for examples
authHeader: B => B = (b: B) => b,
// the maximum LogLevel you want to print the LogEntries.
logLevel: LogLevel = LogLevel.INFO
)
```
The configuration is described in [03-simulation].

You can easily override it in your Simulation:

```scala
override implicit def config =
override implicit def config =
super.config
.withPort(8034)
.withLogLevel(LogLevel.DEBUG)
.withMaxCount(20)
```

Especially interesting on the level of each Simulation are:
- `logLevel` to debug the Simulation.
- `maxCount` to increase the timeout for the interactions (one count is one second).

## Scenarios

The following chapters explain the different scenario types:
Expand Down Expand Up @@ -438,7 +424,7 @@ scenario(

### Only a Scenario

You can run only a scenario at the time by just prefix your Scenario with `only`.
You can run only one are a few scenario at the time by just prefix your Scenarios with `only`.

#### Examples:

Expand All @@ -455,7 +441,7 @@ simulate(
ApproveInvoiceUT,
PrepareBankTransferUT
),
scenario(InvoiceAssignApproverDMN)
only.scenario(InvoiceAssignApproverDMN)
)
```

Expand Down Expand Up @@ -503,31 +489,29 @@ the following possibilities:
@:callout(info)
This only works for one hierarchy of sub processes.
When you have more complex sub processes, you must mock them.

**Not recommended**: please test each process separately.
@:@

## Validation

The simulation uses your BPMN DSL objects not just to run the process and its interactions.
It also uses the the input- and output domain objects to validate variables of the process.
It also uses the input- and output domain objects to validate variables of the process.

```scala
// domain classes
case class InvoiceReceipt(
creditor: String = "Great Pizza for Everyone Inc.",
amount: Double = 300.0,

...
case class In(
creditor: String = "Great Pizza for Everyone Inc.",
amount: Double = 300.0,
//...
)

case class ApproveInvoice(
approved: Boolean = true
)

...
case class Out(
approved: Boolean = true,
//...
)
//...
// bpmn object
process(
id = "example-invoice-c7-review",
descr = "This starts the Review Invoice Process.",
in = InvoiceReceipt(),
out = InvoiceReviewed()
)
Expand Down Expand Up @@ -748,6 +732,15 @@ It checks if the state of the process is `COMPLETED`.
It simple tries until there is a User Task in the process available.
If there are more than one, it just takes the first one.

To complete a User Task, you can also wait some seconds.
This is useful, if you want to check if intermediate events were triggered.
```scala
scenario(userTaskExampleProcess)(
userTaskExample
.waitForSec(2) // wait 2 seconds
)
```

#### Receive Message Event

We try to correlate the message until it is successful.
Expand Down Expand Up @@ -808,6 +801,8 @@ Mocking is handled directly in the processes itself.
This is especially useful in _Simulations_.

However, you can mock on any environment, like local or production (e.g. with _Postman_).

See also [General Concerns](../generalConcerns.md#mocking).
@:@

### Generic Mocking
Expand Down
3 changes: 3 additions & 0 deletions 00-docs/src/docs/generalConcerns.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ However, it turns out that this is quite helpful:
The mocking is done with General Variables - see also the chapter above.

**The Usage** is described here under [_General Variables_](exampleApi/OpenApi.html)

As **Simulations** use mocking the most, we describe it [there](functionalityDsls/simulation.md#mocking)
in more detail.
@:@

We have four ways to mock. Each possibility is done with a dedicated Process Variable.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ trait SEventExtensions extends SimulationHelper:
else None
val tenant = // only set if there is no processInstanceId
if sEvent.processInstanceId then None
else summon[SimulationConfig[?]].tenantId
else config.tenantId
val body = CorrelateMessageIn(
messageName = event.messageName,
tenantId = tenant,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ trait SScenarioExtensions extends SStepExtensions:
val process = scenario.process
val body = CorrelateMessageIn(
messageName = process.processName,
tenantId = summon[SimulationConfig[?]].tenantId,
tenantId = config.tenantId,
businessKey = Some(scenario.name),
processVariables = Some(process.camundaInMap)
).asJson.deepDropNullValues.toString
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import scala.util.Try
trait SimulationHelper extends ResultChecker, Logging:

// not possible to override given instance
implicit def config: SimulationConfig[RequestT[Empty, Either[String, String], Any]] =
def config: SimulationConfig[RequestT[Empty, Either[String, String], Any]] =
SimulationConfig[RequestT[Empty, Either[String, String], Any]]()

lazy val backend: SttpBackend[Identity, Any] = HttpClientSyncBackend()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import sttp.client3.*
trait BasicSimulationDsl extends CustomSimulation:
def username = "demo"
def password = "demo"
override implicit def config: SimulationConfig[RequestT[Empty, Either[String, String], Any]] =
override def config: SimulationConfig[RequestT[Empty, Either[String, String], Any]] =
super.config
.withAuthHeader((r: RequestT[Empty, Either[String, String], Any]) =>
r.auth.basic(username, password)
Expand All @@ -21,7 +21,7 @@ trait OAuthSimulationDsl extends CustomSimulation:

def fsso: Fsso

override implicit def config: SimulationConfig[RequestT[Empty, Either[String, String], Any]] =
override def config: SimulationConfig[RequestT[Empty, Either[String, String], Any]] =
super.config
.withAuthHeader((r: RequestT[Empty, Either[String, String], Any]) =>
val token = getToken
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ case class CompanyWrapperGenerator()(using config: DevConfig):
| lazy val companyProjectVersion = BuildInfo.version
|
|object CompanyApiCreator:
| lazy val apiConfig = ApiConfig(companyId = "$companyName")
| lazy val apiConfig = ApiConfig(companyName = "$companyName")
|""".stripMargin

private lazy val dmnWrapper =
Expand All @@ -81,8 +81,10 @@ case class CompanyWrapperGenerator()(using config: DevConfig):
| */
|trait CompanySimulation extends BasicSimulationDsl:
|
| override implicit def config =
| override def config =
| super.config //TODO Adjust config if needed
|
|end CompanySimulation
|""".stripMargin

private lazy val workerWrapper =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ class BasicAuthExampleSimulation extends BasicSimulationDsl:
DateExampleDMN
)

override implicit def config =
override def config =
super.config.withPort(8033)
end BasicAuthExampleSimulation
Loading

0 comments on commit 2de4306

Please sign in to comment.