Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
34 changes: 30 additions & 4 deletions Installer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ SQL command timeout constants (in seconds)
private const int ShortTimeoutSeconds = 60; // Quick operations (cleanup, queries)
private const int MediumTimeoutSeconds = 120; // Dependency installation
private const int LongTimeoutSeconds = 300; // SQL file execution (5 minutes)
private const int UpgradeTimeoutSeconds = 3600; // Upgrade data migrations (1 hour, large tables)

/*
Exit codes for granular error reporting
Expand All @@ -117,6 +118,7 @@ private static class ExitCodes
public const int VersionCheckFailed = 5;
public const int SqlFilesNotFound = 6;
public const int UninstallFailed = 7;
public const int UpgradesFailed = 8;
}

static async Task<int> Main(string[] args)
Expand Down Expand Up @@ -523,8 +525,9 @@ Search current directory and up to 5 parent directories
string fileName = Path.GetFileName(f);
if (!SqlFileNamePattern.IsMatch(fileName))
return false;
/*Exclude test and troubleshooting scripts from main install*/
if (fileName.StartsWith("97_", StringComparison.Ordinal) ||
/*Exclude uninstall, test, and troubleshooting scripts from main install*/
if (fileName.StartsWith("00_", StringComparison.Ordinal) ||
fileName.StartsWith("97_", StringComparison.Ordinal) ||
fileName.StartsWith("99_", StringComparison.Ordinal))
return false;
return true;
Expand Down Expand Up @@ -699,6 +702,21 @@ Traces are server-level and persist after database drops

Console.WriteLine();
Console.WriteLine($"Upgrades complete: {upgradeSuccessCount} succeeded, {upgradeFailureCount} failed");

/*Abort if any upgrade scripts failed — proceeding would reinstall over a partially-upgraded database*/
if (upgradeFailureCount > 0)
{
Console.WriteLine();
Console.WriteLine("================================================================================");
Console.WriteLine("Installation aborted: upgrade scripts must succeed before installation can proceed.");
Console.WriteLine("Fix the errors above and re-run the installer.");
Console.WriteLine("================================================================================");
if (!automatedMode)
{
WaitForExit();
}
return ExitCodes.UpgradesFailed;
}
}
else
{
Expand Down Expand Up @@ -1332,7 +1350,15 @@ FROM PerformanceMonitor.config.installation_history
return version.ToString();
}

return null;
/*
Fallback: database and history table exist but no SUCCESS rows.
This can happen if a prior GUI install didn't write history (#538/#539).
Return "1.0.0" so all idempotent upgrade scripts are attempted
rather than treating this as a fresh install (which would drop the database).
*/
Console.WriteLine("Warning: PerformanceMonitor database exists but installation_history has no records.");
Console.WriteLine("Treating as v1.0.0 to apply all available upgrades.");
return "1.0.0";
}
}
catch (SqlException ex)
Expand Down Expand Up @@ -1480,7 +1506,7 @@ Execute an upgrade folder

using (var cmd = new SqlCommand(trimmedBatch, connection))
{
cmd.CommandTimeout = LongTimeoutSeconds;
cmd.CommandTimeout = UpgradeTimeoutSeconds;
try
{
await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);
Expand Down
10 changes: 10 additions & 0 deletions InstallerGui/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,16 @@ private async void Install_Click(object sender, RoutedEventArgs e)
upgradeFailure == 0 ? "Success" : "Warning");
LogMessage("", "Info");
}

/*Abort if any upgrade scripts failed — proceeding would reinstall over a partially-upgraded database*/
if (upgradeFailure > 0)
{
LogMessage("", "Info");
LogMessage("Installation aborted: upgrade scripts must succeed before installation can proceed.", "Error");
LogMessage("Fix the errors above and re-run the installer.", "Error");
SetUIState(installing: false);
return;
}
}

/*
Expand Down
15 changes: 11 additions & 4 deletions InstallerGui/Services/InstallationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,9 @@ public static (string? SqlDirectory, string? MonitorRootDirectory, List<string>
/*Match numbered SQL files but exclude 97 (tests) and 99 (troubleshooting)*/
if (!SqlFilePattern.IsMatch(fileName))
return false;
/*Exclude test and troubleshooting scripts from main install*/
if (fileName.StartsWith("97_", StringComparison.Ordinal) ||
/*Exclude uninstall, test, and troubleshooting scripts from main install*/
if (fileName.StartsWith("00_", StringComparison.Ordinal) ||
fileName.StartsWith("97_", StringComparison.Ordinal) ||
fileName.StartsWith("99_", StringComparison.Ordinal))
return false;
return true;
Expand Down Expand Up @@ -1113,7 +1114,13 @@ FROM PerformanceMonitor.config.installation_history
return version.ToString();
}

return null;
/*
Fallback: database and history table exist but no SUCCESS rows.
This can happen if a prior GUI install didn't write history (#538/#539).
Return "1.0.0" so all idempotent upgrade scripts are attempted
rather than treating this as a fresh install (which would drop the database).
*/
return "1.0.0";
}
catch (SqlException)
{
Expand Down Expand Up @@ -1272,7 +1279,7 @@ Parse versions and filter to only applicable upgrades
continue;

using var cmd = new SqlCommand(trimmedBatch, connection);
cmd.CommandTimeout = 300;
cmd.CommandTimeout = 3600; /*1 hour — upgrade migrations on large tables need extended time*/

try
{
Expand Down
Loading