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.
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 });
When tournamentRecord
is passed as a parameter, a temporary tournamentRecords
object is created and any tournamentRecords
in state are not referenced.