Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug(runtime): functions can be registered twice #326

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24,006 changes: 12,003 additions & 12,003 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@
"degit": "^2.8.4",
"eslint": "^8.43.0",
"eslint-plugin-jitar": "0.0.1",
"lerna": "^7.0.2",
"rollup": "^3.25.1",
"lerna": "^7.1.0",
"rollup": "^3.25.3",
"rollup-plugin-dts": "^5.3.0",
"vite": "^4.3.9",
"vitest": "^0.32.2"
Expand Down
30 changes: 29 additions & 1 deletion packages/caching/src/building/SegmentCacheBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

import DuplicateImplementation from './errors/DuplicateImplementation.js';
import Segment from './models/Segment.js';
import SegmentCache from './models/SegmentCache.js';
import SegmentImplementation from './models/SegmentImplementation.js';
Expand All @@ -13,6 +14,8 @@ export default class SegmentCacheBuilder
const imports = this.#createImports(segment);
const procedures = this.#mergeProcedures(segment);

this.#validateProcedures(procedures);

return new SegmentCache(segment.name, files, imports, procedures);
}

Expand Down Expand Up @@ -68,11 +71,36 @@ export default class SegmentCacheBuilder
}

const procedureCopy = new SegmentProcedure(procedure.fqn, [...procedure.implementations]);

procedures.set(procedure.fqn, procedureCopy);
}
}

return [...procedures.values()];
}

#validateProcedures(procedures: SegmentProcedure[]): void
{
for (const procedure of procedures)
{
this.#checkForDuplicateImplementations(procedure);
}
}

