Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/backend/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME = ""
APP_ENV = "dev"

# Basic application logging (default: INFO level)
AZURE_BASIC_LOGGING_LEVEL=INFO
AZURE_BASIC_LOGGING_LEVEL=DEBUG
# Azure package logging (default: WARNING level to suppress INFO)
AZURE_PACKAGE_LOGGING_LEVEL=WARNING
AZURE_PACKAGE_LOGGING_LEVEL=DEBUG
# Comma-separated list of specific logger names to configure (default: empty - no custom loggers)
# Example: AZURE_LOGGING_PACKAGES=azure.identity.aio._internal,azure.monitor.opentelemetry.exporter.export._base
AZURE_LOGGING_PACKAGES=
18 changes: 11 additions & 7 deletions src/backend/common/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import os

from azure.identity.aio import ClientSecretCredential
from azure.identity.aio import DefaultAzureCredential as AioDefaultAzureCredential
from azure.identity.aio import ManagedIdentityCredential as AioManagedIdentityCredential

from helper.azure_credential_utils import get_azure_credential

Expand Down Expand Up @@ -54,13 +56,15 @@ def __init__(self):

def get_azure_credentials(self):
"""Retrieve Azure credentials, either from environment variables or managed identity."""
if all([self.azure_tenant_id, self.azure_client_id, self.azure_client_secret]):
return ClientSecretCredential(
tenant_id=self.azure_tenant_id,
client_id=self.azure_client_id,
client_secret=self.azure_client_secret,
)
return self.__azure_credentials
if os.getenv("APP_ENV", "prod").lower() == "dev":
if all([self.azure_tenant_id, self.azure_client_id, self.azure_client_secret]):
Comment thread
Shreyas-Microsoft marked this conversation as resolved.
Outdated
return ClientSecretCredential(
tenant_id=self.azure_tenant_id,
client_id=self.azure_client_id,
client_secret=self.azure_client_secret,
)
return AioDefaultAzureCredential()
return AioManagedIdentityCredential(client_id=self.azure_client_id)
Comment thread
Shreyas-Microsoft marked this conversation as resolved.
Outdated
Comment thread
Shreyas-Microsoft marked this conversation as resolved.
Outdated


