forio Toggle navigation

Run Manager Strategies

The Run Manager gives you control over run creation, depending on run state. You can select run creation strategies (rules) for which runs end users of your project work with when they log in to your project.

There are several strategies included in Epicenter.js:

You can also create your own strategy and see more details on working with Run Strategies.

reuse-per-session

The reuse-per-session strategy creates a new run when the current one is not in the browser cookie.

Using this strategy means that when end users navigate between pages in your project, or refresh their browsers, they will still be working with the same run. However, if end users log out and return to the project at a later date, a new run is created.

This strategy is useful if your project is structured such that immediately after a run is created, the model is executed completely (for example, a Vensim model that is stepped to the end as soon as it is created). In contrast, if end users play with your project for an extended period of time, executing the model step by step, the reuse-across-sessions strategy is probably a better choice (it allows end users to pick up where they left off, rather than starting from scratch each browser session).

Specifically, the strategy is:

  • Check the sessionKey cookie.
    • This cookie is set by the Run Manager and configurable through its options.
    • If the cookie exists, use the run id stored there.
    • If the cookie does not exist, create a new run for this end user.

reuse-across-sessions

The reuse-across-sessions strategy returns the latest (most recent) run for this user, whether it is in memory or not. If there are no runs for this user, it creates a new one.

This strategy is useful if end users are using your project for an extended period of time, possibly over several sessions. This is most common in cases where a user of your project executes the model step by step (as opposed to a project where the model is executed completely, for example, a Vensim model that is immediately stepped to the end).

Specifically, the strategy is:

  • Check if there are any runs for this end user.
    • If there are no runs (either in memory or in the database), create a new one.
    • If there are runs, take the latest (most recent) one.
Strategy Options
Required? Name Type Description
  options object strategy options
  options.filter object ] Additional filters to retreive a run (e.g { saved: true }) etc

reuse-by-tracking-key

The reuse-by-tracking-key strategy creates or returns the most recent run matching a given tracking key. You can optionally also provide a "Run limit", and it'll prevent new runs from being created with this strategy once that limit has been reached.

This strategy is used by the Settings Manager to apply class settings for turn-by-turn simulations, but can also be used stand-alone.

Strategy Options
Required? Name Type Description
Yes settings `object / function(): object function(): Promise.`
Yes settings.trackingKey string Key to track runs with
  settings.runLimit string Attempts to create new runs once limit is reach will return a RUN_LIMIT_REACHED error
  onCreate function(RunService, object): any Callback will be called each time a new run is created

reuse-last-initialized

The reuse-last-initialized strategy looks for the most recent run that matches particular criteria; if it cannot find one, it creates a new run and immediately executes a set of "initialization" operations.

This strategy is useful if you have a time-based model and always want the run you're operating on to start at a particular step. For example:

 const rm = new F.manager.RunManager({
     strategy: 'reuse-last-initialized',
     strategyOptions: {
         initOperation: [{ step: 10 }]
     }
 });

This strategy is also useful if you have a custom initialization function in your model, and want to make sure it's always executed for new runs.

Specifically, the strategy is:

  • Look for the most recent run that matches the (optional) flag criteria
  • If there are no runs that match the flag criteria, create a new run. Immediately "initialize" this new run by:
    • Calling the model operation(s) specified in the initOperation array.
    • Optionally, setting a flag in the run.
Strategy Options
Required? Name Type Description
  options.initOperation Array.<object> Operations to execute in the model for initialization to be considered complete. Can be in any of the formats Run Service's serial() supports.
  options.flag object Flag to set in run after initialization operations are run. You typically would not override this unless you needed to set additional properties as well.
  options.scope object
  options.scope.scopeByUser boolean If true, only returns the last run for the user in session. Defaults to true.
  options.scope.scopeByGroup boolean If true, only returns the last run for the group in session. Defaults to true.

multiplayer-strategy

