|
|
@ -2,6 +2,8 @@ import * as config from '../config'; |
|
|
|
|
|
|
|
|
|
|
|
import * as nedb from 'nedb'; |
|
|
|
import * as nedb from 'nedb'; |
|
|
|
import * as fs from 'fs'; |
|
|
|
import * as fs from 'fs'; |
|
|
|
|
|
|
|
import * as mongodb from 'mongodb'; |
|
|
|
|
|
|
|
import * as deasync from 'deasync'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export enum Collection {
|
|
|
|
export enum Collection {
|
|
|
@ -13,6 +15,15 @@ export enum Collection { |
|
|
|
DB_META |
|
|
|
DB_META |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const 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'] |
|
|
|
|
|
|
|
]) |
|
|
|
|
|
|
|
|
|
|
|
export enum SortingOrder { ASCENDING = 1, DESCENDING = -1 }; |
|
|
|
export enum SortingOrder { ASCENDING = 1, DESCENDING = -1 }; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -31,24 +42,24 @@ export type DBQ = { |
|
|
|
removeMany: (query: string[] | object) => Promise<number> |
|
|
|
removeMany: (query: string[] | object) => Promise<number> |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function nedbCollectionFromCollection(collection: Collection): nedb { |
|
|
|
function dbCollectionFromCollection(collection: Collection): nedb | mongodb.Collection<any> { |
|
|
|
let nedbCollection = db.get(collection); |
|
|
|
let dbCollection = db.get(collection); |
|
|
|
if(nedbCollection === undefined) { |
|
|
|
if(dbCollection === undefined) { |
|
|
|
throw new Error('Can`t find collection ' + collection); |
|
|
|
throw new Error('Can`t find collection ' + collection); |
|
|
|
} |
|
|
|
} |
|
|
|
return nedbCollection; |
|
|
|
return dbCollection; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function makeDBQ(collection: Collection): DBQ { |
|
|
|
export function makeDBQ(collection: Collection): DBQ { |
|
|
|
return { |
|
|
|
return { |
|
|
|
findOne: dbFindOne.bind(null, nedbCollectionFromCollection(collection)), |
|
|
|
findOne: dbFindOne.bind(null, dbCollectionFromCollection(collection)), |
|
|
|
findMany: dbFindMany.bind(null, nedbCollectionFromCollection(collection)), |
|
|
|
findMany: dbFindMany.bind(null, dbCollectionFromCollection(collection)), |
|
|
|
insertOne: dbInsertOne.bind(null, nedbCollectionFromCollection(collection)), |
|
|
|
insertOne: dbInsertOne.bind(null, dbCollectionFromCollection(collection)), |
|
|
|
insertMany: dbInsertMany.bind(null, nedbCollectionFromCollection(collection)), |
|
|
|
insertMany: dbInsertMany.bind(null, dbCollectionFromCollection(collection)), |
|
|
|
updateOne: dbUpdateOne.bind(null, nedbCollectionFromCollection(collection)), |
|
|
|
updateOne: dbUpdateOne.bind(null, dbCollectionFromCollection(collection)), |
|
|
|
updateMany: dbUpdateMany.bind(null, nedbCollectionFromCollection(collection)), |
|
|
|
updateMany: dbUpdateMany.bind(null, dbCollectionFromCollection(collection)), |
|
|
|
removeOne: dbRemoveOne.bind(null, nedbCollectionFromCollection(collection)), |
|
|
|
removeOne: dbRemoveOne.bind(null, dbCollectionFromCollection(collection)), |
|
|
|
removeMany: dbRemoveMany.bind(null, nedbCollectionFromCollection(collection)) |
|
|
|
removeMany: dbRemoveMany.bind(null, dbCollectionFromCollection(collection)) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -74,7 +85,8 @@ function isEmptyArray(obj: any): boolean { |
|
|
|
return obj.length == 0; |
|
|
|
return obj.length == 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const db = new Map<Collection, nedb>(); |
|
|
|
const db = new Map<Collection, nedb | mongodb.Collection<any>>(); |
|
|
|
|
|
|
|
let mongoClient: mongodb.MongoClient; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function dbInsertOne(nd: nedb, doc: object): Promise<string> { |
|
|
|
async function dbInsertOne(nd: nedb, doc: object): Promise<string> { |
|
|
@ -223,14 +235,60 @@ function checkDataFolders(): void { |
|
|
|
config.ZMQ_IPC_PATH |
|
|
|
config.ZMQ_IPC_PATH |
|
|
|
].forEach(maybeCreateDir); |
|
|
|
].forEach(maybeCreateDir); |
|
|
|
} |
|
|
|
} |
|
|
|
checkDataFolders(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const inMemoryOnly = config.HASTIC_DB_IN_MEMORY; |
|
|
|
async function connectToDb() { |
|
|
|
|
|
|
|
if(config.HASTIC_DB_CONNECTION_TYPE === 'nedb') { |
|
|
|
|
|
|
|
checkDataFolders(); |
|
|
|
|
|
|
|
const inMemoryOnly = config.HASTIC_DB_IN_MEMORY; |
|
|
|
|
|
|
|
console.log('NeDB used as storage'); |
|
|
|
|
|
|
|
// TODO: it's better if models request db which we create if it`s needed
|
|
|
|
|
|
|
|
db.set(Collection.ANALYTIC_UNITS, new nedb({ filename: config.ANALYTIC_UNITS_DATABASE_PATH, autoload: true, timestampData: true, inMemoryOnly})); |
|
|
|
|
|
|
|
db.set(Collection.ANALYTIC_UNIT_CACHES, new nedb({ filename: config.ANALYTIC_UNIT_CACHES_DATABASE_PATH, autoload: true, inMemoryOnly})); |
|
|
|
|
|
|
|
db.set(Collection.SEGMENTS, new nedb({ filename: config.SEGMENTS_DATABASE_PATH, autoload: true, inMemoryOnly})); |
|
|
|
|
|
|
|
db.set(Collection.THRESHOLD, new nedb({ filename: config.THRESHOLD_DATABASE_PATH, autoload: true, inMemoryOnly})); |
|
|
|
|
|
|
|
db.set(Collection.DETECTION_SPANS, new nedb({ filename: config.DETECTION_SPANS_DATABASE_PATH, autoload: true, inMemoryOnly})); |
|
|
|
|
|
|
|
db.set(Collection.DB_META, new nedb({ filename: config.DB_META_PATH, autoload: true, inMemoryOnly})); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
console.log('MongoDB used as storage'); |
|
|
|
|
|
|
|
const dbConfig = config.HASTIC_DB_CONFIG; |
|
|
|
|
|
|
|
const uri = `mongodb://${dbConfig.user}:${dbConfig.password}@${dbConfig.url}`; |
|
|
|
|
|
|
|
const auth = { |
|
|
|
|
|
|
|
user: dbConfig.user, |
|
|
|
|
|
|
|
password: dbConfig.password |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
mongoClient = new mongodb.MongoClient(uri, { |
|
|
|
|
|
|
|
useNewUrlParser: true, |
|
|
|
|
|
|
|
auth, |
|
|
|
|
|
|
|
autoReconnect: true, |
|
|
|
|
|
|
|
useUnifiedTopology: true, |
|
|
|
|
|
|
|
authMechanism: 'SCRAM-SHA-1', |
|
|
|
|
|
|
|
authSource: dbConfig.db_name |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
const client: mongodb.MongoClient = await mongoClient.connect(); |
|
|
|
|
|
|
|
const hasticDb: mongodb.Db = client.db(dbConfig.db_name); |
|
|
|
|
|
|
|
COLLECTION_TO_NAME_MAPPING.forEach((name, collection) => { |
|
|
|
|
|
|
|
db.set(collection, hasticDb.collection(name)); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} catch(err) { |
|
|
|
|
|
|
|
console.log(`got error while connect to MongoDB ${err}`); |
|
|
|
|
|
|
|
throw err; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export async function closeDb() { |
|
|
|
|
|
|
|
if(mongoClient !== undefined && mongoClient.isConnected) { |
|
|
|
|
|
|
|
await mongoClient.close(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO: it's better if models request db which we create if it`s needed
|
|
|
|
let done = false; |
|
|
|
db.set(Collection.ANALYTIC_UNITS, new nedb({ filename: config.ANALYTIC_UNITS_DATABASE_PATH, autoload: true, timestampData: true, inMemoryOnly})); |
|
|
|
connectToDb().then(() => { |
|
|
|
db.set(Collection.ANALYTIC_UNIT_CACHES, new nedb({ filename: config.ANALYTIC_UNIT_CACHES_DATABASE_PATH, autoload: true, inMemoryOnly})); |
|
|
|
done = true; |
|
|
|
db.set(Collection.SEGMENTS, new nedb({ filename: config.SEGMENTS_DATABASE_PATH, autoload: true, inMemoryOnly})); |
|
|
|
}).catch((err) => { |
|
|
|
db.set(Collection.THRESHOLD, new nedb({ filename: config.THRESHOLD_DATABASE_PATH, autoload: true, inMemoryOnly})); |
|
|
|
console.log(`data service got error while connect to data base ${err}`); |
|
|
|
db.set(Collection.DETECTION_SPANS, new nedb({ filename: config.DETECTION_SPANS_DATABASE_PATH, autoload: true, inMemoryOnly})); |
|
|
|
//TODO: choose best practice for error handling
|
|
|
|
db.set(Collection.DB_META, new nedb({ filename: config.DB_META_PATH, autoload: true, inMemoryOnly})); |
|
|
|
throw err; |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
deasync.loopWhile(() => !done); |
|
|
|