Browse Source
* db connector * fix imports * minor fixes * todos * minor codestyle fix * todo * rm extra logs * abstract class -> interface * singletons Co-authored-by: corpglory-dev <dev@corpglory.com>pull/1/head
rozetko
5 years ago
committed by
GitHub
11 changed files with 208 additions and 96 deletions
@ -0,0 +1,8 @@ |
|||||||
|
export enum Collection { |
||||||
|
ANALYTIC_UNITS, |
||||||
|
ANALYTIC_UNIT_CACHES, |
||||||
|
SEGMENTS, |
||||||
|
THRESHOLD, |
||||||
|
DETECTION_SPANS, |
||||||
|
DB_META |
||||||
|
}; |
@ -0,0 +1,39 @@ |
|||||||
|
import { DBType } from '../../data_layer'; |
||||||
|
import { DbConnector } from './index'; |
||||||
|
import { MongodbConnector } from './mongodb_connector'; |
||||||
|
import { NedbConnector } from './nedb_connector'; |
||||||
|
|
||||||
|
import * as config from '../../../config'; |
||||||
|
|
||||||
|
|
||||||
|
export class DbConnectorFactory { |
||||||
|
private static _connector: DbConnector; |
||||||
|
|
||||||
|
private constructor() { } |
||||||
|
|
||||||
|
public static async getDbConnector(): Promise<DbConnector> { |
||||||
|
if(this._connector !== undefined) { |
||||||
|
return this._connector; |
||||||
|
} |
||||||
|
|
||||||
|
let connector: DbConnector; |
||||||
|
switch(config.HASTIC_DB_CONNECTION_TYPE) { |
||||||
|
case DBType.nedb: |
||||||
|
connector = NedbConnector.instance; |
||||||
|
break; |
||||||
|
|
||||||
|
case DBType.mongodb: |
||||||
|
connector = MongodbConnector.instance; |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
throw new Error( |
||||||
|
`"${config.HASTIC_DB_CONNECTION_TYPE}" HASTIC_DB_CONNECTION_TYPE is not supported. Possible values: "nedb", "mongodb"` |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
await connector.init(); |
||||||
|
this._connector = connector; |
||||||
|
return this._connector; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
import { Collection } from '../collection'; |
||||||
|
import { dbCollection } from '../../data_layer'; |
||||||
|
|
||||||
|
export interface DbConnector { |
||||||
|
db: Map<Collection, dbCollection>; |
||||||
|
init(): Promise<void>; |
||||||
|
// TODO: static instance?
|
||||||
|
} |
@ -0,0 +1,69 @@ |
|||||||
|
import { Collection } from '../collection'; |
||||||
|
import { DbConnector } from './index'; |
||||||
|
import { dbCollection } from '../../data_layer'; |
||||||
|
import * as config from '../../../config'; |
||||||
|
|
||||||
|
import * as mongodb from 'mongodb'; |
||||||
|
|
||||||
|
|
||||||
|
export class MongodbConnector implements DbConnector { |
||||||
|
private static _instance: MongodbConnector; |
||||||
|
|
||||||
|
private _db = new Map<Collection, dbCollection>(); |
||||||
|
|
||||||
|
private static COLLECTION_TO_NAME_MAPPING = new Map<Collection, string>([ |
||||||
|
[Collection.ANALYTIC_UNITS, 'analytic_units'], |
||||||
|
[Collection.ANALYTIC_UNIT_CACHES, 'analytic_unit_caches'], |
||||||
|
[Collection.SEGMENTS, 'segments'], |
||||||
|
[Collection.THRESHOLD, 'threshold'], |
||||||
|
[Collection.DETECTION_SPANS, 'detection_spans'], |
||||||
|
[Collection.DB_META, 'db_meta'] |
||||||
|
]); |
||||||
|
|
||||||
|
private _client: mongodb.MongoClient; |
||||||
|
|
||||||
|
private constructor() { } |
||||||
|
|
||||||
|
async init(): Promise<void> { |
||||||
|
const dbConfig = config.HASTIC_DB_CONFIG; |
||||||
|
const uri = `mongodb://${dbConfig.user}:${dbConfig.password}@${dbConfig.url}`; |
||||||
|
const auth = { |
||||||
|
user: dbConfig.user, |
||||||
|
password: dbConfig.password |
||||||
|
}; |
||||||
|
this._client = new mongodb.MongoClient(uri, { |
||||||
|
useNewUrlParser: true, |
||||||
|
auth, |
||||||
|
autoReconnect: true, |
||||||
|
useUnifiedTopology: true, |
||||||
|
// TODO: it should be configurable
|
||||||
|
authMechanism: 'SCRAM-SHA-1', |
||||||
|
authSource: dbConfig.dbName |
||||||
|
}); |
||||||
|
|
||||||
|
try { |
||||||
|
const client: mongodb.MongoClient = await this._client.connect(); |
||||||
|
const hasticDb: mongodb.Db = client.db(dbConfig.dbName); |
||||||
|
MongodbConnector.COLLECTION_TO_NAME_MAPPING.forEach( |
||||||
|
(name: string, collection: Collection) => { |
||||||
|
this._db.set(collection, hasticDb.collection(name)); |
||||||
|
} |
||||||
|
); |
||||||
|
} catch(err) { |
||||||
|
console.log(`got error while connecting to MongoDB: ${err}`); |
||||||
|
// TODO: throw a better error, e.g.: ServiceInitializationError
|
||||||
|
throw err; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
get db(): Map<Collection, dbCollection> { |
||||||
|
return this._db; |
||||||
|
} |
||||||
|
|
||||||
|
static get instance(): MongodbConnector { |
||||||
|
if(this._instance === undefined) { |
||||||
|
this._instance = new this(); |
||||||
|
} |
||||||
|
return this._instance; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,67 @@ |
|||||||
|
import { Collection } from '../collection'; |
||||||
|
import { DbConnector } from './index'; |
||||||
|
import { dbCollection } from '../../data_layer'; |
||||||
|
import * as config from '../../../config'; |
||||||
|
|
||||||
|
import * as nedb from 'nedb'; |
||||||
|
import * as fs from 'fs'; |
||||||
|
|
||||||
|
|
||||||
|
type NedbCollectionConfig = { |
||||||
|
filename: string, |
||||||
|
timestampData?: boolean |
||||||
|
}; |
||||||
|
|
||||||
|
function maybeCreateDir(path: string): void { |
||||||
|
if (fs.existsSync(path)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
console.log('data service: mkdir: ' + path); |
||||||
|
fs.mkdirSync(path); |
||||||
|
} |
||||||
|
|
||||||
|
function checkDataFolders(): void { |
||||||
|
[ |
||||||
|
config.DATA_PATH |
||||||
|
].forEach(maybeCreateDir); |
||||||
|
} |
||||||
|
|
||||||
|
export class NedbConnector implements DbConnector { |
||||||
|
private static _instance: NedbConnector; |
||||||
|
|
||||||
|
private _db = new Map<Collection, dbCollection>(); |
||||||
|
|
||||||
|
private static COLLECTION_TO_CONFIG_MAPPING = new Map<Collection, NedbCollectionConfig>([ |
||||||
|
[Collection.ANALYTIC_UNITS, { filename: config.ANALYTIC_UNITS_DATABASE_PATH, timestampData: true }], |
||||||
|
[Collection.ANALYTIC_UNIT_CACHES, { filename: config.ANALYTIC_UNIT_CACHES_DATABASE_PATH }], |
||||||
|
[Collection.SEGMENTS, { filename: config.SEGMENTS_DATABASE_PATH }], |
||||||
|
[Collection.THRESHOLD, { filename: config.THRESHOLD_DATABASE_PATH }], |
||||||
|
[Collection.DETECTION_SPANS, { filename: config.DETECTION_SPANS_DATABASE_PATH }], |
||||||
|
[Collection.DB_META, { filename: config.DB_META_PATH }], |
||||||
|
]); |
||||||
|
|
||||||
|
constructor() { } |
||||||
|
|
||||||
|
async init(): Promise<void> { |
||||||
|
checkDataFolders(); |
||||||
|
|
||||||
|
const inMemoryOnly = config.HASTIC_DB_IN_MEMORY; |
||||||
|
// TODO: it can throw an error, so we should catch it
|
||||||
|
NedbConnector.COLLECTION_TO_CONFIG_MAPPING.forEach( |
||||||
|
(config: NedbCollectionConfig, collection: Collection) => { |
||||||
|
this._db.set(collection, new nedb({ ...config, autoload: true, inMemoryOnly })); |
||||||
|
} |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
get db(): Map<Collection, dbCollection> { |
||||||
|
return this._db; |
||||||
|
} |
||||||
|
|
||||||
|
static get instance(): NedbConnector { |
||||||
|
if (this._instance === undefined) { |
||||||
|
this._instance = new this(); |
||||||
|
} |
||||||
|
return this._instance; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue