ServerStateManager

ServerStateManager

The StateManager allows to create new SharedStates, or attach to SharedStates created by other nodes (clients or server). It can also track all the SharedStates created by other nodes.

An instance of StateManager is automatically created by the soundworks.Server at initialization (cf. Server#stateManager).

Compared to the ClientStateManager, the ServerStateManager can also define and delete shared state classes, as well as register hooks executed at lifecycle phases of a shared state

See Server#stateManager

Tutorial: https://soundworks.dev/guide/state-manager.html

// server-side
import { Server } from '@soundworks/server/index.js';

const server = new Server(config);
// declare and register the class of a shared state.
server.stateManager.defineClass('some-global-state', {
  myRandom: {
    type: 'float',
    default: 0,
  }
});

await server.start();

// create a global state server-side
const globalState = await server.stateManager.create('some-global-state');
// listen and react to the changes made by the clients
globalState.onUpdate(updates => console.log(updates));
// client-side
import { Client } from '@soundworks/client.index.js';

const client = new Client(config);
await client.start();

// attach to the global state created by the server
const globalState = await client.stateManager.attach('some-global-state');

// update the value of a `myRandom` parameter every seconds
setInterval(() => {
  globalState.set({ myRandom: Math.random() });
}, 1000);

Extends

Methods

(async) attach(className, stateIdOrFilteropt, filteropt) → {Promise.<SharedState>}

Description:
  • Attach to an existing SharedState instance.

    Alternative signatures:

    • stateManager.attach(className)
    • stateManager.attach(className, stateId)
    • stateManager.attach(className, filter)
    • stateManager.attach(className, stateId, filter)
Source:
Overrides:
Example
const state = await client.stateManager.attach('my-class');
Parameters:
Name Type Attributes Default Description
className SharedStateClassName

Name of the class.

stateIdOrFilter number | Array.<string> <optional>
null

Id of the state to attach to. If null, attach to the first state found with the given class name (useful for globally shared states owned by the server).

filter Array.<string> <optional>
null

List of parameters of interest in the returned state. If set to null, no filter is applied.

Returns:
Type
Promise.<SharedState>

(async) create(className, initValuesopt) → {Promise.<SharedState>}

Description:
Source:
Overrides:
Example
const state = await client.stateManager.create('my-class');
Parameters:
Name Type Attributes Default Description
className SharedStateClassName

Name of the class.

initValues Object.<string, any> <optional>
{}

Default values of the created shared state.

Returns:
Type
Promise.<SharedState>

defineClass(className, classDescription)

Description:
  • Define a generic class from which SharedStates can be created.

Source:
See:
Example
server.stateManager.defineClass('my-class', {
  myBoolean: {
    type: 'boolean'
    default: false,
  },
  myFloat: {
    type: 'float'
    default: 0.1,
    min: -1,
    max: 1
  }
});
Parameters:
Name Type Description
className SharedStateClassName

Name of the class.

classDescription SharedStateClassDescription

Description of the class.

deleteClass(className)

Description:
  • Delete a whole class of SharedState.

    All SharedState instances created from this class will be deleted as well, triggering their eventual onDetach and onDelete callbacks.

Source:
Parameters:
Name Type Description
className SharedStateClassName

Name of the shared state class to delete.

deleteSchema()

Source:
Deprecated:

(async) getClassDescription(className) → {SharedStateClassDescription}

Description:
  • Return a class description from a given class name

Source:
Overrides:
Example
const classDescription = await client.stateManager.getClassDescription('my-class');
Parameters:
Name Type Description
className SharedStateClassName

Name of the shared state class. (cf. ServerStateManager)

Returns:
Type
SharedStateClassDescription

(async) getCollection(className, filteropt, optionsopt) → {Promise.<SharedStateCollection>}

Description:
  • Returns a collection of all the states created from a given shared state class.

    Alternative signatures:

    • stateManager.getCollection(className)
    • stateManager.getCollection(className, filter)
    • stateManager.getCollection(className, options)
    • stateManager.getCollection(className, filter, options)
Source:
Overrides:
Example
const collection = await client.stateManager.getCollection(className);
Parameters:
Name Type Attributes Default Description
className SharedStateClassName

Name of the shared state class.

filter array | null <optional>
null

Filter parameter of interest for each state of the collection. If set to null, no filter applied.

options object <optional>
{}

Options.

Properties
Name Type Attributes Default Description
excludeLocal boolean <optional>
false

If set to true, exclude states created by the same node from the collection.

Returns:
Type
Promise.<SharedStateCollection>

(async) getSchema()

Source:
Overrides:
Deprecated:

(async) observe(classNameopt, callback, options) → {Promise.<stateManagerDeleteObserveCallback>}

Description:
  • Observe all the SharedState instances that are created on the network.

    Notes:

    • The order of execution is not guaranteed between nodes, i.e. a state attached in the observe callback can be instantiated before the async create method resolves on the creator node.
    • Filtering, i.e. observedClassName and options.excludeLocal are handled on the node side, the server just notify all state creation activity and the node executes the given callbacks according to the different filter rules. Such strategy allows to simply share the observe notifications between all observers.

    Alternative signatures:

    • stateManager.observe(callback)
    • stateManager.observe(className, callback)
    • stateManager.observe(callback, options)
    • stateManager.observe(className, callback, options)
Source:
Overrides:
Example
client.stateManager.observe(async (className, stateId) => {
  if (className === 'my-shared-state-class') {
    const attached = await client.stateManager.attach(className, stateId);
  }
});
Parameters:
Name Type Attributes Description
className SharedStateClassName <optional>

Optional class name to filter the observed states.

callback stateManagerObserveCallback

Function to be called when a new state is created on the network.

options object

Options.

Properties
Name Type Attributes Default Description
excludeLocal boolean <optional>
false

If set to true, exclude states created locally, i.e. by the same node, from the collection.

Returns:
  • Returns a Promise that resolves when the given callback as been executed on each existing states. The promise value is a function which allows to stop observing the states on the network.
Type
Promise.<stateManagerDeleteObserveCallback>

registerCreateHook(className, createHook) → {function}

Description:
  • Register a function for a given class of shared state class to be executed when a state is created.

    For example, this can be useful to retrieve some initialization values stored in the filesystem, given the value (e.g. a hostname) of one the parameters.

    The hook is associated to each states created from the given class name. Note that the hooks are executed server-side regardless the node on which create has been called.

    Multiple hook can be added to the same className, they will be executed in order of registration.

Source:
Example
server.stateManager.defineClass('hooked', {
  name: { type: 'string', required: true },
  hookTriggered: { type: 'boolean', default: false },
});
server.stateManager.registerCreateHook('hooked', initValues => {
  return {
    ...initValues
    hookTriggered: true,
  };
});

const state = await server.stateManager.create('hooked', {
  name: 'coucou',
});

const values = state.getValues();
assert.deepEqual(result, { value: 'coucou', hookTriggered: true });
Parameters:
Name Type Description
className string

Kind of states on which applying the hook.

createHook serverStateManagerUpdateHook

Function called on when a state of className is created on the network.

Returns:

deleteHook - Handler that deletes the hook when executed.

Type
function

registerDeleteHook(className, createHook) → {function}

Description:
  • Register a function for a given class of shared state class to be executed when a state is deleted.

    For example, this can be useful to store the values of a given shared state in the filesystem.

    The hook is associated to each states created from the given class name. Note that the hooks are executed server-side regardless the node on which delete has been called.

    Multiple hook can be added to the same className, they will be executed in order of registration.

Source:
Example
server.stateManager.defineClass('hooked', {
  name: { type: 'string', required: true },
  hookTriggered: { type: 'boolean', default: false },
});
server.stateManager.registerDeleteHook('hooked', async currentValues => {
  await doSomethingWithValues(currentValues)
});

const state = await server.stateManager.create('hooked');
// later
await state.delete();
Parameters:
Name Type Description
className string

Kind of states on which applying the hook.

createHook serverStateManagerUpdateHook

Function called on when a state of className is created on the network.

Returns:

deleteHook - Handler that deletes the hook when executed.

Type
function

registerSchema()

Source:
Deprecated:

registerUpdateHook(className, updateHook) → {function}

Description:
  • Register a function for a given class of shared state to be executed between set instructions and onUpdate callback(s).

    For example, this can be used to implement a preset system where all the values of the state are updated from e.g. some data stored in filesystem while the consumer of the state only want to update the preset name.

    The hook is associated to each states created from the given class name and executed on each update (i.e. state.set(updates)). Note that the hooks are executed server-side regardless the node on which set has been called and before the call of the onUpdate callback of the shared state.

    Multiple hook can be added to the same className, they will be executed in order of registration.

Source:
Example
server.stateManager.defineClass('hooked', {
  value: { type: 'string', default: null, nullable: true },
  numUpdates: { type: 'integer', default: 0 },
});
server.stateManager.registerUpdateHook('hooked', updates => {
  return {
    ...updates
    numUpdates: currentValues.numUpdates + 1,
  };
});

const state = await server.stateManager.create('hooked');

await state.set({ value: 'test' });
const values = state.getValues();
assert.deepEqual(result, { value: 'test', numUpdates: 1 });
Parameters:
Name Type Description
className string

Kind of states on which applying the hook.

updateHook serverStateManagerUpdateHook

Function called on each update, to eventually modify the updates before they are actually applied.

Returns:

deleteHook - Handler that deletes the hook when executed.

Type
function