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

API-668 Document and Validate Properties #1001

Merged
merged 17 commits into from
Aug 17, 2021
Merged
61 changes: 33 additions & 28 deletions DOCUMENTATION.md

Large diffs are not rendered by default.

41 changes: 29 additions & 12 deletions scripts/test-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,22 @@ const startRC = async () => {
throw `Could not reach to Hazelcast Remote Controller (127.0.0.1:9701) after trying ${retryCount} times.`;
};

const shutdownProcesses = () => {
console.log('Stopping remote controller and test processes...');
shutdownRC();
const shutdown = async () => {
if (testProcess && testProcess.exitCode === null) {
stopTestProcess();
}

if (rcProcess && rcProcess.exitCode === null) {
await stopRC();
}

if (testProcess && testProcess.exitCode !== null) {
process.exit(testProcess.exitCode);
}
};

const stopTestProcess = () => {
console.log('Stopping test process');
if (ON_WINDOWS) {
spawnSync('taskkill', ['/pid', testProcess.pid, '/f', '/t']); // simple sigkill not enough on windows
} else {
Expand All @@ -139,7 +152,8 @@ const shutdownProcesses = () => {
}
};

const shutdownRC = async () => {
const stopRC = async () => {
console.log('Stopping cluster and remote controller');
if (cluster) {
const RC = getRC();
await RC.terminateCluster(cluster.id);
Expand Down Expand Up @@ -205,11 +219,11 @@ if (!fs.existsSync('./lib')) {
// If running unit test, no need to start rc.
if (testType === 'unit') {
console.log(`Running unit tests... Test command: ${testCommand}`);
spawnSync(testCommand, [], {
const subprocess = spawnSync(testCommand, [], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
process.exit(0);
process.exit(subprocess.status);
}

// For other tests, download rc files if needed.
Expand All @@ -220,9 +234,9 @@ try {
throw err;
}

process.on('SIGINT', shutdownProcesses);
process.on('SIGTERM', shutdownProcesses);
process.on('SIGHUP', shutdownProcesses);
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
process.on('SIGHUP', shutdown);

startRC().then(async () => {
console.log('Hazelcast Remote Controller is started!');
Expand All @@ -232,17 +246,20 @@ startRC().then(async () => {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
testProcess.on('exit', shutdownRC);
testProcess.on('exit', shutdown);
} else if (testType === 'check-code-samples') {
const RC = getRC();
cluster = await RC.createClusterKeepClusterName(null, DEV_CLUSTER_CONFIG);
let exitCode = 0;
try {
await codeSampleChecker.main(cluster);
} catch (e) {
console.error(e);
process.exit(1);
exitCode = 1;
} finally {
await shutdownRC();
await shutdown();
// testProcess is undefined `shutdown` won't exit the process, so we exit with non-zero error code
process.exit(exitCode);
}
}
}).catch(err => {
Expand Down
8 changes: 4 additions & 4 deletions src/config/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ export interface ClientConfig {

}

/** @internal */
/**
* If you are adding a new property, don't forget to add its validation in `handleProperties`.
* @internal
*/
const DEFAULT_PROPERTIES: Properties = {
'hazelcast.client.heartbeat.interval': 5000,
'hazelcast.client.heartbeat.timeout': 60000,
Expand All @@ -179,9 +182,6 @@ const DEFAULT_PROPERTIES: Properties = {
'hazelcast.discovery.public.ip.enabled': null,
};

/** @internal */
export const PROPERTY_SET = new Set(Object.keys(DEFAULT_PROPERTIES));

/** @internal */
export class ClientConfigImpl implements ClientConfig {
properties: Properties = {...DEFAULT_PROPERTIES}; // Create a new object
Expand Down
75 changes: 71 additions & 4 deletions src/config/ConfigBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
tryGetNumber,
tryGetString
} from '../util/Util';
import {ClientConfig, ClientConfigImpl, PROPERTY_SET} from './Config';
import {ClientConfig, ClientConfigImpl} from './Config';
import {EvictionPolicy} from './EvictionPolicy';
import {FlakeIdGeneratorConfigImpl} from './FlakeIdGeneratorConfig';
import {InMemoryFormat} from './InMemoryFormat';
Expand All @@ -35,6 +35,7 @@ import {ReliableTopicConfigImpl} from './ReliableTopicConfig';
import {JsonStringDeserializationPolicy} from './JsonStringDeserializationPolicy';
import {ReconnectMode} from './ConnectionStrategyConfig';
import {LoadBalancerType} from './LoadBalancerConfig';
import {LogLevel} from '../logging';

/**
* Responsible for user-defined config validation. Builds the effective config with necessary defaults.
Expand Down Expand Up @@ -223,10 +224,76 @@ export class ConfigBuilder {

private handleProperties(jsonObject: any): void {
for (const key in jsonObject) {
if (!PROPERTY_SET.has(key)) {
throw new RangeError(`Unexpected property '${key}' is passed to the Hazelcast Client`);
let value = jsonObject[key];
try {
switch (key) {
case 'hazelcast.client.heartbeat.interval':
value = tryGetNumber(value);
break;
case 'hazelcast.client.heartbeat.timeout':
value = tryGetNumber(value);
break;
case 'hazelcast.client.invocation.retry.pause.millis':
value = tryGetNumber(value);
break;
case 'hazelcast.client.invocation.timeout.millis':
value = tryGetNumber(value);
break;
case 'hazelcast.client.internal.clean.resources.millis':
value = tryGetNumber(value);
break;
case 'hazelcast.client.cloud.url':
value = tryGetString(value);
break;
case 'hazelcast.client.statistics.enabled':
value = tryGetBoolean(value);
break;
case 'hazelcast.client.statistics.period.seconds':
value = tryGetNumber(value);
break;
case 'hazelcast.invalidation.reconciliation.interval.seconds':
value = tryGetNumber(value);
break;
case 'hazelcast.invalidation.max.tolerated.miss.count':
value = tryGetNumber(value);
break;
case 'hazelcast.invalidation.min.reconciliation.interval.seconds':
value = tryGetNumber(value);
break;
case 'hazelcast.logging.level':
tryGetEnum(LogLevel, value);
break;
case 'hazelcast.client.autopipelining.enabled':
value = tryGetBoolean(value);
break;
case 'hazelcast.client.autopipelining.threshold.bytes':
value = tryGetNumber(value);
break;
case 'hazelcast.client.socket.no.delay':
value = tryGetBoolean(value);
break;
case 'hazelcast.client.shuffle.member.list':
value = tryGetBoolean(value);
break;
case 'hazelcast.client.operation.backup.timeout.millis':
value = tryGetNumber(value);
break;
case 'hazelcast.client.operation.fail.on.indeterminate.state':
value = tryGetBoolean(value);
break;
case 'hazelcast.discovery.public.ip.enabled':
if (value !== null && typeof value !== 'boolean') {
throw new RangeError(`${value} is not null or a boolean.`);
}
break;
default:
throw new RangeError(`Unexpected property '${key}' is passed to the Hazelcast Client`);
}
} catch (e) {
throw new RangeError(`Property validation error: Property: ${key}, value: ${value}. Error: ${e}`);
}
this.effectiveConfig.properties[key] = jsonObject[key];

this.effectiveConfig.properties[key] = value;
}
}

Expand Down
3 changes: 2 additions & 1 deletion test/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"max-len": ["warn", 130],
"mocha/prefer-arrow-callback": ["error", {
"allowNamedFunctions": true
}]
}],
"padded-blocks": ["error", "never"]
},
"parserOptions": {
"ecmaVersion": 11
Expand Down
2 changes: 0 additions & 2 deletions test/TestUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ exports.randomString = function (length) {
};

class CountingMembershipListener {

constructor(expectedAdds, expectedRemoves) {
this.adds = 0;
this.expectedAdds = expectedAdds;
Expand Down Expand Up @@ -230,7 +229,6 @@ class CountingMembershipListener {
}
this._resolve();
}

}

exports.CountingMembershipListener = CountingMembershipListener;
Expand Down
1 change: 0 additions & 1 deletion test/integration/ClientShutdownTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ const { ConnectionManager } = require('../../lib/network/ConnectionManager');
const { InvocationService } = require('../../lib/invocation/InvocationService');

describe('ClientShutdownTest', function () {

let cluster;

afterEach(async function () {
Expand Down
1 change: 0 additions & 1 deletion test/integration/ConnectionManagerTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ const { promiseWaitMilliseconds } = require('../TestUtil');
* Basic tests for `ConnectionManager`.
*/
describe('ConnectionManagerTest', function () {

let cluster;
let client;
let server;
Expand Down
1 change: 0 additions & 1 deletion test/integration/ConnectionManagerTranslateTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ const { EndpointQualifier, ProtocolType } = require('../../lib/core/EndpointQual
* Tests address translation done by `ConnectionManager`.
*/
describe('ConnectionManagerTranslateTest', function () {

const PROPERTY_DISCOVERY_PUBLIC_IP_ENABLED = 'hazelcast.discovery.public.ip.enabled';
const REACHABLE_HOST = '127.0.0.1';
const UNREACHABLE_HOST = '192.168.0.1';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ const RC = require('../RC');
const { Client } = require('../../../');

describe('AutoPipeliningDisabledTest', function () {

let cluster;
let client;
let map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ const { ClientLocalBackupListenerCodec } = require('../../../lib/codec/ClientLoc
* so there is no need for additional member side configuration.
*/
describe('ClientBackupAcksTest', function () {

let cluster;
let client;

Expand Down
2 changes: 0 additions & 2 deletions test/integration/backward_compatible/ClientFailoverTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ function createClientConfig({ clusterName, lifecycleListener, connectTimeoutMs }
* Tests blue/green failover support for OSS.
*/
describe('ClientFailoverTest - community', function () {

let cluster1;
let cluster2;

Expand Down Expand Up @@ -101,7 +100,6 @@ describe('ClientFailoverTest - community', function () {
* Tests blue/green failover support for EE.
*/
describe('ClientFailoverTest - enterprise', function () {

let cluster1;
let member1;
let cluster2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const TestUtil = require('../../TestUtil');
* This test assumes cluster with a single member.
*/
describe('ClientHotRestartEventTest', function () {

let client;
let cluster;

Expand Down
2 changes: 0 additions & 2 deletions test/integration/backward_compatible/ClientLabelTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ const RC = require('./../RC');
const { Client } = require('../../../');

describe('ClientLabelTest', function () {

let cluster;
let client;

Expand Down Expand Up @@ -50,5 +49,4 @@ describe('ClientLabelTest', function () {
expect(res.result).to.not.be.null;
expect(res.result.toString()).to.equal('testLabel');
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ const TestUtil = require('../../TestUtil');
* Advanced tests for reconnection to cluster scenarios.
*/
describe('ClientReconnectAdvancedTest', function () {

let cluster;
let client;

Expand Down Expand Up @@ -95,7 +94,6 @@ describe('ClientReconnectAdvancedTest', function () {
const member = members[0];
expect(member.uuid.toString()).to.be.equal(newMember.uuid);
});

}

async function testListenersAfterClientDisconnected(memberAddress, clientAddress) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ const { markClientVersionAtLeast } = require('../../TestUtil');
* Basic tests for reconnection to cluster scenarios.
*/
describe('ClientReconnectTest', function () {

let cluster;
let client;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ const {
} = require('../../../');

describe('ClientRedoEnabledTest', function () {

let cluster;
let client;

Expand Down
1 change: 0 additions & 1 deletion test/integration/backward_compatible/ClusterServiceTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ const RC = require('../RC');
const { Client } = require('../../../');

describe('ClusterServiceTest', function () {

let cluster;
let member1;
let client;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ const { LifecycleState } = require('../../../lib/LifecycleService');
const TestUtil = require('../../TestUtil');

describe('ConnectionStrategyTest', function () {

let cluster;
let client;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const { Client } = require('../../../');
const TestUtil = require('../../TestUtil');

describe('DistributedObjectsTest', function () {

let cluster;
let client;

Expand Down
3 changes: 0 additions & 3 deletions test/integration/backward_compatible/HazelcastClientTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ const { deferredPromise } = require('../../../lib/util/Util');
const TestUtil = require('../../TestUtil');

class ManagedObjects {

constructor() {
this.managedObjects = [];
}
Expand Down Expand Up @@ -53,7 +52,6 @@ class ManagedObjects {
});
return deferred.promise;
}

}

const dummyConfig = {
Expand All @@ -75,7 +73,6 @@ const configParams = [

configParams.forEach((cfg) => {
describe('HazelcastClientTest[smart=' + cfg.network.smartRouting + ']', function () {

let cluster;
let client;
let managed;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const { Client } = require('../../../');
const { deferredPromise } = require('../../../lib/util/Util');

describe('InitialMembershipListenerTest', function () {

let cluster;
let initialMember;
let client;
Expand Down
Loading