mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 15:00:57 +03:00
Feature/Add bullmq redis for message queue processing (#3568)
* add bullmq redis for message queue processing * Update pnpm-lock.yaml * update queue manager * remove singleton patterns, add redis to cache pool * add bull board ui * update rate limit handler * update redis configuration * Merge add rate limit redis prefix * update rate limit queue events * update preview loader to queue * refractor namings to constants * update env variable for queue * update worker shutdown gracefully
This commit is contained in:
@@ -2,7 +2,7 @@ import { NextFunction, Request, Response } from 'express'
|
||||
import { StatusCodes } from 'http-status-codes'
|
||||
import apiKeyService from '../../services/apikey'
|
||||
import { ChatFlow } from '../../database/entities/ChatFlow'
|
||||
import { updateRateLimiter } from '../../utils/rateLimit'
|
||||
import { RateLimiterManager } from '../../utils/rateLimit'
|
||||
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
|
||||
import { ChatflowType } from '../../Interface'
|
||||
import chatflowsService from '../../services/chatflows'
|
||||
@@ -130,7 +130,8 @@ const updateChatflow = async (req: Request, res: Response, next: NextFunction) =
|
||||
Object.assign(updateChatFlow, body)
|
||||
|
||||
updateChatFlow.id = chatflow.id
|
||||
updateRateLimiter(updateChatFlow)
|
||||
const rateLimiterManager = RateLimiterManager.getInstance()
|
||||
await rateLimiterManager.updateRateLimiter(updateChatFlow)
|
||||
|
||||
const apiResponse = await chatflowsService.updateChatflow(chatflow, updateChatFlow)
|
||||
return res.json(apiResponse)
|
||||
|
||||
@@ -4,15 +4,8 @@ import documentStoreService from '../../services/documentstore'
|
||||
import { DocumentStore } from '../../database/entities/DocumentStore'
|
||||
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
|
||||
import { DocumentStoreDTO } from '../../Interface'
|
||||
import { getRateLimiter } from '../../utils/rateLimit'
|
||||
|
||||
const getRateLimiterMiddleware = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
return getRateLimiter(req, res, next)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
import { FLOWISE_COUNTER_STATUS, FLOWISE_METRIC_COUNTERS } from '../../Interface.Metrics'
|
||||
|
||||
const createDocumentStore = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
@@ -90,8 +83,14 @@ const getDocumentStoreFileChunks = async (req: Request, res: Response, next: Nex
|
||||
`Error: documentStoreController.getDocumentStoreFileChunks - fileId not provided!`
|
||||
)
|
||||
}
|
||||
const appDataSource = getRunningExpressApp().AppDataSource
|
||||
const page = req.params.pageNo ? parseInt(req.params.pageNo) : 1
|
||||
const apiResponse = await documentStoreService.getDocumentStoreFileChunks(req.params.storeId, req.params.fileId, page)
|
||||
const apiResponse = await documentStoreService.getDocumentStoreFileChunks(
|
||||
appDataSource,
|
||||
req.params.storeId,
|
||||
req.params.fileId,
|
||||
page
|
||||
)
|
||||
return res.json(apiResponse)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
@@ -171,6 +170,7 @@ const editDocumentStoreFileChunk = async (req: Request, res: Response, next: Nex
|
||||
|
||||
const saveProcessingLoader = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
if (typeof req.body === 'undefined') {
|
||||
throw new InternalFlowiseError(
|
||||
StatusCodes.PRECONDITION_FAILED,
|
||||
@@ -178,7 +178,7 @@ const saveProcessingLoader = async (req: Request, res: Response, next: NextFunct
|
||||
)
|
||||
}
|
||||
const body = req.body
|
||||
const apiResponse = await documentStoreService.saveProcessingLoader(body)
|
||||
const apiResponse = await documentStoreService.saveProcessingLoader(appServer.AppDataSource, body)
|
||||
return res.json(apiResponse)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
@@ -201,7 +201,7 @@ const processLoader = async (req: Request, res: Response, next: NextFunction) =>
|
||||
}
|
||||
const docLoaderId = req.params.loaderId
|
||||
const body = req.body
|
||||
const apiResponse = await documentStoreService.processLoader(body, docLoaderId)
|
||||
const apiResponse = await documentStoreService.processLoaderMiddleware(body, docLoaderId)
|
||||
return res.json(apiResponse)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
@@ -264,7 +264,7 @@ const previewFileChunks = async (req: Request, res: Response, next: NextFunction
|
||||
}
|
||||
const body = req.body
|
||||
body.preview = true
|
||||
const apiResponse = await documentStoreService.previewChunks(body)
|
||||
const apiResponse = await documentStoreService.previewChunksMiddleware(body)
|
||||
return res.json(apiResponse)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
@@ -286,9 +286,15 @@ const insertIntoVectorStore = async (req: Request, res: Response, next: NextFunc
|
||||
throw new Error('Error: documentStoreController.insertIntoVectorStore - body not provided!')
|
||||
}
|
||||
const body = req.body
|
||||
const apiResponse = await documentStoreService.insertIntoVectorStore(body)
|
||||
const apiResponse = await documentStoreService.insertIntoVectorStoreMiddleware(body)
|
||||
getRunningExpressApp().metricsProvider?.incrementCounter(FLOWISE_METRIC_COUNTERS.VECTORSTORE_UPSERT, {
|
||||
status: FLOWISE_COUNTER_STATUS.SUCCESS
|
||||
})
|
||||
return res.json(DocumentStoreDTO.fromEntity(apiResponse))
|
||||
} catch (error) {
|
||||
getRunningExpressApp().metricsProvider?.incrementCounter(FLOWISE_METRIC_COUNTERS.VECTORSTORE_UPSERT, {
|
||||
status: FLOWISE_COUNTER_STATUS.FAILURE
|
||||
})
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
@@ -327,7 +333,9 @@ const saveVectorStoreConfig = async (req: Request, res: Response, next: NextFunc
|
||||
throw new Error('Error: documentStoreController.saveVectorStoreConfig - body not provided!')
|
||||
}
|
||||
const body = req.body
|
||||
const apiResponse = await documentStoreService.saveVectorStoreConfig(body)
|
||||
const appDataSource = getRunningExpressApp().AppDataSource
|
||||
const componentNodes = getRunningExpressApp().nodesPool.componentNodes
|
||||
const apiResponse = await documentStoreService.saveVectorStoreConfig(appDataSource, componentNodes, body)
|
||||
return res.json(apiResponse)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
@@ -388,8 +396,14 @@ const upsertDocStoreMiddleware = async (req: Request, res: Response, next: NextF
|
||||
const body = req.body
|
||||
const files = (req.files as Express.Multer.File[]) || []
|
||||
const apiResponse = await documentStoreService.upsertDocStoreMiddleware(req.params.id, body, files)
|
||||
getRunningExpressApp().metricsProvider?.incrementCounter(FLOWISE_METRIC_COUNTERS.VECTORSTORE_UPSERT, {
|
||||
status: FLOWISE_COUNTER_STATUS.SUCCESS
|
||||
})
|
||||
return res.json(apiResponse)
|
||||
} catch (error) {
|
||||
getRunningExpressApp().metricsProvider?.incrementCounter(FLOWISE_METRIC_COUNTERS.VECTORSTORE_UPSERT, {
|
||||
status: FLOWISE_COUNTER_STATUS.FAILURE
|
||||
})
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
@@ -404,8 +418,14 @@ const refreshDocStoreMiddleware = async (req: Request, res: Response, next: Next
|
||||
}
|
||||
const body = req.body
|
||||
const apiResponse = await documentStoreService.refreshDocStoreMiddleware(req.params.id, body)
|
||||
getRunningExpressApp().metricsProvider?.incrementCounter(FLOWISE_METRIC_COUNTERS.VECTORSTORE_UPSERT, {
|
||||
status: FLOWISE_COUNTER_STATUS.SUCCESS
|
||||
})
|
||||
return res.json(apiResponse)
|
||||
} catch (error) {
|
||||
getRunningExpressApp().metricsProvider?.incrementCounter(FLOWISE_METRIC_COUNTERS.VECTORSTORE_UPSERT, {
|
||||
status: FLOWISE_COUNTER_STATUS.FAILURE
|
||||
})
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
@@ -470,7 +490,6 @@ export default {
|
||||
queryVectorStore,
|
||||
deleteVectorStoreFromStore,
|
||||
updateVectorStoreConfigOnly,
|
||||
getRateLimiterMiddleware,
|
||||
upsertDocStoreMiddleware,
|
||||
refreshDocStoreMiddleware,
|
||||
saveProcessingLoader,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Request, Response, NextFunction } from 'express'
|
||||
import { utilBuildChatflow } from '../../utils/buildChatflow'
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
import { getErrorMessage } from '../../errors/utils'
|
||||
import { MODE } from '../../Interface'
|
||||
|
||||
// Send input message and get prediction result (Internal)
|
||||
const createInternalPrediction = async (req: Request, res: Response, next: NextFunction) => {
|
||||
@@ -11,7 +12,7 @@ const createInternalPrediction = async (req: Request, res: Response, next: NextF
|
||||
return
|
||||
} else {
|
||||
const apiResponse = await utilBuildChatflow(req, true)
|
||||
return res.json(apiResponse)
|
||||
if (apiResponse) return res.json(apiResponse)
|
||||
}
|
||||
} catch (error) {
|
||||
next(error)
|
||||
@@ -22,6 +23,7 @@ const createInternalPrediction = async (req: Request, res: Response, next: NextF
|
||||
const createAndStreamInternalPrediction = async (req: Request, res: Response, next: NextFunction) => {
|
||||
const chatId = req.body.chatId
|
||||
const sseStreamer = getRunningExpressApp().sseStreamer
|
||||
|
||||
try {
|
||||
sseStreamer.addClient(chatId, res)
|
||||
res.setHeader('Content-Type', 'text/event-stream')
|
||||
@@ -30,6 +32,10 @@ const createAndStreamInternalPrediction = async (req: Request, res: Response, ne
|
||||
res.setHeader('X-Accel-Buffering', 'no') //nginx config: https://serverfault.com/a/801629
|
||||
res.flushHeaders()
|
||||
|
||||
if (process.env.MODE === MODE.QUEUE) {
|
||||
getRunningExpressApp().redisSubscriber.subscribe(chatId)
|
||||
}
|
||||
|
||||
const apiResponse = await utilBuildChatflow(req, true)
|
||||
sseStreamer.streamMetadataEvent(apiResponse.chatId, apiResponse)
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Request, Response, NextFunction } from 'express'
|
||||
import { getRateLimiter } from '../../utils/rateLimit'
|
||||
import { RateLimiterManager } from '../../utils/rateLimit'
|
||||
import chatflowsService from '../../services/chatflows'
|
||||
import logger from '../../utils/logger'
|
||||
import predictionsServices from '../../services/predictions'
|
||||
@@ -8,6 +8,7 @@ import { StatusCodes } from 'http-status-codes'
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { getErrorMessage } from '../../errors/utils'
|
||||
import { MODE } from '../../Interface'
|
||||
|
||||
// Send input message and get prediction result (External)
|
||||
const createPrediction = async (req: Request, res: Response, next: NextFunction) => {
|
||||
@@ -55,6 +56,7 @@ const createPrediction = async (req: Request, res: Response, next: NextFunction)
|
||||
const isStreamingRequested = req.body.streaming === 'true' || req.body.streaming === true
|
||||
if (streamable?.isStreaming && isStreamingRequested) {
|
||||
const sseStreamer = getRunningExpressApp().sseStreamer
|
||||
|
||||
let chatId = req.body.chatId
|
||||
if (!req.body.chatId) {
|
||||
chatId = req.body.chatId ?? req.body.overrideConfig?.sessionId ?? uuidv4()
|
||||
@@ -68,6 +70,10 @@ const createPrediction = async (req: Request, res: Response, next: NextFunction)
|
||||
res.setHeader('X-Accel-Buffering', 'no') //nginx config: https://serverfault.com/a/801629
|
||||
res.flushHeaders()
|
||||
|
||||
if (process.env.MODE === MODE.QUEUE) {
|
||||
getRunningExpressApp().redisSubscriber.subscribe(chatId)
|
||||
}
|
||||
|
||||
const apiResponse = await predictionsServices.buildChatflow(req)
|
||||
sseStreamer.streamMetadataEvent(apiResponse.chatId, apiResponse)
|
||||
} catch (error) {
|
||||
@@ -96,7 +102,7 @@ const createPrediction = async (req: Request, res: Response, next: NextFunction)
|
||||
|
||||
const getRateLimiterMiddleware = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
return getRateLimiter(req, res, next)
|
||||
return RateLimiterManager.getInstance().getRateLimiter()(req, res, next)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Request, Response, NextFunction } from 'express'
|
||||
import vectorsService from '../../services/vectors'
|
||||
import { getRateLimiter } from '../../utils/rateLimit'
|
||||
import { RateLimiterManager } from '../../utils/rateLimit'
|
||||
|
||||
const getRateLimiterMiddleware = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
return getRateLimiter(req, res, next)
|
||||
return RateLimiterManager.getInstance().getRateLimiter()(req, res, next)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user