Commit bc6c933f authored by Lucas Fernandes de Oliveira's avatar Lucas Fernandes de Oliveira
Browse files

Merge branch 'issue/61' into 'develop'

Issue #61:  Add route to sources

See merge request !55
parents b80adcb2 c26aaaaa
Pipeline #15096 passed with stages
in 1 minute
...@@ -234,3 +234,48 @@ enumTypes: ...@@ -234,3 +234,48 @@ enumTypes:
name: "enum type:3" name: "enum type:3"
values: values:
- "test:9" - "test:9"
sources:
-
name: "source:0"
description: "source with 3 entries"
fields:
-
name: "fields:0"
description: "first entry"
dataType: "string"
-
name: "fields:1"
description: "second entry"
dataType: "string"
-
name: "fields:2"
description: "third entry"
dataType: "string"
-
name: "source:1"
description: "source with 2 entries"
fields:
-
name: "fields:0"
description: "first entry"
dataType: "string"
-
name: "fields:1"
description: "second entry"
dataType: "string"
-
name: "source:2"
description: "source with one entry"
fields:
-
name: "fields:0"
description: "first entry"
dataType: "string"
-
name: "source:3"
description: "source with one entry and without description"
fields:
-
name: "fields:3"
dataType: "string"
...@@ -279,6 +279,13 @@ traits: ...@@ -279,6 +279,13 @@ traits:
system and their descriptions. system and their descriptions.
securedBy: [ null, oauth_2_0 ] securedBy: [ null, oauth_2_0 ]
get: get:
/sources:
description: |
A Source represents a type of object that can be inserted in the database.
This collection allows the user to list all the sources available in the
system and their descriptions
securedBy: [ null, oauth_2_0 ]
get:
/dimensions: /dimensions:
description: | description: |
......
...@@ -36,7 +36,17 @@ describe("API engine controller", () => { ...@@ -36,7 +36,17 @@ describe("API engine controller", () => {
}) })
.end(done); .end(done);
}); });
it("should respond 200 and the list of sources", (done) => {
request(server)
.get("/v1/sources")
.expect(200)
.expect((res: any) => {
let result = res.body;
expect(result).to.be.an("array");
expect(result).to.have.length(4);
})
.end(done);
});
it("should respond 200 and the list of dimensions", (done) => { it("should respond 200 and the list of dimensions", (done) => {
request(server) request(server)
.get("/v1/dimensions") .get("/v1/dimensions")
......
...@@ -26,11 +26,15 @@ export class EngineCtrl { ...@@ -26,11 +26,15 @@ export class EngineCtrl {
res.status(200).json(req.engine.getMetricsDescription()); res.status(200).json(req.engine.getMetricsDescription());
} }
public static dimensions(req: Request, res: express.Response, next: express.NextFunction) { public static dimensions(req: Request, res: express.Response, next: express.NextFunction) {
res.status(200).json(req.engine.getDimensionsDescription()); res.status(200).json(req.engine.getDimensionsDescription());
} }
public static enumTypes(req: Request, res: express.Response, next: express.NextFunction) { public static enumTypes(req: Request, res: express.Response, next: express.NextFunction) {
res.status(200).json(req.engine.getEnumTypesDescription()); res.status(200).json(req.engine.getEnumTypesDescription());
} }
public static sources(req: Request, res: express.Response, next: express.NextFunction) {
res.status(200).json(req.engine.getSourcesDescription());
}
} }
...@@ -29,6 +29,7 @@ export function EngineMw (config: ParsedConfig): Middleware { ...@@ -29,6 +29,7 @@ export function EngineMw (config: ParsedConfig): Middleware {
config.dimensions.forEach ((dim) => engine.addDimension(dim)); config.dimensions.forEach ((dim) => engine.addDimension(dim));
config.views.forEach ((view) => engine.addView(view)); config.views.forEach ((view) => engine.addView(view));
config.enumTypes.forEach ((enumt) => engine.addEnumType(enumt)); config.enumTypes.forEach ((enumt) => engine.addEnumType(enumt));
config.sources.forEach ((sourc) => engine.addSource(sourc));
return function engineMiddleware(req, res, next) { return function engineMiddleware(req, res, next) {
req.engine = engine; req.engine = engine;
......
...@@ -28,6 +28,7 @@ import { EngineCtrl } from "./controllers/engine"; ...@@ -28,6 +28,7 @@ import { EngineCtrl } from "./controllers/engine";
export const router = osprey.Router(); export const router = osprey.Router();
router.get("/metrics", EngineCtrl.metrics); router.get("/metrics", EngineCtrl.metrics);
router.get("/sources", EngineCtrl.sources);
router.get("/dimensions", EngineCtrl.dimensions); router.get("/dimensions", EngineCtrl.dimensions);
router.get("/enumtypes", EngineCtrl.enumTypes); router.get("/enumtypes", EngineCtrl.enumTypes);
router.get("/data", DataCtrl.read); router.get("/data", DataCtrl.read);
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
import * as express from "express"; import * as express from "express";
import { Engine } from "../core/engine"; import { Engine } from "../core/engine";
import { Adapter} from "../core/adpater"; import { Adapter} from "../core/adapter";
export interface Request extends express.Request { export interface Request extends express.Request {
engine: Engine; engine: Engine;
......
...@@ -26,12 +26,14 @@ import { View } from "./view"; ...@@ -26,12 +26,14 @@ import { View } from "./view";
import { Query } from "../common/query"; import { Query } from "../common/query";
import { Graph } from "../util/graph"; import { Graph } from "../util/graph";
import { EnumType, EnumTypeOptions} from "./enumType"; import { EnumType, EnumTypeOptions} from "./enumType";
import { Source , SourceOptions } from "./source";
export class Engine { export class Engine {
private views: View[] = []; private views: View[] = [];
private metrics: Metric[] = []; private metrics: Metric[] = [];
private enumTypes: EnumType[] = []; private enumTypes: EnumType[] = [];
private dimensions: Dimension[] = []; private dimensions: Dimension[] = [];
private sources: Source[] = [];
private graph: Graph; private graph: Graph;
constructor () { constructor () {
...@@ -39,6 +41,7 @@ export class Engine { ...@@ -39,6 +41,7 @@ export class Engine {
this.views = []; this.views = [];
this.metrics = []; this.metrics = [];
this.dimensions = []; this.dimensions = [];
this.sources = [];
this.graph = new Graph(); this.graph = new Graph();
} }
...@@ -54,6 +57,10 @@ export class Engine { ...@@ -54,6 +57,10 @@ export class Engine {
return this.enumTypes.map((i) => i.strOptions()); return this.enumTypes.map((i) => i.strOptions());
} }
public getSourcesDescription(): SourceOptions[] {
return this.sources.map((i) => i.strOptions());
}
public getDimensionsDescription() { public getDimensionsDescription() {
return this.dimensions.map((i) => i.strOptions()); return this.dimensions.map((i) => i.strOptions());
} }
...@@ -72,6 +79,11 @@ export class Engine { ...@@ -72,6 +79,11 @@ export class Engine {
return enumType; return enumType;
} }
public addSource(sourc: Source): Source {
this.sources.push(sourc);
return sourc;
}
public addMetric(metric: Metric) { public addMetric(metric: Metric) {
if (this.graph.addMetric(metric)) { if (this.graph.addMetric(metric)) {
this.metrics.push(metric); this.metrics.push(metric);
......
...@@ -18,12 +18,12 @@ ...@@ -18,12 +18,12 @@
* along with blendb. If not, see <http://www.gnu.org/licenses/>. * along with blendb. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { expect } from "chai"; // import { expect } from "chai";
//
// import { Server } from "./server";
import { Server } from "./server"; /*describe("server class", () => {
it("should be able to create and retrieve sources", () => {
describe("server class", () => {
it("should be able to create and retrieve sources", () => {
const server = new Server(); const server = new Server();
// create two sources // create two sources
...@@ -142,4 +142,4 @@ describe("server class", () => { ...@@ -142,4 +142,4 @@ describe("server class", () => {
server.transformer("transformerX"); server.transformer("transformerX");
}).to.throw(Error); }).to.throw(Error);
}); });
}); });*/
...@@ -35,7 +35,7 @@ export class Server { ...@@ -35,7 +35,7 @@ export class Server {
this.aggregates = new Map(); this.aggregates = new Map();
} }
public source(name: string, options?: any) { /*public source(name: string, options?: any) {
if (this.sources.has(name)) { if (this.sources.has(name)) {
return this.sources.get(name); return this.sources.get(name);
} }
...@@ -44,7 +44,7 @@ export class Server { ...@@ -44,7 +44,7 @@ export class Server {
this.sources.set(name, source); this.sources.set(name, source);
return source; return source;
} }
} }*/
public aggregate(metrics: string[], dimensions: string[], options?: any) { public aggregate(metrics: string[], dimensions: string[], options?: any) {
const id = Hash.sha1(metrics.sort(), dimensions.sort()); const id = Hash.sha1(metrics.sort(), dimensions.sort());
......
...@@ -18,27 +18,40 @@ ...@@ -18,27 +18,40 @@
* along with blendb. If not, see <http://www.gnu.org/licenses/>. * along with blendb. If not, see <http://www.gnu.org/licenses/>.
*/ */
export class Source { export interface Field {
public name: string; name: string;
private data: any[]; description?: string;
dataType: string;
constructor(name: string, options?: any) { }
this.name = name;
this.data = []; export interface SourceOptions {
} name: string;
description?: string;
fields: Field[];
}
public push(doc: any) { export class Source {
this.data.push(doc); public readonly name: string;
} public readonly description: string;
public readonly fields: Field[];
public forEach(callback: Function) { constructor(options: SourceOptions) {
this.data.forEach((value: any, index: number, array: any[]) => { this.name = options.name;
callback(value); this.description = (options.description) ? options.description : "";
this.fields = options.fields.map((item) => {
return {
name: item.name,
description: (item.description) ? item.description : "",
dataType: item.dataType
};
}); });
} }
public truncate() { public strOptions(): SourceOptions {
this.data = []; return {
name: this.name,
description: this.description,
fields: this.fields
};
} }
} }
...@@ -18,15 +18,15 @@ ...@@ -18,15 +18,15 @@
* along with blendb. If not, see <http://www.gnu.org/licenses/>. * along with blendb. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { expect } from "chai"; // import { expect } from "chai";
//
// import { Hash } from "../util/hash";
//
// import { Transformer } from "./transformer";
// import { Source } from "./source";
// import { Aggregate } from "./aggregate";
import { Hash } from "../util/hash"; /*describe("transformer class", () => {
import { Transformer } from "./transformer";
import { Source } from "./source";
import { Aggregate } from "./aggregate";
describe("transformer class", () => {
const source = new Source("testSource"); const source = new Source("testSource");
const aggregate = new Aggregate(["met:one"], ["dim:one", "dim:two"]); const aggregate = new Aggregate(["met:one"], ["dim:one", "dim:two"]);
...@@ -83,3 +83,4 @@ describe("transformer class", () => { ...@@ -83,3 +83,4 @@ describe("transformer class", () => {
expect(result[0].metrics["met:one"]).to.be.equal(25000); expect(result[0].metrics["met:one"]).to.be.equal(25000);
}); });
}); });
*/
...@@ -25,6 +25,7 @@ import { EnumType, EnumTypeOptions } from "../core/enumType"; ...@@ -25,6 +25,7 @@ import { EnumType, EnumTypeOptions } from "../core/enumType";
import { RelationType } from "../common/types"; import { RelationType } from "../common/types";
import { Filter } from "../core/filter"; import { Filter } from "../core/filter";
import { Clause } from "../core/clause"; import { Clause } from "../core/clause";
import { Source, SourceOptions} from "../core/source";
import * as fs from "fs"; import * as fs from "fs";
import * as yaml from "js-yaml"; import * as yaml from "js-yaml";
...@@ -40,6 +41,7 @@ export interface ViewParsingOptions { ...@@ -40,6 +41,7 @@ export interface ViewParsingOptions {
} }
interface ConfigSchema { interface ConfigSchema {
sources: SourceOptions[];
views: ViewParsingOptions[]; views: ViewParsingOptions[];
metrics: MetricStrOptions[]; metrics: MetricStrOptions[];
dimensions: DimensionStrOptions[]; dimensions: DimensionStrOptions[];
...@@ -61,6 +63,7 @@ export interface ParsedConfig { ...@@ -61,6 +63,7 @@ export interface ParsedConfig {
adapter: string; adapter: string;
connection: Connection; connection: Connection;
views: View[]; views: View[];
sources: Source[];
metrics: Metric[]; metrics: Metric[];
enumTypes: EnumType[]; enumTypes: EnumType[];
dimensions: Dimension[]; dimensions: Dimension[];
...@@ -89,6 +92,10 @@ interface EnumTypeMap{ ...@@ -89,6 +92,10 @@ interface EnumTypeMap{
[key: string]: EnumType; [key: string]: EnumType;
} }
interface SourceMap {
[key: string]: Source;
}
export class ConfigParser { export class ConfigParser {
public static parse(configPath: string): ParsedConfig { public static parse(configPath: string): ParsedConfig {
let config: ConfigSchema = yaml.safeLoad(fs.readFileSync(configPath, { let config: ConfigSchema = yaml.safeLoad(fs.readFileSync(configPath, {
...@@ -115,6 +122,7 @@ export class ConfigParser { ...@@ -115,6 +122,7 @@ export class ConfigParser {
let viewsOpts = config.views; let viewsOpts = config.views;
let dimensionsOpts = config.dimensions; let dimensionsOpts = config.dimensions;
let enumTypesOpts = config.enumTypes; let enumTypesOpts = config.enumTypes;
let sourcesOpts = config.sources;
let parsed: ParsedConfig = { let parsed: ParsedConfig = {
adapter: process.env.BLENDB_ADAPTER || "postgres", adapter: process.env.BLENDB_ADAPTER || "postgres",
connection: connection, connection: connection,
...@@ -124,12 +132,14 @@ export class ConfigParser { ...@@ -124,12 +132,14 @@ export class ConfigParser {
dimensions: [], dimensions: [],
struct: struct, struct: struct,
loadViews: [], loadViews: [],
buildViews: [] buildViews: [],
sources: []
}; };
let metMap: MetricMap = {}; let metMap: MetricMap = {};
let dimMap: DimensionMap = {}; let dimMap: DimensionMap = {};
let enumMap: EnumTypeMap = {}; let enumMap: EnumTypeMap = {};
let sourcMap: SourceMap = {};
for (let i = 0; i < metricsOpts.length; ++i) { for (let i = 0; i < metricsOpts.length; ++i) {
let met = new Metric(this.parseMetOpts(metricsOpts[i])); let met = new Metric(this.parseMetOpts(metricsOpts[i]));
...@@ -148,6 +158,12 @@ export class ConfigParser { ...@@ -148,6 +158,12 @@ export class ConfigParser {
dimMap[dim.name] = dim; dimMap[dim.name] = dim;
} }
for (let i = 0; i < sourcesOpts.length; i++) {
let sourc = new Source((sourcesOpts[i]));
parsed.sources.push(sourc);
sourcMap[sourc.name] = sourc;
}
for (let i = 0; i < viewsOpts.length; ++i) { for (let i = 0; i < viewsOpts.length; ++i) {
if (!viewsOpts[i].metrics) { if (!viewsOpts[i].metrics) {
viewsOpts[i].metrics = []; viewsOpts[i].metrics = [];
...@@ -192,6 +208,7 @@ export class ConfigParser { ...@@ -192,6 +208,7 @@ export class ConfigParser {
else { else {
throw new Error("[Parsing error] Non exist metric set to view " + opts.alias); throw new Error("[Parsing error] Non exist metric set to view " + opts.alias);
} }
} }
for (let i = 0; i < opts.dimensions.length; ++i) { for (let i = 0; i < opts.dimensions.length; ++i) {
...@@ -203,7 +220,6 @@ export class ConfigParser { ...@@ -203,7 +220,6 @@ export class ConfigParser {
throw new Error("[Parsing error] Non exist dimension set to view " + opts.alias); throw new Error("[Parsing error] Non exist dimension set to view " + opts.alias);
} }
} }
for (let i = 0; i < keys.length; ++i) { for (let i = 0; i < keys.length; ++i) {
if (dimMap[keys[i]]) { if (dimMap[keys[i]]) {
viewOpt.keys.push(dimMap[opts.keys[i]]); viewOpt.keys.push(dimMap[opts.keys[i]]);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment