Skip to content

Commit

Permalink
Use POJsOs to model Cluster. Same pattern as DataCube type. (#886)
Browse files Browse the repository at this point in the history
* Use POJsOs to model Cluster. Same pattern as DataCube type.

* Cluster tests

* Renames for brevity
  • Loading branch information
adrianmroz-allegro authored Mar 17, 2022
1 parent 12c1cf9 commit a78295a
Show file tree
Hide file tree
Showing 20 changed files with 326 additions and 223 deletions.
8 changes: 4 additions & 4 deletions src/client/deserializers/app-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
*/

import { ClientAppSettings, SerializedAppSettings } from "../../common/models/app-settings/app-settings";
import { deserialize as customizationDeserialize } from "./customization";
import { deserialize as oauthDeserialize } from "./oauth";
import { deserialize as deserializeCustomization } from "./customization";
import { deserialize as deserializeOauth } from "./oauth";

export function deserialize({ oauth, clientTimeout, customization, version }: SerializedAppSettings): ClientAppSettings {
return {
clientTimeout,
version,
customization: customizationDeserialize(customization),
oauth: oauthDeserialize(oauth)
customization: deserializeCustomization(customization),
oauth: deserializeOauth(oauth)
};
}
21 changes: 21 additions & 0 deletions src/client/deserializers/cluster.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright 2017-2022 Allegro.pl
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { ClientCluster, SerializedCluster } from "../../common/models/cluster/cluster";

export function deserialize(cluster: SerializedCluster): ClientCluster {
return cluster;
}
4 changes: 2 additions & 2 deletions src/client/deserializers/customization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import { Timezone } from "chronoshift";
import { ClientCustomization, SerializedCustomization } from "../../common/models/customization/customization";
import { deserialize as localeDeserialize } from "../../common/models/locale/locale";
import { deserialize as deserializeLocale } from "../../common/models/locale/locale";

export function deserialize(customization: SerializedCustomization): ClientCustomization {
const { headerBackground, locale, customLogoSvg, timezones, externalViews, hasUrlShortener, sentryDSN } = customization;
Expand All @@ -26,7 +26,7 @@ export function deserialize(customization: SerializedCustomization): ClientCusto
externalViews,
hasUrlShortener,
sentryDSN,
locale: localeDeserialize(locale),
locale: deserializeLocale(locale),
timezones: timezones.map(Timezone.fromJS)
};
}
16 changes: 8 additions & 8 deletions src/client/deserializers/data-cube.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
import { Duration, Timezone } from "chronoshift";
import { AttributeInfo, Executor } from "plywood";
import { ClientDataCube, SerializedDataCube } from "../../common/models/data-cube/data-cube";
import { serialize as dimensionsSerialize } from "../../common/models/dimension/dimensions";
import { serialize as serializeDimensions } from "../../common/models/dimension/dimensions";
import { Filter } from "../../common/models/filter/filter";
import { serialize as measuresSerialize } from "../../common/models/measure/measures";
import { serialize as serializeMeasures } from "../../common/models/measure/measures";
import { RefreshRule } from "../../common/models/refresh-rule/refresh-rule";
import { deserialize as dimensionsDeserialize } from "./dimensions";
import { deserialize as measuresDeserialize } from "./measures";
import { deserialize as deserializeDimensions } from "./dimensions";
import { deserialize as deserializeMeasures } from "./measures";

