mirror of
https://gitlab.com/MrFry/mrfrys-node-server
synced 2025-04-01 20:24:18 +02:00
Answering questions using worker poolz
This commit is contained in:
parent
f5f3b51eee
commit
d8695682f7
4 changed files with 67 additions and 91 deletions
|
@ -38,7 +38,8 @@ import {
|
||||||
} from '../../utils/actions'
|
} from '../../utils/actions'
|
||||||
import dbtools from '../../utils/dbtools'
|
import dbtools from '../../utils/dbtools'
|
||||||
import auth from '../../middlewares/auth.middleware'
|
import auth from '../../middlewares/auth.middleware'
|
||||||
import { dataToString, searchDatas } from '../../utils/classes'
|
import { dataToString } from '../../utils/classes'
|
||||||
|
import { initWorkerPool, doALongTask } from '../../utils/workerPool'
|
||||||
|
|
||||||
import { SetupData } from '../../server'
|
import { SetupData } from '../../server'
|
||||||
import { ModuleType, User, DataFile, Request } from '../../types/basicTypes'
|
import { ModuleType, User, DataFile, Request } from '../../types/basicTypes'
|
||||||
|
@ -75,6 +76,8 @@ let publicdirs = []
|
||||||
function GetApp(): ModuleType {
|
function GetApp(): ModuleType {
|
||||||
const app = express()
|
const app = express()
|
||||||
|
|
||||||
|
initWorkerPool()
|
||||||
|
|
||||||
const publicDir = publicdirs[0]
|
const publicDir = publicdirs[0]
|
||||||
if (!publicDir) {
|
if (!publicDir) {
|
||||||
throw new Error(`No public dir! ( API )`)
|
throw new Error(`No public dir! ( API )`)
|
||||||
|
@ -1066,7 +1069,19 @@ function GetApp(): ModuleType {
|
||||||
const question = req.query.q
|
const question = req.query.q
|
||||||
const recData: any = req.query.data
|
const recData: any = req.query.data
|
||||||
|
|
||||||
searchDatas(questionDbs, question, subj, recData)
|
const promises = []
|
||||||
|
|
||||||
|
questionDbs.map((qdb, i) => {
|
||||||
|
promises.push(
|
||||||
|
doALongTask(i, {
|
||||||
|
type: 'work',
|
||||||
|
index: i,
|
||||||
|
data: { qdb: qdb.data, question, subjName: subj, recData },
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
Promise.all(promises)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
try {
|
try {
|
||||||
const mergedResult = result.reduce((acc, dbRes) => {
|
const mergedResult = result.reduce((acc, dbRes) => {
|
||||||
|
|
|
@ -289,17 +289,3 @@ if (certsLoaded) {
|
||||||
} else {
|
} else {
|
||||||
logger.Log('Https not avaible')
|
logger.Log('Https not avaible')
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('hai')
|
|
||||||
import { init, doALongTask } from './utils/workerPool'
|
|
||||||
init()
|
|
||||||
setTimeout(() => {
|
|
||||||
doALongTask(1, {
|
|
||||||
type: 'work',
|
|
||||||
add: 1,
|
|
||||||
index: 1,
|
|
||||||
}).then((res) => {
|
|
||||||
console.log('woohoo!')
|
|
||||||
console.log(res)
|
|
||||||
})
|
|
||||||
}, 6000)
|
|
||||||
|
|
|
@ -254,6 +254,7 @@ function compareData(q1: Question, q2: Question) {
|
||||||
logger.DebugLog('Error comparing data', 'Compare question data', 1)
|
logger.DebugLog('Error comparing data', 'Compare question data', 1)
|
||||||
logger.DebugLog(error.message, 'Compare question data', 1)
|
logger.DebugLog(error.message, 'Compare question data', 1)
|
||||||
logger.DebugLog(error, 'Compare question data', 2)
|
logger.DebugLog(error, 'Compare question data', 2)
|
||||||
|
console.error(error)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -273,7 +274,7 @@ function compareQuestionObj(
|
||||||
q2subjName: string,
|
q2subjName: string,
|
||||||
data: QuestionData
|
data: QuestionData
|
||||||
) {
|
) {
|
||||||
assert(data)
|
assert(data !== undefined || data !== null)
|
||||||
assert(q1)
|
assert(q1)
|
||||||
assert(typeof q1 === 'object')
|
assert(typeof q1 === 'object')
|
||||||
assert(q2)
|
assert(q2)
|
||||||
|
@ -321,12 +322,7 @@ function questionToString(question: Question) {
|
||||||
// ---------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------
|
||||||
// Subject
|
// Subject
|
||||||
// ---------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------
|
||||||
function searchQuestion(
|
function searchQuestion(subj: Subject, question: Question, subjName: string) {
|
||||||
subj: Subject,
|
|
||||||
question: Question,
|
|
||||||
questionData: QuestionData,
|
|
||||||
subjName: string
|
|
||||||
) {
|
|
||||||
assert(question)
|
assert(question)
|
||||||
|
|
||||||
let result = []
|
let result = []
|
||||||
|
@ -336,7 +332,7 @@ function searchQuestion(
|
||||||
subjName,
|
subjName,
|
||||||
question,
|
question,
|
||||||
subj.Name,
|
subj.Name,
|
||||||
questionData
|
question.data
|
||||||
)
|
)
|
||||||
|
|
||||||
if (percent.avg > minMatchAmmount) {
|
if (percent.avg > minMatchAmmount) {
|
||||||
|
@ -409,19 +405,6 @@ function addQuestion(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchDatas(
|
|
||||||
data: Array<QuestionDb>,
|
|
||||||
question: any,
|
|
||||||
subjName: string,
|
|
||||||
questionData?: QuestionData
|
|
||||||
): Promise<Array<SearchResult>> {
|
|
||||||
return Promise.all(
|
|
||||||
data.map((db: QuestionDb) => {
|
|
||||||
return searchData(db, question, subjName, questionData)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareQuestion(
|
function prepareQuestion(
|
||||||
question: string | Question,
|
question: string | Question,
|
||||||
data: string | QuestionData
|
data: string | QuestionData
|
||||||
|
@ -518,14 +501,21 @@ function dataToString(data: Array<Subject>): string {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
function searchWorker(
|
function doSearch(
|
||||||
data: Array<Subject>,
|
data: Array<Subject>,
|
||||||
subjName: string,
|
subjName: string,
|
||||||
question: Question,
|
question: Question | string,
|
||||||
questionData?: QuestionData
|
questionData?: QuestionData
|
||||||
): any {
|
): any {
|
||||||
let result = []
|
let result = []
|
||||||
|
|
||||||
|
const questionToSearch =
|
||||||
|
typeof question === 'string'
|
||||||
|
? createQuestion(question, null, questionData || { type: 'simple' })
|
||||||
|
: question
|
||||||
|
|
||||||
|
assert(questionToSearch.data)
|
||||||
|
|
||||||
data.forEach((subj) => {
|
data.forEach((subj) => {
|
||||||
if (
|
if (
|
||||||
subjName
|
subjName
|
||||||
|
@ -533,9 +523,7 @@ function searchWorker(
|
||||||
.includes(getSubjNameWithoutYear(subj.Name).toLowerCase())
|
.includes(getSubjNameWithoutYear(subj.Name).toLowerCase())
|
||||||
) {
|
) {
|
||||||
logger.DebugLog(`Searching in ${subj.Name} `, 'searchworker', 2)
|
logger.DebugLog(`Searching in ${subj.Name} `, 'searchworker', 2)
|
||||||
result = result.concat(
|
result = result.concat(searchQuestion(subj, questionToSearch, subjName))
|
||||||
searchQuestion(subj, question, questionData, subjName)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -552,9 +540,7 @@ function searchWorker(
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
data.forEach((subj) => {
|
data.forEach((subj) => {
|
||||||
result = result.concat(
|
result = result.concat(searchQuestion(subj, questionToSearch, subjName))
|
||||||
searchQuestion(subj, question, questionData, subjName)
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
if (result.length > 0) {
|
if (result.length > 0) {
|
||||||
logger.DebugLog(
|
logger.DebugLog(
|
||||||
|
@ -576,8 +562,7 @@ function searchWorker(
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
parentPort.postMessage(result)
|
return result
|
||||||
process.exit(0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const workerTs = (file: string, wkOpts: any) => {
|
const workerTs = (file: string, wkOpts: any) => {
|
||||||
|
@ -598,51 +583,42 @@ const workerTs = (file: string, wkOpts: any) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (!isMainThread) {
|
|
||||||
// logger.DebugLog(`Starting search worker ...`, 'searchworker', 1)
|
|
||||||
// const { data, subjName, question, questionData } = workerData
|
|
||||||
// searchWorker(data, subjName, question, questionData)
|
|
||||||
// }
|
|
||||||
|
|
||||||
function random(min, max) {
|
|
||||||
return Math.floor(Math.random() * (max - min) + min)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isMainThread) {
|
if (!isMainThread) {
|
||||||
const workerIndex = workerData.workerIndex
|
const workerIndex = workerData.workerIndex
|
||||||
const timeoutMin = workerData.workerTimeoutMin
|
// TODO: check if thread independent
|
||||||
const timeoutMax = workerData.workerTimeoutMax
|
|
||||||
const data = { val: 0 }
|
|
||||||
|
|
||||||
console.log(
|
logger.Log(
|
||||||
`[THREAD #${workerIndex}]: Worker ${workerIndex} reporting for duty`
|
`[THREAD #${workerIndex}]: Worker ${workerIndex} reporting for duty`
|
||||||
)
|
)
|
||||||
console.log(`[THREAD #${workerIndex}]: data`, workerData)
|
|
||||||
// parentPort.postMessage('hello parent port')
|
|
||||||
|
|
||||||
parentPort.on('message', (msg) => {
|
parentPort.on('message', (msg) => {
|
||||||
// console.log(`[THREAD #${workerIndex}]: onmsg`, msg)
|
|
||||||
|
|
||||||
if (msg.type === 'work') {
|
if (msg.type === 'work') {
|
||||||
|
const { qdb, subjName, question, questionData } = msg.data
|
||||||
const index = msg.index
|
const index = msg.index
|
||||||
console.log(`[THREAD #${workerIndex}]: staring work on ${index}`)
|
console.log(`[THREAD #${workerIndex}]: staring work on ${index}`)
|
||||||
setTimeout(() => {
|
|
||||||
data.val = data.val + msg.add
|
|
||||||
parentPort.postMessage({
|
|
||||||
msg: `From thread #${workerIndex}: job ${index} done`,
|
|
||||||
workerIndex: workerIndex,
|
|
||||||
result: data.val,
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log(`[THREAD #${workerIndex}]: Work ${index} done!`)
|
let searchResult = null
|
||||||
}, random(timeoutMin, timeoutMax))
|
try {
|
||||||
|
searchResult = doSearch(qdb, subjName, question, questionData)
|
||||||
|
} catch (err) {
|
||||||
|
logger.Log('Error in worker thread!', logger.GetColor('redbg'))
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ONDONE:
|
||||||
|
parentPort.postMessage({
|
||||||
|
msg: `From thread #${workerIndex}: job ${index} done`,
|
||||||
|
workerIndex: workerIndex,
|
||||||
|
result: searchResult,
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(`[THREAD #${workerIndex}]: Work ${index} done!`)
|
||||||
} else if (msg.type === 'update') {
|
} else if (msg.type === 'update') {
|
||||||
if (msg.data.workerIndex !== workerIndex) {
|
if (msg.data.workerIndex !== workerIndex) {
|
||||||
|
// TODO
|
||||||
|
// qdbs = msg.qdb
|
||||||
console.log(`[THREAD #${workerIndex}]: update`, msg.data)
|
console.log(`[THREAD #${workerIndex}]: update`, msg.data)
|
||||||
console.log(
|
console.log(`[THREAD #${workerIndex}]: From ... to ${msg.data.result}`)
|
||||||
`[THREAD #${workerIndex}]: From ${data.val} to ${msg.data.result}`
|
|
||||||
)
|
|
||||||
data.val = msg.data.result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -658,6 +634,5 @@ export {
|
||||||
createQuestion,
|
createQuestion,
|
||||||
addQuestion,
|
addQuestion,
|
||||||
searchData,
|
searchData,
|
||||||
searchDatas,
|
|
||||||
dataToString,
|
dataToString,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,12 @@ import { Worker } from 'worker_threads'
|
||||||
import genericPool from 'generic-pool'
|
import genericPool from 'generic-pool'
|
||||||
import os from 'os'
|
import os from 'os'
|
||||||
|
|
||||||
|
import logger from './logger'
|
||||||
|
// import { QuestionDb } from '../types/basicTypes'
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
const workerFile = './src/utils/classes.ts'
|
const workerFile = './src/utils/classes.ts'
|
||||||
const workerTimeoutMin = 5 * 1000
|
|
||||||
const workerTimeoutMax = 10 * 1000
|
|
||||||
let pool: any = null
|
let pool: any = null
|
||||||
let workers: any = null
|
let workers: any = null
|
||||||
|
|
||||||
|
@ -30,17 +31,17 @@ export function doALongTask(i: Number, obj: any): Promise<any> {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
console.log('resourcePromise error')
|
logger.Log('resourcePromise error', logger.GetColor('redbg'))
|
||||||
console.log(err)
|
console.error(err)
|
||||||
// handle error - this is generally a timeout or maxWaitingClients
|
// handle error - this is generally a timeout or maxWaitingClients
|
||||||
// error
|
// error
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function init(): void {
|
export function initWorkerPool(): void {
|
||||||
if (workers && pool) {
|
if (workers && pool) {
|
||||||
console.log('WORKER AND POOL ALREADY EXISTS')
|
logger.Log('WORKER AND POOL ALREADY EXISTS', logger.GetColor('redbg'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
workers = []
|
workers = []
|
||||||
|
@ -84,27 +85,26 @@ function getAWorker(i) {
|
||||||
const worker = workerTs(workerFile, {
|
const worker = workerTs(workerFile, {
|
||||||
workerData: {
|
workerData: {
|
||||||
workerIndex: i,
|
workerIndex: i,
|
||||||
workerTimeoutMin,
|
|
||||||
workerTimeoutMax,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
worker.setMaxListeners(50)
|
worker.setMaxListeners(50)
|
||||||
|
|
||||||
// worker.on('message', (msg) => {
|
// worker.on('message', (msg) => {
|
||||||
// console.log(`[MAIN]: Msg from worker #${i}`, msg)
|
// logger.Log(`[MAIN]: Msg from worker #${i}`, msg)
|
||||||
// })
|
// })
|
||||||
|
|
||||||
worker.on('online', () => {
|
worker.on('online', () => {
|
||||||
console.log(`[THREAD #${i}]: Worker ${i} online`)
|
logger.Log(`[THREAD #${i}]: Worker ${i} online`)
|
||||||
})
|
})
|
||||||
|
|
||||||
worker.on('error', (err) => {
|
worker.on('error', (err) => {
|
||||||
console.log(err)
|
logger.Log('Worker error!', logger.GetColor('redbg'))
|
||||||
|
console.error(err)
|
||||||
})
|
})
|
||||||
|
|
||||||
worker.on('exit', (code) => {
|
worker.on('exit', (code) => {
|
||||||
console.log(`[MAIN]: worker #${i} exit code: `, code)
|
logger.Log(`[MAIN]: worker #${i} exit code: ${code}`)
|
||||||
})
|
})
|
||||||
return worker
|
return worker
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue