🔀 fix: Remove use of Mongo Transactions (#2525)

* fix: remove use of transactions

* fix: remove use of transactions

* refactor(actions): perform OpenAI API operation first, before attempting database updates
This commit is contained in:
Danny Avila 2024-04-24 16:04:46 -04:00 committed by GitHub
parent 667f5f91fe
commit bde6bb0152
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 14 additions and 45 deletions

View file

@ -5,7 +5,6 @@ const { actionDelimiter, EModelEndpoint } = require('librechat-data-provider');
const { initializeClient } = require('~/server/services/Endpoints/assistants'); const { initializeClient } = require('~/server/services/Endpoints/assistants');
const { updateAction, getActions, deleteAction } = require('~/models/Action'); const { updateAction, getActions, deleteAction } = require('~/models/Action');
const { updateAssistant, getAssistant } = require('~/models/Assistant'); const { updateAssistant, getAssistant } = require('~/models/Assistant');
const { withSession } = require('~/server/utils');
const { logger } = require('~/config'); const { logger } = require('~/config');
const router = express.Router(); const router = express.Router();
@ -109,10 +108,10 @@ router.post('/:assistant_id', async (req, res) => {
})), })),
); );
let updatedAssistant = await openai.beta.assistants.update(assistant_id, { tools });
const promises = []; const promises = [];
promises.push( promises.push(
withSession( updateAssistant(
updateAssistant,
{ assistant_id }, { assistant_id },
{ {
actions, actions,
@ -120,29 +119,26 @@ router.post('/:assistant_id', async (req, res) => {
}, },
), ),
); );
promises.push(openai.beta.assistants.update(assistant_id, { tools })); promises.push(updateAction({ action_id }, { metadata, assistant_id, user: req.user.id }));
promises.push(
withSession(updateAction, { action_id }, { metadata, assistant_id, user: req.user.id }),
);
/** @type {[AssistantDocument, Assistant, Action]} */ /** @type {[AssistantDocument, Action]} */
const resolved = await Promise.all(promises); let [assistantDocument, updatedAction] = await Promise.all(promises);
const sensitiveFields = ['api_key', 'oauth_client_id', 'oauth_client_secret']; const sensitiveFields = ['api_key', 'oauth_client_id', 'oauth_client_secret'];
for (let field of sensitiveFields) { for (let field of sensitiveFields) {
if (resolved[2].metadata[field]) { if (updatedAction.metadata[field]) {
delete resolved[2].metadata[field]; delete updatedAction.metadata[field];
} }
} }
/* Map Azure OpenAI model to the assistant as defined by config */ /* Map Azure OpenAI model to the assistant as defined by config */
if (req.app.locals[EModelEndpoint.azureOpenAI]?.assistants) { if (req.app.locals[EModelEndpoint.azureOpenAI]?.assistants) {
resolved[1] = { updatedAssistant = {
...resolved[1], ...updatedAssistant,
model: req.body.model, model: req.body.model,
}; };
} }
res.json(resolved); res.json([assistantDocument, updatedAssistant, updatedAction]);
} catch (error) { } catch (error) {
const message = 'Trouble updating the Assistant Action'; const message = 'Trouble updating the Assistant Action';
logger.error(message, error); logger.error(message, error);
@ -190,10 +186,11 @@ router.delete('/:assistant_id/:action_id/:model', async (req, res) => {
(tool) => !(tool.function && tool.function.name.includes(domain)), (tool) => !(tool.function && tool.function.name.includes(domain)),
); );
await openai.beta.assistants.update(assistant_id, { tools: updatedTools });
const promises = []; const promises = [];
promises.push( promises.push(
withSession( updateAssistant(
updateAssistant,
{ assistant_id }, { assistant_id },
{ {
actions: updatedActions, actions: updatedActions,
@ -201,8 +198,7 @@ router.delete('/:assistant_id/:action_id/:model', async (req, res) => {
}, },
), ),
); );
promises.push(openai.beta.assistants.update(assistant_id, { tools: updatedTools })); promises.push(deleteAction({ action_id }));
promises.push(withSession(deleteAction, { action_id }));
await Promise.all(promises); await Promise.all(promises);
res.status(200).json({ message: 'Action deleted successfully' }); res.status(200).json({ message: 'Action deleted successfully' });

View file

@ -5,7 +5,6 @@ const handleText = require('./handleText');
const cryptoUtils = require('./crypto'); const cryptoUtils = require('./crypto');
const citations = require('./citations'); const citations = require('./citations');
const sendEmail = require('./sendEmail'); const sendEmail = require('./sendEmail');
const mongoose = require('./mongoose');
const queue = require('./queue'); const queue = require('./queue');
const files = require('./files'); const files = require('./files');
const math = require('./math'); const math = require('./math');
@ -15,7 +14,6 @@ module.exports = {
...cryptoUtils, ...cryptoUtils,
...handleText, ...handleText,
...citations, ...citations,
...mongoose,
countTokens, countTokens,
removePorts, removePorts,
sendEmail, sendEmail,

View file

@ -1,25 +0,0 @@
const mongoose = require('mongoose');
/**
* Executes a database operation within a session.
* @param {() => Promise<any>} method - The method to execute. This method must accept a session as its first argument.
* @param {...any} args - Additional arguments to pass to the method.
* @returns {Promise<any>} - The result of the executed method.
*/
async function withSession(method, ...args) {
const session = await mongoose.startSession();
session.startTransaction();
try {
const result = await method(...args, session);
await session.commitTransaction();
return result;
} catch (error) {
if (session.inTransaction()) {
await session.abortTransaction();
}
throw error;
} finally {
await session.endSession();
}
}
module.exports = { withSession };