export function deserialize(dataCube: SerializedDataCube, executor: Executor): ClientDataCube {
const {
Expand Down Expand Up @@ -60,12 +60,12 @@ export function deserialize(dataCube: SerializedDataCube, executor: Executor): C
defaultSplitDimensions,
defaultTimezone: Timezone.fromJS(defaultTimezone),
description,
dimensions: dimensionsDeserialize(dimensions),
dimensions: deserializeDimensions(dimensions),
executor,
extendedDescription,
group,
maxSplits,
measures: measuresDeserialize(measures),
measures: deserializeMeasures(measures),
name,
options,
refreshRule: RefreshRule.fromJS(refreshRule),
Expand Down Expand Up @@ -116,11 +116,11 @@ export function serialize(dataCube: ClientDataCube): SerializedDataCube {
defaultSplitDimensions,
defaultTimezone: defaultTimezone.toJS(),
description,
dimensions: dimensionsSerialize(dimensions),
dimensions: serializeDimensions(dimensions),
extendedDescription,
group,
maxSplits,
measures: measuresSerialize(measures),
measures: serializeMeasures(measures),
name,
options,
refreshRule: RefreshRule.fromJS(refreshRule),
Expand Down
4 changes: 2 additions & 2 deletions src/client/deserializers/dimensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

import { ClientDimensions, SerializedDimensions } from "../../common/models/dimension/dimensions";
import { mapValues } from "../../common/utils/object/object";
import { deserialize as dimensionDeserialize } from "./dimension";
import { deserialize as deserializeDimension } from "./dimension";

export function deserialize({ tree, byName }: SerializedDimensions): ClientDimensions {
return {
tree,
byName: mapValues(byName, dimensionDeserialize)
byName: mapValues(byName, deserializeDimension)
};
}
4 changes: 2 additions & 2 deletions src/client/deserializers/measures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

import { ClientMeasures, SerializedMeasures } from "../../common/models/measure/measures";
import { mapValues } from "../../common/utils/object/object";
import { deserialize as measureDeserialize } from "./measure";
import { deserialize as deserializeMeasure } from "./measure";

export function deserialize({ tree, byName }: SerializedMeasures): ClientMeasures {
return {
tree,
byName: mapValues(byName, measureDeserialize)
byName: mapValues(byName, deserializeMeasure)
};
}
8 changes: 4 additions & 4 deletions src/client/deserializers/sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@
*/

import { ClientAppSettings } from "../../common/models/app-settings/app-settings";
import { Cluster } from "../../common/models/cluster/cluster";
import { SerializedDataCube } from "../../common/models/data-cube/data-cube";
import { ClientSources, SerializedSources } from "../../common/models/sources/sources";
import { Ajax } from "../utils/ajax/ajax";
import { deserialize as dataCubeDeserialize } from "./data-cube";
import { deserialize as deserializeCluster } from "./cluster";
import { deserialize as deserializeDataCube } from "./data-cube";

export function deserialize(settings: SerializedSources, appSettings: ClientAppSettings): ClientSources {
const clusters = settings.clusters.map(cluster => Cluster.fromJS(cluster));
const clusters = settings.clusters.map(deserializeCluster);

const dataCubes = settings.dataCubes.map((dataCube: SerializedDataCube) => {
const executor = Ajax.queryUrlExecutorFactory(dataCube.name, appSettings);
return dataCubeDeserialize(dataCube, executor);
return deserializeDataCube(dataCube, executor);
});

return {
Expand Down
8 changes: 4 additions & 4 deletions src/common/models/app-settings/app-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ import {
Customization,
CustomizationJS,
fromConfig as customizationFromConfig,
serialize as customizationSerialize,
serialize as serializeCustomization,
SerializedCustomization
} from "../customization/customization";
import {
fromConfig as oauthFromConfig,
Oauth,
OauthJS,
serialize as oauthSerialize,
serialize as serializeOauth,
SerializedOauth
} from "../oauth/oauth";

Expand Down Expand Up @@ -82,8 +82,8 @@ export function serialize({ oauth, clientTimeout, customization, version }: AppS
return {
clientTimeout,
version,
customization: customizationSerialize(customization),
oauth: oauthSerialize(oauth)
customization: serializeCustomization(customization),
oauth: serializeOauth(oauth)
};
}

Expand Down
8 changes: 4 additions & 4 deletions src/common/models/cluster/cluster.fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { Cluster, ClusterJS } from "./cluster";
import { Cluster, ClusterJS, fromConfig } from "./cluster";

export class ClusterFixtures {
static druidWikiClusterJS(): ClusterJS {
Expand All @@ -33,7 +33,7 @@ export class ClusterFixtures {
}

static druidWikiCluster(): Cluster {
return Cluster.fromJS(ClusterFixtures.druidWikiClusterJS());
return fromConfig(ClusterFixtures.druidWikiClusterJS());
}

static druidTwitterClusterJS(): ClusterJS {
Expand All @@ -52,11 +52,11 @@ export class ClusterFixtures {
}

static druidTwitterCluster(): Cluster {
return Cluster.fromJS(ClusterFixtures.druidTwitterClusterJS());
return fromConfig(ClusterFixtures.druidTwitterClusterJS());
}

static druidTwitterClusterJSWithGuard(guardDataCubes = true): Cluster {
return Cluster.fromJS({
return fromConfig({
name: "druid-custom",
url: "http://192.168.99.101",
version: "0.9.1",
Expand Down
168 changes: 126 additions & 42 deletions src/common/models/cluster/cluster.mocha.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,56 +15,140 @@
* limitations under the License.
*/

import { expect } from "chai";
import { testImmutableClass } from "immutable-class-tester";
import { Cluster, ClusterJS } from "./cluster";
import { expect, use } from "chai";
import equivalent from "../../../client/utils/test-utils/equivalent";
import { RequestDecorator } from "../../../server/utils/request-decorator/request-decorator";
import { RetryOptions } from "../../../server/utils/retry-options/retry-options";
import { ClusterJS, fromConfig } from "./cluster";

use(equivalent);

describe("Cluster", () => {
// TODO: reimplement this test as simpler cases without immutable-class-tester - it checks too much
it.skip("is an immutable class", () => {
testImmutableClass(Cluster, [
{
name: "my-druid-cluster"
},
{
name: "my-druid-cluster",
url: "https://192.168.99.100",
version: "0.9.1",
timeout: 30000,
healthCheckTimeout: 50,
sourceListScan: "auto",
sourceListRefreshOnLoad: true,
sourceListRefreshInterval: 10000,
sourceReintrospectInterval: 10000,

introspectionStrategy: "segment-metadata-fallback"
},
{
name: "my-mysql-cluster",
url: "http://192.168.99.100",
timeout: 30000,
sourceListScan: "auto"
},
{
name: "my-mysql-cluster",
url: "https://192.168.99.100",
timeout: 30000,
sourceListScan: "auto",
describe("fromConfig", () => {
it("should load default values", () => {
const cluster = fromConfig({
name: "foobar",
url: "http://bazz"
});

expect(cluster).to.be.deep.equal({
name: "foobar",
guardDataCubes: false,
healthCheckTimeout: 1000,
introspectionStrategy: "segment-metadata-fallback",
requestDecorator: null,
retry: new RetryOptions(),
sourceListRefreshInterval: 0,
sourceReintrospectInterval: 0
}
]);
});
sourceListRefreshOnLoad: false,
sourceListScan: "auto",
sourceReintrospectInterval: 0,
sourceReintrospectOnLoad: false,
timeout: undefined,
title: "",
type: "druid",
url: "http://bazz",
version: null
});
});

it("should throw with incorrect name type", () => {
expect(() => fromConfig({ name: 1 } as unknown as ClusterJS)).to.throw("must be a string");
});

it("should throw with incorrect empty name", () => {
expect(() => fromConfig({ name: "", url: "http://foobar" })).to.throw("empty name");
});

it("should throw with not url safe name", () => {
expect(() => fromConfig({ name: "foobar%bazz#", url: "http://foobar" })).to.throw("is not a URL safe name");
});

it("should throw with name equal to native", () => {
expect(() => fromConfig({ name: "native", url: "http://foobar" })).to.throw("name can not be 'native'");
});

it("should read retry options", () => {
const cluster = fromConfig({
name: "foobar",
url: "http://foobar",
retry: {
maxAttempts: 1,
delay: 42
}
});

expect(cluster.retry).to.be.equivalent(new RetryOptions({ maxAttempts: 1, delay: 42 }));
});

it("should read request decorator", () => {
const cluster = fromConfig({
name: "foobar",
url: "http://foobar",
requestDecorator: {
path: "foobar",
options: { bazz: true }
}
});

expect(cluster.requestDecorator).to.be.equivalent(new RequestDecorator("foobar", { bazz: true }));
});

it("should read request decorator old format", () => {
const cluster = fromConfig({
name: "foobar",
url: "http://foobar",
requestDecorator: "foobar",
decoratorOptions: { bazz: true }
} as unknown as ClusterJS);

expect(cluster.requestDecorator).to.be.equivalent(new RequestDecorator("foobar", { bazz: true }));
});

describe("backward compatibility", () => {
it("should read old host and assume http protocol", () => {
const cluster = Cluster.fromJS({
const cluster = fromConfig({
name: "old-host",
host: "broker-host.com"
} as ClusterJS);
} as unknown as ClusterJS);

expect(cluster.url).to.be.eq("http://broker-host.com");
});
});

});
it("should override default values", () => {
const cluster = fromConfig({
guardDataCubes: true,
healthCheckTimeout: 42,
introspectionStrategy: "introspection-introspection",
name: "cluster-name",
sourceListRefreshInterval: 1123,
sourceListRefreshOnLoad: true,
sourceListScan: "auto",
sourceReintrospectInterval: 1432,
sourceReintrospectOnLoad: true,
timeout: 581,
title: "foobar-title",
url: "http://url-bazz",
version: "new-version"
});

expect(cluster).to.be.deep.equal({
guardDataCubes: true,
healthCheckTimeout: 42,
introspectionStrategy: "introspection-introspection",
name: "cluster-name",
sourceListRefreshInterval: 1123,
sourceListRefreshOnLoad: true,
sourceListScan: "auto",
sourceReintrospectInterval: 1432,
sourceReintrospectOnLoad: true,
timeout: 581,
title: "foobar-title",
url: "http://url-bazz",
version: "new-version",
type: "druid",
requestDecorator: null,
retry: new RetryOptions()
});
});
});
})
;
Loading

0 comments on commit a78295a

Please sign in to comment.