#checkForDuplicateImplementations(procedure: SegmentProcedure): void
{
for (const implementation of procedure.implementations)
{
const duplicate = procedure.implementations.find(other =>
{
return other.id !== implementation.id
&& other.version === implementation.version;
});

if (duplicate !== undefined)
{
throw new DuplicateImplementation(procedure.fqn, implementation.version);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

export default class DuplicateImplementation extends Error
{
constructor(fqn: string, version: string)
{
super(`Duplicate implementation found for '${fqn}' with version '${version}'.`);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { SEGMENT_MODULES } from './SegmentModule.fixture';
const SEGMENTS =
{
ORDER: new Segment('order', [SEGMENT_MODULES.CREATE_ORDER, SEGMENT_MODULES.STORE_ORDER]),
PRODUCT: new Segment('product', [SEGMENT_MODULES.GET_PRODUCTS, SEGMENT_MODULES.GET_PRODUCTS_V1])
PRODUCT: new Segment('product', [SEGMENT_MODULES.GET_PRODUCTS, SEGMENT_MODULES.GET_PRODUCTS_V1]),
DUPLICATE: new Segment('duplicate', [SEGMENT_MODULES.DUPLICATE_MODULE])
};

export { SEGMENTS };
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,43 @@ import { SEGMENT_MODULES } from './SegmentModule.fixture';
import { SEGMENT_PROCEDURES } from './SegmentProcedure.fixture';

const ORDER = new SegmentCache
(
'order',
[SEGMENT_MODULES.CREATE_ORDER.filename, SEGMENT_MODULES.STORE_ORDER.filename],
[
new SegmentImport(['default as $1'], SEGMENT_MODULES.CREATE_ORDER.filename),
new SegmentImport(['v0_0_0 as $2', 'v1_0_0 as $3'], SEGMENT_MODULES.STORE_ORDER.filename)
],
[SEGMENT_PROCEDURES.CREATE_ORDER, SEGMENT_PROCEDURES.STORE_ORDER]
);
(
'order',
[SEGMENT_MODULES.CREATE_ORDER.filename, SEGMENT_MODULES.STORE_ORDER.filename],
[
new SegmentImport(['default as $1'], SEGMENT_MODULES.CREATE_ORDER.filename),
new SegmentImport(['v0_0_0 as $2', 'v1_0_0 as $3'], SEGMENT_MODULES.STORE_ORDER.filename)
],
[SEGMENT_PROCEDURES.CREATE_ORDER, SEGMENT_PROCEDURES.STORE_ORDER]
);

const PRODUCT = new SegmentCache
(
'product',
[SEGMENT_MODULES.GET_PRODUCTS.filename],
[
new SegmentImport(['default as $1', 'searchProducts as $2'], SEGMENT_MODULES.GET_PRODUCTS.filename),
new SegmentImport(['default as $3', 'searchProducts as $4'], SEGMENT_MODULES.GET_PRODUCTS_V1.filename)
],
[SEGMENT_PROCEDURES.GET_PRODUCTS_MERGED, SEGMENT_PROCEDURES.SEARCH_PRODUCTS_MERGED]
);
(
'product',
[SEGMENT_MODULES.GET_PRODUCTS.filename],
[
new SegmentImport(['default as $1', 'searchProducts as $2'], SEGMENT_MODULES.GET_PRODUCTS.filename),
new SegmentImport(['default as $3', 'searchProducts as $4'], SEGMENT_MODULES.GET_PRODUCTS_V1.filename)
],
[SEGMENT_PROCEDURES.GET_PRODUCTS_MERGED, SEGMENT_PROCEDURES.SEARCH_PRODUCTS_MERGED]
);

const DUPLICATE = new SegmentCache
(
'duplicate',
[SEGMENT_MODULES.DUPLICATE_MODULE.filename],
[
new SegmentImport(['v0_0_0 as $1', 'v0_0_0 as $2'], SEGMENT_MODULES.DUPLICATE_MODULE.filename),
new SegmentImport(['v1_0_0 as $3', 'v1_0_0 as $4'], SEGMENT_MODULES.DUPLICATE_MODULE.filename)
],
[SEGMENT_PROCEDURES.DUPLICATE_PROCEDURES]
);

const SEGMENT_CACHES =
{
ORDER,
PRODUCT
PRODUCT,
DUPLICATE
};

export { SEGMENT_CACHES };
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ const SEGMENT_IMPLEMENTATIONS =
GET_PRODUCTS: new SegmentImplementation('$1', 'default', 'private', '0.0.0', GET_PRODUCTS),
SEARCH_PRODUCTS: new SegmentImplementation('$2', 'searchProducts', 'public', '0.0.0', SEARCH_PRODUCTS),
GET_PRODUCTS_V1: new SegmentImplementation('$3', 'default', 'private', '1.0.0', GET_PRODUCTS),
SEARCH_PRODUCTS_V1: new SegmentImplementation('$4', 'searchProducts', 'public', '1.0.0', SEARCH_PRODUCTS_V1)
SEARCH_PRODUCTS_V1: new SegmentImplementation('$4', 'searchProducts', 'public', '1.0.0', SEARCH_PRODUCTS_V1),
STORE_ORDER_V0_DUPLICATE: new SegmentImplementation('$1', 'v0_0_0', 'public', '0.0.0', STORE_ORDER_V0),
};

export { SEGMENT_IMPLEMENTATIONS };
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ const SEGMENT_MODULES =
CREATE_ORDER: new SegmentModule('order/createOrder.js', [SEGMENT_PROCEDURES.CREATE_ORDER]),
STORE_ORDER: new SegmentModule('order/storeOrder.js', [SEGMENT_PROCEDURES.STORE_ORDER]),
GET_PRODUCTS: new SegmentModule('product/getProducts.js', [SEGMENT_PROCEDURES.GET_PRODUCTS, SEGMENT_PROCEDURES.SEARCH_PRODUCTS]),
GET_PRODUCTS_V1: new SegmentModule('product/getProducts_v1.js', [SEGMENT_PROCEDURES.GET_PRODUCTS_V1, SEGMENT_PROCEDURES.SEARCH_PRODUCTS_V1])
GET_PRODUCTS_V1: new SegmentModule('product/getProducts_v1.js', [SEGMENT_PROCEDURES.GET_PRODUCTS_V1, SEGMENT_PROCEDURES.SEARCH_PRODUCTS_V1]),
DUPLICATE_MODULE: new SegmentModule('order/storeOrder.js', [SEGMENT_PROCEDURES.DUPLICATE_PROCEDURES])
};

export { SEGMENT_MODULES };
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const SEGMENT_PROCEDURES =
GET_PRODUCTS_MERGED: new SegmentProcedure('product/getProducts', [SEGMENT_IMPLEMENTATIONS.GET_PRODUCTS, SEGMENT_IMPLEMENTATIONS.GET_PRODUCTS_V1]),
SEARCH_PRODUCTS: new SegmentProcedure('product/searchProducts', [SEGMENT_IMPLEMENTATIONS.SEARCH_PRODUCTS]),
SEARCH_PRODUCTS_V1: new SegmentProcedure('product/searchProducts', [SEGMENT_IMPLEMENTATIONS.SEARCH_PRODUCTS_V1]),
SEARCH_PRODUCTS_MERGED: new SegmentProcedure('product/searchProducts', [SEGMENT_IMPLEMENTATIONS.SEARCH_PRODUCTS, SEGMENT_IMPLEMENTATIONS.SEARCH_PRODUCTS_V1])
SEARCH_PRODUCTS_MERGED: new SegmentProcedure('product/searchProducts', [SEGMENT_IMPLEMENTATIONS.SEARCH_PRODUCTS, SEGMENT_IMPLEMENTATIONS.SEARCH_PRODUCTS_V1]),
DUPLICATE_PROCEDURES: new SegmentProcedure('order/storeOrder', [SEGMENT_IMPLEMENTATIONS.STORE_ORDER_V0, SEGMENT_IMPLEMENTATIONS.STORE_ORDER_V0_DUPLICATE])
};

export { SEGMENT_PROCEDURES };
11 changes: 10 additions & 1 deletion packages/caching/test/building/SegmentCacheBuilder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
import { describe, expect, it } from 'vitest';

import SegmentCacheBuilder from '../../src/building/SegmentCacheBuilder';
import DuplicateImplementation from '../../src/building/errors/DuplicateImplementation';

import { INPUT, OUTPUT } from '../_fixtures/building/SegmentCacheBuilder.fixture';
import { SEGMENTS } from '../_fixtures/building/models/Segment.fixture';

const segmentCacheBuilder = new SegmentCacheBuilder();

Expand All @@ -18,7 +20,7 @@ describe('building/SegmentCacheBuilder', () =>

// Check if the files are correctly populated
expect(result.files).toEqual(OUTPUT.files);

// Check if the imports are correctly created
expect(result.imports).toHaveLength(OUTPUT.imports.length);
expect(result.imports[0].members).toEqual(OUTPUT.imports[0].members);
Expand All @@ -31,5 +33,12 @@ describe('building/SegmentCacheBuilder', () =>
expect(result.procedures[0].fqn).toEqual(OUTPUT.procedures[0].fqn);
expect(result.procedures[1].fqn).toEqual(OUTPUT.procedures[1].fqn);
});

it('should throw an error if the procedure contain a duplicate implementation', () =>
{
const run = () => segmentCacheBuilder.build(SEGMENTS.DUPLICATE);

expect(run).toThrowError(new DuplicateImplementation('order/storeOrder', '0.0.0'));
});
});
});
9 changes: 7 additions & 2 deletions packages/server-nodejs/src/JitarServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export default class JitarServer
this.#options = ServerOptionsReader.read();
this.#configuration = RuntimeConfigurationLoader.load(this.#options.config);
this.#logger = LogBuilder.build(this.#options.loglevel);

this.#printStartupMessage();
}

get classLoader(): ClassLoader
Expand All @@ -82,8 +84,6 @@ export default class JitarServer

async start(): Promise<void>
{
console.log(STARTUP_MESSAGE);

const url = new URL(this.#configuration.url ?? RuntimeDefaults.URL);

this.#addHealthChecks();
Expand Down Expand Up @@ -216,4 +216,9 @@ export default class JitarServer
{
return new Promise(resolve => { this.#app.listen(port, resolve); });
}

#printStartupMessage(): void
{
console.log(STARTUP_MESSAGE);
}
}