Skip to content

Commit

Permalink
feat(state-collection): [breaking-change] exclude states from same no…
Browse files Browse the repository at this point in the history
…de only if excludeLocal is true
  • Loading branch information
b-ma committed Dec 13, 2023
1 parent 5e9517d commit d0d255e
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 26 deletions.
7 changes: 5 additions & 2 deletions src/client/SharedStateCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ import BaseSharedStateCollection from '../common/BaseSharedStateCollection.js';

/**
* The `SharedStateCollection` interface represent a collection of all states
* created from a given schema name on the network, at the execption of the ones
* created by the current node.
* created from a given schema name on the network.
*
* It can optionnaly exclude the states created by the current node.
*
* See {@link client.StateManager#getCollection} for factory method API
*
* ```
* const collection = await client.stateManager.getCollection('my-schema');
Expand Down
11 changes: 5 additions & 6 deletions src/common/BaseSharedStateCollection.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
/**
* @private
*/
let id = 0;

class BaseSharedStateCollection {
constructor(stateManager, schemaName) {
constructor(stateManager, schemaName, options = {}) {
this._stateManager = stateManager;
this._schemaName = schemaName;
this._options = Object.assign({ excludeLocal: false }, options);

this._states = [];

this._onUpdateCallbacks = new Set();
this._onAttachCallbacks = new Set();
this._onDetachCallbacks = new Set();
this._unobserve = null;
// testing
this._id = id++;
}

async _init() {
Expand All @@ -36,7 +35,7 @@ class BaseSharedStateCollection {
});

this._onAttachCallbacks.forEach(callback => callback(state));
});
}, this._options);
}

/**
Expand Down
35 changes: 20 additions & 15 deletions src/common/BaseStateManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,24 +212,26 @@ class BaseStateManager {
* control over them from a single point.
*
* Notes:
* - The states that are created by the same node are not propagated through
* the observe callback.
* - The order of execution is not guaranted between nodes, i.e. an state attached
* in the `observe` callback could be created before the `async create` method resolves.
* - Filtering, i.e. `observedSchemaName` and `options.excludeLocal` are handled
* on the client-side, the server just notify of all state creation activity and
* the client executes the given callbacks according to the different filter rules.
* Such strategy allows to share the obersve notifications between all observers.
* 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 share the observe notifications between all observers.
*
* - observe(callback)
* - observe(schemaName, callback)
* - observe(callback, options)
* - observe(schemaName, callback, options)
* Alternative signatures:
* - .observe(callback)
* - .observe(schemaName, callback)
* - .observe(callback, options)
* - .observe(schemaName, callback, options)
*
* @param {String} [schemaName] - optionnal schema name to filter the observed
* @param {string} [schemaName] - optionnal schema name to filter the observed
* states.
* @param {server.StateManager~ObserveCallback|client.StateManager~ObserveCallback}
* callback - Function to be called when a new state is created on the network.
* @param {object} options - Options.
* @param {boolean} [options.excludeLocal = false] - If set to true, exclude states
* created locallly, i.e. by the same node, from the collection.
* @returns {Promise<Function>} - 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.
Expand Down Expand Up @@ -350,21 +352,24 @@ class BaseStateManager {
}

/**
* Returns a collection of all the states created from the schema name. Except
* the ones created by the current node.
* Returns a collection of all the states created from the schema name.
*
* @param {string} schemaName - Name of the schema.
* @param {object} options - Options.
* @param {boolean} [options.excludeLocal = false] - If set to true, exclude states
* created locallly, i.e. by the same node, from the collection.
* @returns {server.SharedStateCollection|client.SharedStateCollection}
*/
async getCollection(schemaName) {
const collection = new SharedStateCollection(this, schemaName);
async getCollection(schemaName, options) {
const collection = new SharedStateCollection(this, schemaName, options);

try {
await collection._init();
return collection;
} catch(err) {
throw new Error(`Cannot create collection, schema "${schemaName}" does not exists`);
}

return collection;
}
}

Expand Down
7 changes: 5 additions & 2 deletions src/server/SharedStateCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ import BaseSharedStateCollection from '../common/BaseSharedStateCollection.js';

/**
* The `SharedStateCollection` interface represent a collection of all states
* created from a given schema name on the network, at the execption of the ones
* created by the current node.
* created from a given schema name on the network.
*
* It can optionnaly exclude the states created by the current node.
*
* See {@link server.StateManager#getCollection} for factory method API
*
* ```
* const collection = await server.stateManager.getCollection('my-schema');
Expand Down
12 changes: 11 additions & 1 deletion tests/states/StateCollection.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,20 @@ describe(`# SharedStateCollection`, () => {
assert.isTrue(collection1 === collection2);
});

it.skip(`[FIXME #69] should not behave like this by default`, async () => {
it(`should not exclude locally created states by default`, async () => {
const state = await clients[0].stateManager.create('a');
const collection = await clients[0].stateManager.getCollection('a');

assert.equal(collection.length, 1);

await state.delete();
await delay(50);
});

it(`should exclude locally created states is excludeLocal is set to true`, async () => {
const state = await clients[0].stateManager.create('a');
const collection = await clients[0].stateManager.getCollection('a', { excludeLocal: true });

assert.equal(collection.length, 0);

await state.delete();
Expand Down

0 comments on commit d0d255e

Please sign in to comment.