app_config = Config()
Expand Down
7 changes: 5 additions & 2 deletions src/backend/sql_agents/convert_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ async def convert_script(

# orchestrate the chat
current_migration = "No migration"
while True:
is_complete: bool = False
while not is_complete:
await comms_manager.group_chat.add_chat_message(
ChatMessageContent(role=AuthorRole.USER, content=source_script)
)
Expand Down Expand Up @@ -273,7 +274,9 @@ async def convert_script(
break

if comms_manager.group_chat.is_complete:
break
is_complete = True
Comment thread
Shreyas-Microsoft marked this conversation as resolved.
Dismissed

break

Comment thread
Shreyas-Microsoft marked this conversation as resolved.
Outdated
migrated_query = current_migration

Expand Down
3 changes: 3 additions & 0 deletions src/frontend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
dist
.git
111 changes: 22 additions & 89 deletions src/frontend/src/pages/modernizationPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { Light as SyntaxHighlighter } from "react-syntax-highlighter"
import { vs } from "react-syntax-highlighter/dist/esm/styles/hljs"
import sql from "react-syntax-highlighter/dist/cjs/languages/hljs/sql"
import { useNavigate, useParams } from "react-router-dom"
import { useState, useEffect, useCallback } from "react"
import { useState, useEffect, useCallback, useRef } from "react"
Comment thread
Shreyas-Microsoft marked this conversation as resolved.
Dismissed
Comment thread
Shreyas-Microsoft marked this conversation as resolved.
Outdated
import { getApiUrl, headerBuilder } from '../api/config';
import BatchHistoryPanel from "../components/batchHistoryPanel"
import PanelRight from "../components/Panels/PanelRight";
Expand Down Expand Up @@ -497,10 +497,11 @@ const ModernizationPage = () => {
const [fileId, setFileId] = React.useState<string>("");
const [expandedSections, setExpandedSections] = React.useState<string[]>([]);
const [allFilesCompleted, setAllFilesCompleted] = useState(false);
const [progressPercentage, setProgressPercentage] = useState(0);
Comment thread
Shreyas-Microsoft marked this conversation as resolved.
Dismissed
const [isZipButtonDisabled, setIsZipButtonDisabled] = useState(true);
const [fileLoading, setFileLoading] = useState(false);
const [lastActivityTime, setLastActivityTime] = useState<number>(Date.now());
const [pageLoadTime] = useState<number>(Date.now());
//const [pageLoadTime] = useState<number>(Date.now());
Comment thread
Shreyas-Microsoft marked this conversation as resolved.

// Fetch file content when a file is selected
useEffect(() => {
Expand All @@ -514,18 +515,9 @@ const ModernizationPage = () => {
if (!selectedFile || !selectedFile.translatedCode) {
setFileLoading(true);
const newFileUpdate = await fetchFileFromAPI(selectedFile?.fileId || "");
setFiles((prevFiles) =>
prevFiles.map((file) =>
file.fileId === selectedFile?.fileId
? {
...file,
code: newFileUpdate.content,
translatedCode: newFileUpdate.translated_content,
}
: file
)
);
setFileLoading(false);
Comment thread
Shreyas-Microsoft marked this conversation as resolved.
} else {

}

} catch (err) {
Expand Down Expand Up @@ -603,18 +595,9 @@ const ModernizationPage = () => {
fetchBatchData(batchId);
}, [batchId]);

// Listen for startProcessing completion and navigate to batch view
useEffect(() => {
if (batchState && !batchState.loading && batchState.status === "Processing completed") {
console.log("Start processing API completed successfully - processing is done!");

// Check if we have the response with batch_id that matches current batchId
if (batchState.batchId === batchId) {
console.log("Processing completed for current batch, navigating to batch view page");
navigate(`/batch-view/${batchId}`);
}
}
}, [batchState.loading, batchState.status, batchState.batchId, batchId, navigate]);
// Do NOT navigate based on Redux startProcessing state.
// The start-processing API may return 504 even if backend work is ongoing.
// Navigation is ONLY triggered by actual file completion via WebSocket/polling.

const handleDownloadZip = async () => {
if (batchId) {
Expand Down Expand Up @@ -811,37 +794,17 @@ const ModernizationPage = () => {
const latestBatch = await fetchBatchSummary(batchId!);
setBatchSummary(latestBatch);

// Check if all files are in terminal states OR if the batch itself is marked as completed
// Only complete when all files reach terminal states.
const allFilesDone = latestBatch.files.every(file =>
["completed", "failed", "error"].includes(file.status?.toLowerCase() || "")
);

// Also check if batch status indicates completion (for cases where some files remain queued)
const batchCompleted = latestBatch.status?.toLowerCase() === "completed" ||
latestBatch.status?.toLowerCase() === "failed";

// Special handling for stuck processing files - if no completed files and long time passed
const hasProcessingFiles = latestBatch.files.some(file =>
file.status?.toLowerCase() === "in_process"
);
const hasCompletedFiles = latestBatch.files.some(file =>
file.status?.toLowerCase() === "completed"
);
const timeSinceLastActivity = Date.now() - lastActivityTime;
const likelyStuckProcessing = hasProcessingFiles &&
!hasCompletedFiles &&
timeSinceLastActivity > 60000; // 60 seconds of no activity

// Consider processing done if either all files are terminal OR batch is marked complete OR files appear stuck
const processingComplete = allFilesDone || batchCompleted || likelyStuckProcessing;

const processingComplete = allFilesDone;

Comment thread
Shreyas-Microsoft marked this conversation as resolved.
if (processingComplete) {
console.log("Processing complete detected:", {
allFilesDone,
batchCompleted,
likelyStuckProcessing,
batchStatus: latestBatch.status,
timeSinceActivity: timeSinceLastActivity
batchStatus: latestBatch.status
});
setAllFilesCompleted(true);
const hasUsableFile = latestBatch.files.some(file =>
Expand All @@ -868,8 +831,8 @@ const ModernizationPage = () => {
return updated;
});

// Navigate to batch view page when processing is complete
console.log("Processing complete (either all files done or batch completed), navigating to batch view page");
// Navigate only after all files have reached terminal states.
console.log("Processing complete (all files done), navigating to batch view page");
navigate(`/batch-view/${batchId}`);
}
} catch (err) {
Expand Down Expand Up @@ -950,17 +913,8 @@ useEffect(() => {
file.id === "summary" || // skip summary
["completed", "failed", "error"].includes(file.status?.toLowerCase() || "")
);

// Also check if we have at least one completed file and no files currently processing
const hasCompletedFiles = files.some(file =>
file.id !== "summary" && file.status === "completed"
);
const hasProcessingFiles = files.some(file =>
file.id !== "summary" && file.status === "in_process"
);

// Consider done if all terminal OR (has completed files and no processing files)
const effectivelyDone = areAllFilesTerminal || (hasCompletedFiles && !hasProcessingFiles);

const effectivelyDone = areAllFilesTerminal;

if (files.length > 1 && effectivelyDone && !allFilesCompleted) {
console.log("Files processing appears complete, checking batch status");
Expand Down Expand Up @@ -1013,55 +967,34 @@ useEffect(() => {
};
}, [handleWebSocketMessage]);

// Set a timeout for initial loading - if still loading after 30 seconds, show a warning message
// Set a timeout for initial loading - if no progress after 30 seconds, show error
useEffect(() => {
const loadingTimeout = setTimeout(() => {
if (showLoading) {
if (progressPercentage < 5 && showLoading) {
setLoadingError('Processing is taking longer than expected. You can continue waiting or try again later.');
}
Comment thread
Shreyas-Microsoft marked this conversation as resolved.
Comment thread
Shreyas-Microsoft marked this conversation as resolved.
}, 30000);

return () => clearTimeout(loadingTimeout);
}, [showLoading]);
}, [progressPercentage, showLoading]);

// Add timeout mechanism to navigate if no activity for 30 seconds
// Poll summary status during inactivity, but do not force completion/navigation by timeout.
useEffect(() => {
const checkInactivity = setInterval(() => {
const timeSinceLastActivity = Date.now() - lastActivityTime;
const hasCompletedFiles = files.some(file =>
file.id !== "summary" && file.status === "completed"
);
const hasProcessingFiles = files.some(file =>
file.id !== "summary" && file.status === "in_process"
);
const nonSummaryFiles = files.filter(f => f.id !== "summary");

// If we have completed files and no activity for 30 seconds, check if we should navigate
// If we have completed files and no activity for 30 seconds, refresh status.
if (hasCompletedFiles && timeSinceLastActivity > 30000 && !allFilesCompleted) {
console.log("No activity for 30 seconds with completed files, checking final status");
updateSummaryStatus();
}

// Special case: If only harmful files that are stuck in processing for 60+ seconds
if (nonSummaryFiles.length > 0 &&
hasProcessingFiles &&
!hasCompletedFiles &&
timeSinceLastActivity > 60000 &&
!allFilesCompleted) {
console.log("Files stuck in processing for 60+ seconds, likely failed - checking batch status");
updateSummaryStatus();
}

// Ultimate fallback: If on page for 2+ minutes with no completion, force navigation
const timeSincePageLoad = Date.now() - pageLoadTime;
if (timeSincePageLoad > 120000 && !allFilesCompleted && nonSummaryFiles.length > 0) {
console.log("Page loaded for 2+ minutes without completion, forcing navigation to batch view");
navigate(`/batch-view/${batchId}`);
}
}, 5000); // Check every 5 seconds

return () => clearInterval(checkInactivity);
}, [lastActivityTime, files, allFilesCompleted, updateSummaryStatus, pageLoadTime, navigate, batchId]);
}, [lastActivityTime, files, allFilesCompleted, updateSummaryStatus, navigate, batchId]);


useEffect(() => {
Expand Down
Loading