From bb57c853bf1197d85642ee92eb2c5d218a284501 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Wed, 16 Jun 2021 13:12:50 +0300 Subject: [PATCH 1/3] feat: initialization will run only once --- lib/DashPlatformProtocol.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/DashPlatformProtocol.js b/lib/DashPlatformProtocol.js index c3a88379..8d1203fb 100644 --- a/lib/DashPlatformProtocol.js +++ b/lib/DashPlatformProtocol.js @@ -1,3 +1,4 @@ +const EventEmitter = require('events'); const getRE2Class = require('@dashevo/re2-wasm').default; const createAjv = require('./ajv/createAjv'); @@ -9,6 +10,8 @@ const StateTransitionFacade = require('./stateTransition/StateTransitionFacade') const IdentityFacade = require('./identity/IdentityFacade'); +const INITIALIZED_EVENT = 'LOADED'; + /** * @class DashPlatformProtocol */ @@ -22,9 +25,28 @@ class DashPlatformProtocol { this.stateRepository = options.stateRepository; this.jsonSchemaValidator = options.jsonSchemaValidator; + this.initialized = false; + this.isInitializing = false; + this.events = new EventEmitter(); } async initialize() { + if (this.initialized) { + return; + } + + if (this.isInitializing) { + await new Promise((resolve) => { + this.events.once(INITIALIZED_EVENT, () => { + resolve(); + }); + }); + + return; + } + + this.isInitializing = true; + if (this.jsonSchemaValidator === undefined) { const ajv = await createAjv(); @@ -51,6 +73,10 @@ class DashPlatformProtocol { this.identity = new IdentityFacade( this.jsonSchemaValidator, ); + + this.initialized = true; + this.isInitializing = false; + this.events.emit(INITIALIZED_EVENT); } /** From cae5c1b3d7142b03f8e62fbde7a0b1a86b0d21ef Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Wed, 16 Jun 2021 15:28:56 +0300 Subject: [PATCH 2/3] refactor: simplify `initialize` logic --- lib/DashPlatformProtocol.js | 86 +++++++++---------- lib/ajv/createAjv.js | 7 +- lib/ajv/injectRE2.js | 9 +- .../keywords/byteArray/addByteArrayKeyword.js | 2 +- ...ctCreateTransitionStructureFactory.spec.js | 6 +- .../validateDataContractFactory.spec.js | 6 +- ...ntsBatchTransitionStructureFactory.spec.js | 7 +- .../document/validateDocumentFactory.spec.js | 6 +- ...hainAssetLockProofStructureFactory.spec.js | 7 +- ...tantAssetLockProofStructureFactory.spec.js | 7 +- ...tyCreateTransitionStructureFactory.spec.js | 6 +- ...ityTopUpTransitionStructureFactory.spec.js | 6 +- .../validateIdentityFactory.spec.js | 7 +- .../validatePublicKeysFactory.spec.js | 7 +- 14 files changed, 103 insertions(+), 66 deletions(-) diff --git a/lib/DashPlatformProtocol.js b/lib/DashPlatformProtocol.js index 8d1203fb..5297bb80 100644 --- a/lib/DashPlatformProtocol.js +++ b/lib/DashPlatformProtocol.js @@ -1,5 +1,4 @@ -const EventEmitter = require('events'); -const getRE2Class = require('@dashevo/re2-wasm').default; +const { default: getRE2Class } = require('@dashevo/re2-wasm'); const createAjv = require('./ajv/createAjv'); const JsonSchemaValidator = require('./validation/JsonSchemaValidator'); @@ -10,8 +9,6 @@ const StateTransitionFacade = require('./stateTransition/StateTransitionFacade') const IdentityFacade = require('./identity/IdentityFacade'); -const INITIALIZED_EVENT = 'LOADED'; - /** * @class DashPlatformProtocol */ @@ -22,61 +19,58 @@ class DashPlatformProtocol { * @param {JsonSchemaValidator} [options.jsonSchemaValidator] */ constructor(options = {}) { - this.stateRepository = options.stateRepository; + this.options = options; + + this.stateRepository = undefined; + this.jsonSchemaValidator = undefined; - this.jsonSchemaValidator = options.jsonSchemaValidator; this.initialized = false; - this.isInitializing = false; - this.events = new EventEmitter(); } + /** + * Initialize + * + * @return {Promise} + */ async initialize() { if (this.initialized) { - return; + return this.initialized; } - if (this.isInitializing) { - await new Promise((resolve) => { - this.events.once(INITIALIZED_EVENT, () => { - resolve(); - }); - }); + this.initialized = getRE2Class().then((RE2) => { + this.stateRepository = this.options.stateRepository; - return; - } + this.jsonSchemaValidator = this.options.jsonSchemaValidator; + if (this.jsonSchemaValidator === undefined) { + const ajv = createAjv(RE2); - this.isInitializing = true; + this.jsonSchemaValidator = new JsonSchemaValidator(ajv); + } - if (this.jsonSchemaValidator === undefined) { - const ajv = await createAjv(); + this.dataContract = new DataContractFacade( + this.jsonSchemaValidator, + RE2, + ); - this.jsonSchemaValidator = new JsonSchemaValidator(ajv); - } + this.document = new DocumentFacade( + this.stateRepository, + this.jsonSchemaValidator, + ); + + this.stateTransition = new StateTransitionFacade( + this.stateRepository, + this.jsonSchemaValidator, + RE2, + ); + + this.identity = new IdentityFacade( + this.jsonSchemaValidator, + ); + + return true; + }); - const RE2 = await getRE2Class(); - this.dataContract = new DataContractFacade( - this.jsonSchemaValidator, - RE2, - ); - - this.document = new DocumentFacade( - this.stateRepository, - this.jsonSchemaValidator, - ); - - this.stateTransition = new StateTransitionFacade( - this.stateRepository, - this.jsonSchemaValidator, - RE2, - ); - - this.identity = new IdentityFacade( - this.jsonSchemaValidator, - ); - - this.initialized = true; - this.isInitializing = false; - this.events.emit(INITIALIZED_EVENT); + return this.initialized; } /** diff --git a/lib/ajv/createAjv.js b/lib/ajv/createAjv.js index c0c4fd0d..6096530f 100644 --- a/lib/ajv/createAjv.js +++ b/lib/ajv/createAjv.js @@ -7,10 +7,11 @@ const addByteArrayKeyword = require('./keywords/byteArray/addByteArrayKeyword'); const injectRE2 = require('./injectRE2'); /** - * @return {Promise} + * @param {Function} RE2 + * @return {Ajv2020} */ -async function createAjv() { - await injectRE2(); +function createAjv(RE2) { + injectRE2(RE2); const ajv = new Ajv({ strictTypes: true, diff --git a/lib/ajv/injectRE2.js b/lib/ajv/injectRE2.js index 1e2ac498..3454106b 100644 --- a/lib/ajv/injectRE2.js +++ b/lib/ajv/injectRE2.js @@ -1,11 +1,10 @@ -const { default: getRE2Class } = require('@dashevo/re2-wasm'); - const codegen = require('ajv/dist/compile/codegen'); const code = require('ajv/dist/vocabularies/code'); -async function injectRE2() { - const RE2 = await getRE2Class(); - +/** + * @param {Function} RE2 + */ +function injectRE2(RE2) { global.RE2 = RE2; code.usePattern = function usePattern({ gen }, pattern) { diff --git a/lib/ajv/keywords/byteArray/addByteArrayKeyword.js b/lib/ajv/keywords/byteArray/addByteArrayKeyword.js index d109d26a..40f1a7a2 100644 --- a/lib/ajv/keywords/byteArray/addByteArrayKeyword.js +++ b/lib/ajv/keywords/byteArray/addByteArrayKeyword.js @@ -1,7 +1,7 @@ const byteArray = require('./byteArray'); /** - * @param {ajv.Ajv} ajv + * @param {Ajv2020} ajv */ function addByteArrayKeyword(ajv) { ajv.addKeyword(byteArray); diff --git a/test/integration/dataContract/stateTransition/validation/validateDataContractCreateTransitionStructureFactory.spec.js b/test/integration/dataContract/stateTransition/validation/validateDataContractCreateTransitionStructureFactory.spec.js index 05fb3ade..e13c4f72 100644 --- a/test/integration/dataContract/stateTransition/validation/validateDataContractCreateTransitionStructureFactory.spec.js +++ b/test/integration/dataContract/stateTransition/validation/validateDataContractCreateTransitionStructureFactory.spec.js @@ -1,5 +1,7 @@ const crypto = require('crypto'); +const { default: getRE2Class } = require('@dashevo/re2-wasm'); + const createAjv = require('../../../../../lib/ajv/createAjv'); const JsonSchemaValidator = require('../../../../../lib/validation/JsonSchemaValidator'); @@ -56,7 +58,9 @@ describe('validateDataContractCreateTransitionStructureFactory', () => { new ValidationResult(), ); - const ajv = await createAjv(); + const RE2 = await getRE2Class(); + const ajv = createAjv(RE2); + const jsonSchemaValidator = new JsonSchemaValidator(ajv); // eslint-disable-next-line max-len diff --git a/test/integration/dataContract/validateDataContractFactory.spec.js b/test/integration/dataContract/validateDataContractFactory.spec.js index 107517a9..ab33d2c9 100644 --- a/test/integration/dataContract/validateDataContractFactory.spec.js +++ b/test/integration/dataContract/validateDataContractFactory.spec.js @@ -1,4 +1,5 @@ -const getRE2Class = require('@dashevo/re2-wasm').default; +const { default: getRE2Class } = require('@dashevo/re2-wasm'); + const $RefParser = require('@apidevtools/json-schema-ref-parser'); const createAjv = require('../../../lib/ajv/createAjv'); @@ -41,7 +42,8 @@ describe('validateDataContractFactory', function main() { dataContract = getDataContractFixture(); rawDataContract = dataContract.toObject(); - const jsonSchemaValidator = new JsonSchemaValidator(await createAjv()); + const ajv = createAjv(RE2); + const jsonSchemaValidator = new JsonSchemaValidator(ajv); const validateDataContractMaxDepth = validateDataContractMaxDepthFactory($RefParser); diff --git a/test/integration/document/stateTransition/validation/structure/validateDocumentsBatchTransitionStructureFactory.spec.js b/test/integration/document/stateTransition/validation/structure/validateDocumentsBatchTransitionStructureFactory.spec.js index 9c1ce2d4..5c512916 100644 --- a/test/integration/document/stateTransition/validation/structure/validateDocumentsBatchTransitionStructureFactory.spec.js +++ b/test/integration/document/stateTransition/validation/structure/validateDocumentsBatchTransitionStructureFactory.spec.js @@ -1,3 +1,5 @@ +const { default: getRE2Class } = require('@dashevo/re2-wasm'); + const createAjv = require('../../../../../../lib/ajv/createAjv'); const Document = require('../../../../../../lib/document/Document'); @@ -90,7 +92,10 @@ describe('validateDocumentsBatchTransitionStructureFactory', () => { stateRepositoryMock = createStateRepositoryMock(this.sinonSandbox); stateRepositoryMock.fetchDataContract.resolves(dataContract); - validator = new JsonSchemaValidator(await createAjv()); + const RE2 = await getRE2Class(); + const ajv = createAjv(RE2); + + validator = new JsonSchemaValidator(ajv); enrichSpy = this.sinonSandbox.spy(enrichDataContractWithBaseSchema); diff --git a/test/integration/document/validateDocumentFactory.spec.js b/test/integration/document/validateDocumentFactory.spec.js index a9f4847d..f9c1bb08 100644 --- a/test/integration/document/validateDocumentFactory.spec.js +++ b/test/integration/document/validateDocumentFactory.spec.js @@ -1,3 +1,5 @@ +const { default: getRE2Class } = require('@dashevo/re2-wasm'); + const createAjv = require('../../../lib/ajv/createAjv'); const JsonSchemaValidator = require('../../../lib/validation/JsonSchemaValidator'); @@ -31,9 +33,11 @@ describe('validateDocumentFactory', () => { let validator; beforeEach(async function beforeEach() { - const ajv = await createAjv(); + const RE2 = await getRE2Class(); + const ajv = createAjv(RE2); validator = new JsonSchemaValidator(ajv); + this.sinonSandbox.spy(validator, 'validate'); dataContract = getDataContractFixture(); diff --git a/test/integration/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.spec.js b/test/integration/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.spec.js index 445ea962..387048e6 100644 --- a/test/integration/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.spec.js +++ b/test/integration/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.spec.js @@ -1,3 +1,5 @@ +const { default: getRE2Class } = require('@dashevo/re2-wasm'); + const createAjv = require('../../../../../../lib/ajv/createAjv'); const getChainAssetLockFixture = require('../../../../../../lib/test/fixtures/getChainAssetLockProofFixture'); @@ -32,7 +34,10 @@ describe('validateChainAssetLockProofStructureFactory', () => { rawProof = assetLock.toObject(); - jsonSchemaValidator = new JsonSchemaValidator(await createAjv()); + const RE2 = await getRE2Class(); + const ajv = createAjv(RE2); + + jsonSchemaValidator = new JsonSchemaValidator(ajv); stateRepositoryMock = createStateRepositoryMock(this.sinonSandbox); diff --git a/test/integration/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.spec.js b/test/integration/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.spec.js index 690b21d8..d3d0dbc0 100644 --- a/test/integration/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.spec.js +++ b/test/integration/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.spec.js @@ -1,3 +1,5 @@ +const { default: getRE2Class } = require('@dashevo/re2-wasm'); + const rewiremock = require('rewiremock/node'); const { Transaction } = require('@dashevo/dashcore-lib'); @@ -37,7 +39,10 @@ describe('validateInstantAssetLockProofStructureFactory', () => { rawProof = assetLock.toObject(); - jsonSchemaValidator = new JsonSchemaValidator(await createAjv()); + const RE2 = await getRE2Class(); + const ajv = createAjv(RE2); + + jsonSchemaValidator = new JsonSchemaValidator(ajv); stateRepositoryMock = createStateRepositoryMock(this.sinonSandbox); stateRepositoryMock.verifyInstantLock.resolves(true); diff --git a/test/integration/identity/stateTransition/identityCreateTransition/validateIdentityCreateTransitionStructureFactory.spec.js b/test/integration/identity/stateTransition/identityCreateTransition/validateIdentityCreateTransitionStructureFactory.spec.js index a3dbcec8..4b8c6d65 100644 --- a/test/integration/identity/stateTransition/identityCreateTransition/validateIdentityCreateTransitionStructureFactory.spec.js +++ b/test/integration/identity/stateTransition/identityCreateTransition/validateIdentityCreateTransitionStructureFactory.spec.js @@ -1,3 +1,5 @@ +const { default: getRE2Class } = require('@dashevo/re2-wasm'); + const createAjv = require('../../../../../lib/ajv/createAjv'); const JsonSchemaValidator = require('../../../../../lib/validation/JsonSchemaValidator'); @@ -40,7 +42,9 @@ describe('validateIdentityCreateTransitionStructureFactory', () => { validateSignatureAgainstAssetLockPublicKeyMock = this.sinonSandbox.stub() .resolves(new ValidationResult()); - const ajv = await createAjv(); + const RE2 = await getRE2Class(); + const ajv = createAjv(RE2); + const jsonSchemaValidator = new JsonSchemaValidator(ajv); const proofValidationResult = new ValidationResult(); diff --git a/test/integration/identity/stateTransition/identityTopUpTransition/validateIdentityTopUpTransitionStructureFactory.spec.js b/test/integration/identity/stateTransition/identityTopUpTransition/validateIdentityTopUpTransitionStructureFactory.spec.js index fd686c56..fe1e8cd1 100644 --- a/test/integration/identity/stateTransition/identityTopUpTransition/validateIdentityTopUpTransitionStructureFactory.spec.js +++ b/test/integration/identity/stateTransition/identityTopUpTransition/validateIdentityTopUpTransitionStructureFactory.spec.js @@ -1,3 +1,5 @@ +const { default: getRE2Class } = require('@dashevo/re2-wasm'); + const createAjv = require('../../../../../lib/ajv/createAjv'); const JsonSchemaValidator = require('../../../../../lib/validation/JsonSchemaValidator'); @@ -46,7 +48,9 @@ describe('validateIdentityTopUpTransitionStructureFactory', () => { validateSignatureAgainstAssetLockPublicKeyMock = this.sinonSandbox.stub() .resolves(new ValidationResult()); - const ajv = await createAjv(); + const RE2 = await getRE2Class(); + const ajv = createAjv(RE2); + const jsonSchemaValidator = new JsonSchemaValidator(ajv); validateIdentityTopUpTransitionStructure = validateIdentityTopUpTransitionStructureFactory( diff --git a/test/integration/identity/validation/validateIdentityFactory.spec.js b/test/integration/identity/validation/validateIdentityFactory.spec.js index d39f5c2b..7ac4940b 100644 --- a/test/integration/identity/validation/validateIdentityFactory.spec.js +++ b/test/integration/identity/validation/validateIdentityFactory.spec.js @@ -1,3 +1,5 @@ +const { default: getRE2Class } = require('@dashevo/re2-wasm'); + const createAjv = require('../../../../lib/ajv/createAjv'); const getIdentityFixture = require('../../../../lib/test/fixtures/getIdentityFixture'); @@ -27,7 +29,10 @@ describe('validateIdentityFactory', () => { let validatePublicKeysMock; beforeEach(async function beforeEach() { - const schemaValidator = new JsonSchemaValidator(await createAjv()); + const RE2 = await getRE2Class(); + const ajv = createAjv(RE2); + + const schemaValidator = new JsonSchemaValidator(ajv); validatePublicKeysMock = this.sinonSandbox.stub().returns(new ValidationResult()); diff --git a/test/integration/identity/validation/validatePublicKeysFactory.spec.js b/test/integration/identity/validation/validatePublicKeysFactory.spec.js index e284efe2..cccd4d23 100644 --- a/test/integration/identity/validation/validatePublicKeysFactory.spec.js +++ b/test/integration/identity/validation/validatePublicKeysFactory.spec.js @@ -1,3 +1,5 @@ +const { default: getRE2Class } = require('@dashevo/re2-wasm'); + const createAjv = require('../../../../lib/ajv/createAjv'); const JsonSchemaValidator = require( @@ -33,7 +35,10 @@ describe('validatePublicKeysFactory', () => { beforeEach(async () => { ({ publicKeys: rawPublicKeys } = getIdentityFixture().toObject()); - const validator = new JsonSchemaValidator(await createAjv()); + const RE2 = await getRE2Class(); + const ajv = createAjv(RE2); + + const validator = new JsonSchemaValidator(ajv); validatePublicKeys = validatePublicKeysFactory( validator, From ebc50d8b76c6cc77bcfa7490379f1482ae2a5396 Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Wed, 16 Jun 2021 15:31:18 +0300 Subject: [PATCH 3/3] refactor: simplify `initialize` logic --- lib/DashPlatformProtocol.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/DashPlatformProtocol.js b/lib/DashPlatformProtocol.js index 5297bb80..1a509c02 100644 --- a/lib/DashPlatformProtocol.js +++ b/lib/DashPlatformProtocol.js @@ -23,8 +23,7 @@ class DashPlatformProtocol { this.stateRepository = undefined; this.jsonSchemaValidator = undefined; - - this.initialized = false; + this.initialized = undefined; } /**