Fix upload 'processing' status

This commit is contained in:
inubimambo
2025-07-06 23:39:32 +08:00
parent f5f5189fa0
commit b2b12a4197
3 changed files with 335 additions and 61 deletions

182
server.js
View File

@@ -634,7 +634,7 @@ app.post('/upload', requireAuth, upload.single('noteFile'), async (req, res) =>
console.log('Response sent, starting async processing...');
// Process document asynchronously
processDocumentAsync(fileInfo, req.session.userId);
processDocumentAsync(fileInfo, req.session.userId, req.session);
} catch (error) {
console.error('Upload error:', error);
@@ -647,13 +647,24 @@ app.post('/upload', requireAuth, upload.single('noteFile'), async (req, res) =>
});
// Async function to process document and upsert to Flowise using FormData
async function processDocumentAsync(fileInfo, userId) {
async function processDocumentAsync(fileInfo, userId, session) {
try {
console.log('=== DOCUMENT PROCESSING START (FormData) ===');
console.log(`Starting document processing for: ${fileInfo.originalName}`);
console.log(`File path: ${fileInfo.path}`);
console.log(`File size: ${fileInfo.size} bytes`);
console.log(`User ID: ${userId}`);
console.log(`Session ID in processing: ${session.id || 'undefined'}`);
// Find the file in the session to update it by reference
const sessionFile = session.uploadedFiles.find(f => f.id === fileInfo.id);
if (!sessionFile) {
console.error('File not found in session:', fileInfo.id);
console.error('Available files in session:', session.uploadedFiles.map(f => ({ id: f.id, name: f.originalName })));
return;
}
console.log('Found session file for update:', { id: sessionFile.id, name: sessionFile.originalName, currentStatus: sessionFile.status });
// Create document metadata
const documentMetadata = {
@@ -668,7 +679,7 @@ async function processDocumentAsync(fileInfo, userId) {
console.log('Document metadata:', documentMetadata);
// Initialize processing result
fileInfo.processingResult = {
sessionFile.processingResult = {
totalChunks: 1, // FormData uploads are single operations
successfulChunks: 0,
failedChunks: 0,
@@ -683,41 +694,71 @@ async function processDocumentAsync(fileInfo, userId) {
console.log('FormData upsert result:', upsertResult);
// Update file info with processing results
fileInfo.status = upsertResult.success ? 'processed' : 'failed';
fileInfo.processingProgress = null; // Clear progress when done
fileInfo.processingResult = {
// Update session file with processing results
sessionFile.status = upsertResult.success ? 'processed' : 'failed';
sessionFile.processingProgress = null; // Clear progress when done
sessionFile.processingResult = {
totalChunks: upsertResult.totalChunks,
successfulChunks: upsertResult.successfulChunks,
failedChunks: upsertResult.failedChunks,
processedAt: new Date().toISOString(),
startedAt: fileInfo.processingResult.startedAt,
duration: Date.now() - new Date(fileInfo.processingResult.startedAt).getTime(),
startedAt: sessionFile.processingResult.startedAt,
duration: Date.now() - new Date(sessionFile.processingResult.startedAt).getTime(),
method: 'formdata'
};
if (upsertResult.errors.length > 0) {
fileInfo.processingErrors = upsertResult.errors;
console.log(`Processing errors for ${fileInfo.originalName}:`, upsertResult.errors);
sessionFile.processingErrors = upsertResult.errors;
console.log(`Processing errors for ${sessionFile.originalName}:`, upsertResult.errors);
}
console.log(`Document processing completed for: ${fileInfo.originalName}`);
console.log(`Document processing completed for: ${sessionFile.originalName}`);
console.log(`Result: FormData upload ${upsertResult.success ? 'successful' : 'failed'}`);
console.log(`Updated session file status to: ${sessionFile.status}`);
// Verify the session file was updated
console.log('Session file after update:', { id: sessionFile.id, name: sessionFile.originalName, status: sessionFile.status });
console.log('All session files after update:', session.uploadedFiles.map(f => ({ id: f.id, name: f.originalName, status: f.status })));
// Force session save since we modified it in an async context
session.save((err) => {
if (err) {
console.error('Error saving session after document processing:', err);
} else {
console.log('Session saved successfully after document processing');
}
});
// Log final upsert verification
console.log('Final FormData upsert verification:', {
documentStore: `${FLOWISE_BASE_URL}/api/v1/document-store/${FLOWISE_DOCUMENT_STORE_ID}`,
documentId: fileInfo.id,
fileName: fileInfo.originalName,
success: upsertResult.success
documentId: sessionFile.id,
fileName: sessionFile.originalName,
success: upsertResult.success,
finalStatus: sessionFile.status
});
} catch (error) {
console.error(`Error processing document ${fileInfo.originalName}:`, error);
fileInfo.status = 'failed';
fileInfo.processingError = error.message;
fileInfo.processingResult = fileInfo.processingResult || {};
fileInfo.processingResult.failedAt = new Date().toISOString();
// Find the file in the session to update it with error
const sessionFile = session.uploadedFiles.find(f => f.id === fileInfo.id);
if (sessionFile) {
sessionFile.status = 'failed';
sessionFile.processingError = error.message;
sessionFile.processingResult = sessionFile.processingResult || {};
sessionFile.processingResult.failedAt = new Date().toISOString();
console.log(`Updated session file status to: ${sessionFile.status} due to error`);
// Force session save since we modified it in an async context
session.save((err) => {
if (err) {
console.error('Error saving session after processing error:', err);
} else {
console.log('Session saved successfully after processing error');
}
});
}
}
}
@@ -806,34 +847,115 @@ app.post('/api/revise', requireAuth, async (req, res) => {
});
app.get('/chat', requireAuth, (req, res) => {
// Initialize chat history if it doesn't exist
if (!req.session.chatHistory) {
req.session.chatHistory = [];
}
res.render('chat', {
title: 'Chat with EduCat AI'
title: 'Chat with EduCat AI',
chatHistory: req.session.chatHistory
});
});
app.post('/api/chat', requireAuth, async (req, res) => {
try {
const { message, history } = req.body;
const { message } = req.body;
// Call Flowise API for chat
// Initialize chat history in session if it doesn't exist
if (!req.session.chatHistory) {
req.session.chatHistory = [];
}
console.log('Chat message received:', message);
console.log('Current chat history length:', req.session.chatHistory.length);
// Call Flowise API for chat with session history
const response = await axios.post(`${FLOWISE_API_URL}/${FLOWISE_CHATFLOW_ID}`, {
question: message,
history: history || []
history: req.session.chatHistory
});
const aiResponse = response.data.text || response.data.answer || 'No response received';
// Add the conversation to session history
req.session.chatHistory.push({
human: message,
ai: aiResponse
});
// Save session explicitly since we modified it
req.session.save((err) => {
if (err) {
console.error('Error saving chat session:', err);
}
});
console.log('Updated chat history length:', req.session.chatHistory.length);
res.json({
success: true,
response: response.data.text || response.data.answer || 'No response received'
response: aiResponse
});
} catch (error) {
console.error('Chat error:', error);
res.status(500).json({
success: false,
error: 'Failed to get chat response',
details: error.message
});
}
});
// Get chat history from session
app.get('/api/chat/history', requireAuth, (req, res) => {
try {
const chatHistory = req.session.chatHistory || [];
console.log('Chat history requested, returning', chatHistory.length, 'messages');
res.json({
success: true,
history: chatHistory
});
} catch (error) {
console.error('Error getting chat history:', error);
res.status(500).json({
success: false,
error: 'Failed to get chat history',
details: error.message
});
}
});
// Clear chat history
app.delete('/api/chat/history', requireAuth, (req, res) => {
try {
req.session.chatHistory = [];
req.session.save((err) => {
if (err) {
console.error('Error clearing chat session:', err);
return res.status(500).json({
success: false,
error: 'Failed to clear chat history'
});
}
console.log('Chat history cleared for user:', req.session.userId);
res.json({
success: true,
message: 'Chat history cleared'
});
});
} catch (error) {
console.error('Error clearing chat history:', error);
res.status(500).json({
success: false,
error: 'Failed to clear chat history',
details: error.message
});
}
});
app.get('/dashboard', requireAuth, (req, res) => {
const files = req.session.uploadedFiles || [];
res.render('dashboard', {
@@ -921,6 +1043,12 @@ app.get('/api/files/:fileId/status', requireAuth, async (req, res) => {
const files = req.session.uploadedFiles || [];
const file = files.find(f => f.id === fileId);
console.log(`Status requested for file ${fileId}`);
console.log(`Session ID: ${req.session.id || req.sessionID}`);
console.log(`User ID: ${req.session.userId}`);
console.log(`Files in session:`, files.map(f => ({ id: f.id, name: f.originalName, status: f.status })));
console.log(`Found file:`, file ? { id: file.id, name: file.originalName, status: file.status } : 'Not found');
if (!file) {
return res.status(404).json({ success: false, error: 'File not found' });
}
@@ -969,7 +1097,7 @@ app.post('/api/files/:fileId/retry', requireAuth, async (req, res) => {
file.processingErrors = null;
// Start processing asynchronously
processDocumentAsync(file, req.session.userId);
processDocumentAsync(file, req.session.userId, req.session);
res.json({
success: true,
@@ -989,6 +1117,8 @@ app.post('/api/files/:fileId/retry', requireAuth, async (req, res) => {
app.get('/api/files/status/all', requireAuth, async (req, res) => {
try {
const files = req.session.uploadedFiles || [];
console.log('Status check requested for session files:', files.map(f => ({ id: f.id, name: f.originalName, status: f.status })));
const statusSummary = files.map(file => ({
id: file.id,
originalName: file.originalName,
@@ -1010,6 +1140,8 @@ app.get('/api/files/status/all', requireAuth, async (req, res) => {
files: statusSummary
};
console.log('Returning status summary:', summary);
res.json({
success: true,
summary: summary