The multiplayer strategy is for use with multiplayer worlds. It checks the current world for this end user, and always returns the current run for that world. This is equivalent to calling getCurrentWorldForUser() and then getCurrentRunId() from the World API Adapater. If you use the World Manager, you are automatically using this strategy.

Using this strategy means that end users in projects with multiplayer worlds always see the most current world and run. This ensures that they are in sync with the other end users sharing their world and run. In turn, this allows for competitive or collaborative multiplayer projects.

use-specific-run-strategy

Use this strategy you already have a runid you want to use with the Run Manager (Usually used for impersonating a run)

Example:

        var runOptions = window.location.search.indexOf('impersonate') === -1 ? 'reuse-across-sessions': {
            strategy: 'use-specific-run',
            strategyOptions: {
                runId: 'runidToImpersonate' //usually passed on in the url
            }
        }
        var rs = new F.Manager.Run(runOptions);
Strategy Options
Required? Name Type Description
  options.runId string Id of Run to use

none-strategy

The none strategy never returns a run or tries to create a new run. It simply returns the contents of the current Run Service instance.

This strategy is useful if you want to manually decide how to create your own runs and don't want any automatic assistance.

Create your Own

You can create your own strategy by passing in a function as the strategy parameter to the F.manager.RunManager() instantiation call. Strategy functions must return objects of the form:

{
    getRun: function() {},
    reset: function() {}
}

Some strategies have options you can specify through strategyOptions in the Run Manager. If you create your own strategy, this options object is passed in to your strategy function constructor.

For example:

// example create-your-own strategy provides a new run every minute
var ConditionalStrategy = F.manager.RunManager.strategies.byName('conditional-creation');
var myNewStrategy = new ConditionalStrategy(function (run, headers, usersession, runsession) { 
    var created = (new Date(run.created)).valueOf();
    var timeAgo = Date.now() - created;
    var runLifetime = 1;
    var minsAgo = timeAgo / (1000 * 60);
    return minsAgo > runLifetime;
});

var rm = new F.manager.RunManager({
    strategy: myNewStrategy,
    run: { ... }
});

Working with Run Strategies

You can access a list of available strategies using F.manager.RunManager.strategies.list. You can also ask for a particular strategy by name.

If you decide to create your own run strategy, you can register your strategy. Registering your strategy means that:

  • You can pass the strategy by name to a Run Manager (as opposed to passing the strategy function): new F.manager.RunManager({ strategy: 'mynewname'}).
  • You can pass configuration options to your strategy.
  • You can specify whether or not your strategy requires authorization (a valid user session) to work.

Constructor options

Required? Name Type Description
Yes strategyName String Name of strategy to get.

Methods

byName(strategyName)

Gets strategy by name.

Parameters

Required? Name Type Description
Yes strategyName String Name of strategy to get.

Returns

Function - Strategy function.

Example

var reuseStrat = F.manager.RunManager.strategies.byName('reuse-across-sessions');
     // shows strategy function
     console.log('reuseStrat = ', reuseStrat);
     // create a new run manager using this strategy
     var rm = new F.manager.RunManager({strategy: reuseStrat, run: { model: 'model.vmf'} });

register(name, strategy, options)

Adds a new strategy.

Parameters

Required? Name Type Description
Yes name String Name for strategy. This string can then be passed to a Run Manager as new F.manager.RunManager({ strategy: 'mynewname'}).
Yes strategy Function The strategy constructor. Will be called with new on Run Manager initialization.
Yes options Object Options for strategy.
Yes options.requiresAuth Boolean Specify if the strategy requires a valid user session to work.

Example

// this "favorite run" strategy always returns the same run, no matter what
// (not a useful strategy, except as an example)
F.manager.RunManager.strategies.register('favRun', function() { 
 return { 
     getRun: function() { return '0000015a4cd1700209cd0a7d207f44bac289'; },
     reset: function() { return '0000015a4cd1700209cd0a7d207f44bac289'; } 
 }}, { requiresAuth: true });
var rm = new F.manager.RunManager({strategy: 'favRun', run: { model: 'model.vmf'} });