Skip to main content

State Engines

Competition Factory engines share a state which contains one or more tournamentRecords and any factory functions which have been imported from Governors.

All factory engines provide logging and middleware services which resolve parameters such as events and drawDefinitions from identifiers. Mutation engines provide subscription/notification functionality.

  • askEngine: used to synchronously query tournamentRecords held in state.
  • syncEngine: used to synchronously mutate tournamentRecords held in state.
  • asyncEngine: used to asynchronously mutate tournamentRecords held in state.
note

All engine methods which make a mutation return either { success: true } or { error }

Engine state

By default, a "deep copy" of tournamentRecords is made as they are loaded into shared state.

  • engine.setState(tournamentRecord)
  • engine.setState(tournamentRecords)

This behavior can be overridden such that engines operate directly on loaded tournamentRecords.

  • engine.setState(tournamentRecord, deepCopyOptions)

deepCopyOptions can be either a boolean or an object which configures the behavior of the deep copy.

Invoking Factory Functions

All state engines can be used to invoke factory functions in multiple ways:

  • execute: invoke a factory function directly, parameters passed into execute method
  • import and execute: invoke an imported function as an engine attribute
  • import and execute by name: invoke an imported function by reference

Mutation engines can submit a queue of functions to be executed in sequence.

  • executionQueue: invoke an imported function as part of a queue of functions

Examples

For each of the following examples askEngine and the getParticipants method are first imported from the factory.

import { askEngine, participantGovernor: { getParticipants } } from 'tods-competition-factory';

// load a tournamentRecord into state
askEngine.setState(tournamentRecord);

Execute

Function is invoked directly, parameters passed into execute method.

const { participants } = askEngine.execute({ getParticipants, ...params });

Import and Execute

Function is imported and invoked as an engine attribute.

askEngine.importMethods({ getParticipants });
const { participants } = askEngine.getParticipants({ withIndividualParticipants: true });

Import and Execute by Name

Function is imported and invoked by reference.

askEngine.importMethods({ getParticipants });
const { participants } = askEngine.execute({
params: { participantFilters: { participantTypes: [PAIR] } },
method: 'getParticipants',
});

Execution Queue

The executionQueue method accepts an array of imported governor methods and associated parameters, allowing for multiple queries or mutations in a single API call, which is significant if a client is making a request of a server and the server needs to prepare context by loading a tournament record.

An additional benefit of the executionQueue is that subscribers to engine events are not notified until all methods in the queue have completed successfully, and a failure of any one method can be used to roll back state with the assurance that there are no side-effects caused by subscribers responding to notifications. This also means that the server context can not be blocked by any long-running external processes.

syncEngine.importMethods({ getParticipants });
const result = syncEngine.executionQueue([
{ method: 'getParticipants', params: { participantFilters: { participantTypes: [INDIVIDUAL] } } },
]);
const { participants } = result[0];

devContext

devConext is a property of engine state which is used to store any data which is useful for development purposes.

  • The devContext value can be either a boolean or an object.
  • When there is a devContext value present, the try {} catch {} block is NOT used in method invocation.
  • When devContext is an object it is used to configure engine logging.
askEngine.devContext(true); // default
askEngine.devContext(false); // do not catch internal errors

Bypassing State

Passing tournamentRecord as a parameter to any engine method will operate directly on the passed tournamentRecord.

askEngine.getParticipants({ tournamentRecord });
info

When tournamentRecord is passed as a parameter, a temporary tournamentRecords object is created and any tournamentRecords in state are not referenced.