A behaviour module for implementing a load testing scenario to be run via LiveLoad.
A LiveLoad.Scenario runs in a distributed fashion. Nodes are elastically created
via LiveLoad whenever a load test is being performed. On each node, the config/1
callback is called once, to initialize the node's configuration, and a set of user
processes are created and run to simulate the load by calling the scenario's run/3
callback with the current user ID and the config that was created for this node.
use LiveLoad.Scenario
In order for LiveLoad to be able to run your scenario correctly,
you must use LiveLoad.Scenario. This will not only set the behaviour
for LiveLoad, but also set up various functionality related to running
the scenario properly through LiveLoad's internals. LiveLoad's internals
are opaque, and while you can see how they work by browsing the code and
reading the docs, they should not be assumed to be stable. Ensuring that
you are creating scenarios with use LiveLoad.Scenario will make certain
that any scenario you create will be stable and runnable by LiveLoad.
The config/1 callback
When you use LiveLoad.Scenario, the LiveLoad.Scenario module will
define an empty config/1 function for you which will return an empty map.
If you don't need any configurable parts in your scenario, this injected
callback can remain and does not need to be overriden by your scenario module.
Scenario Lifecycle
When a LiveLoad.Scenario is run, the config/1 callback is called once per node, before any
user processes are created. The value returned from config/1 is then passed into the run/3
callback on every iteration of the scenario for every user.
After config/1 returns, LiveLoad creates the configured number of user processes for this node.
Each user process is given its own LiveLoad.Browser.Context and LiveLoad.Scenario.Context, and
the user process enters a loop that calls the scenario's run/3 callback over and over until
the configured :scenario_duration has been reached.
Each iteration of the loop runs run/3 with the current LiveLoad.Scenario.Context and the config
that was returned from config/1. The LiveLoad.Scenario.Context returned from run/3 becomes
the context for the next iteration, allowing values to be carried forward via LiveLoad.Scenario.Context.assign/3.
See LiveLoad.Scenario.Context for more details on how the context is maintained across iterations.
If run/3 returns a context that is halted? or failed?, or if it raises an exception, the
user process will be terminated and no further iterations will run for that user. Any other users
on the node will continue running their own iterations until the :scenario_duration is reached.
Once the :scenario_duration has elapsed, the user processes will finish their current iteration
and then terminate. The scenario is considered complete once all user processes on all nodes have
terminated.
Summary
Types
A config that is created by the config/1 callback on initialization of the LiveLoad.Scenario.
Any module implementing the LiveLoad.Scenario behaviour.
Callbacks
Invoked once per node that LiveLoad is running the load test on.
config/1 will receive any options passed in to LiveLoad.run/1
that have not been consumed yet and can return a config value that
will be passed in to run/3.
Invoked once per user. run/3 is the actual load test that will be run,
measured, and instrumented by LiveLoad.
Types
A config that is created by the config/1 callback on initialization of the LiveLoad.Scenario.
A config can be any term, as it will simply be passed into the run/3 callback and can be handled by the scenario.
@type t() :: module()
Any module implementing the LiveLoad.Scenario behaviour.
The user ID passed to the run/3 callback. It can be either an integer or a binary.
Callbacks
Invoked once per node that LiveLoad is running the load test on.
config/1 will receive any options passed in to LiveLoad.run/1
that have not been consumed yet and can return a config value that
will be passed in to run/3.
config/1 is called synchronously on startup, and if an error is
returned, the entire load test will fail for this scenario.
@callback run( context :: LiveLoad.Scenario.Context.t(), user_id :: user_id(), config :: config() ) :: LiveLoad.Scenario.Context.t() | {:error, term()}
Invoked once per user. run/3 is the actual load test that will be run,
measured, and instrumented by LiveLoad.