Skip to content

Commit

Permalink
Fix server/compiler paths being incorrect for custom OD installations
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyberboss committed Nov 28, 2024
1 parent e7447d1 commit 2869eaf
Showing 1 changed file with 86 additions and 76 deletions.
162 changes: 86 additions & 76 deletions src/Tgstation.Server.Host/Components/Engine/EngineManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -412,110 +412,120 @@ async ValueTask<EngineExecutableLock> AssertAndLockVersion(
EngineExecutableLock installLock;
bool installedOrInstalling;

var potentialInstallation = await engineInstaller.CreateInstallation(
version,
ioManager.ResolvePath(version.ToString()),
ourTcs.Task,
cancellationToken);

lock (installedVersions)
// loop is because of the race condition with potentialInstallation, installedVersions, and CustomIteration selection
while (true)
{
if (customVersionStream != null)
lock (installedVersions)
{
var customInstallationNumber = 1;
do
if (customVersionStream != null)
{
version.CustomIteration = customInstallationNumber++;
var customInstallationNumber = 1;
do
{
version.CustomIteration = customInstallationNumber++;
}
while (installedVersions.ContainsKey(version));
}
while (installedVersions.ContainsKey(version));
}

installedOrInstalling = installedVersions.TryGetValue(version, out var installationContainerNullable);
ReferenceCountingContainer<IEngineInstallation, EngineExecutableLock> installationContainer;
if (!installedOrInstalling)
{
if (!allowInstallation)
throw new InvalidOperationException($"Engine version {version} not installed!");

installationContainer = AddInstallationContainer(potentialInstallation);
}
else
installationContainer = installationContainerNullable!;

installation = installationContainer.Instance;
installLock = installationContainer.AddReference();
}
var potentialInstallation = await engineInstaller.CreateInstallation(
version,
ioManager.ResolvePath(version.ToString()),
ourTcs.Task,
cancellationToken);

var deploymentPipelineProcesses = !neededForLock;
try
{
if (installedOrInstalling)
lock (installedVersions)
{
progressReporter.StageName = "Waiting for existing installation job...";
if (customVersionStream != null && installedVersions.ContainsKey(version))
continue;

if (neededForLock && !installation.InstallationTask.IsCompleted)
logger.LogWarning("The required engine version ({version}) is not readily available! We will have to wait for it to install.", version);
installedOrInstalling = installedVersions.TryGetValue(version, out var installationContainerNullable);
ReferenceCountingContainer<IEngineInstallation, EngineExecutableLock> installationContainer;
if (!installedOrInstalling)
{
if (!allowInstallation)
throw new InvalidOperationException($"Engine version {version} not installed!");

await installation.InstallationTask.WaitAsync(cancellationToken);
return installLock;
installationContainer = AddInstallationContainer(potentialInstallation);
}
else
installationContainer = installationContainerNullable!;

installation = installationContainer.Instance;
installLock = installationContainer.AddReference();
}

// okay up to us to install it then
string? installPath = null;
var deploymentPipelineProcesses = !neededForLock;
try
{
if (customVersionStream != null)
logger.LogInformation("Installing custom engine version as {version}...", version);
else if (neededForLock)
if (installedOrInstalling)
{
if (version.CustomIteration.HasValue)
throw new JobException(ErrorCode.EngineNonExistentCustomVersion);
progressReporter.StageName = "Waiting for existing installation job...";

if (neededForLock && !installation.InstallationTask.IsCompleted)
logger.LogWarning("The required engine version ({version}) is not readily available! We will have to wait for it to install.", version);

logger.LogWarning("The required engine version ({version}) is not readily available! We will have to install it.", version);
await installation.InstallationTask.WaitAsync(cancellationToken);
return installLock;
}
else
logger.LogInformation("Requested engine version {version} not currently installed. Doing so now...", version);

progressReporter.StageName = "Running event";
// okay up to us to install it then
string? installPath = null;
try
{
if (customVersionStream != null)
logger.LogInformation("Installing custom engine version as {version}...", version);
else if (neededForLock)
{
if (version.CustomIteration.HasValue)
throw new JobException(ErrorCode.EngineNonExistentCustomVersion);

var versionString = version.ToString();
await eventConsumer.HandleEvent(EventType.EngineInstallStart, new List<string> { versionString }, deploymentPipelineProcesses, cancellationToken);
logger.LogWarning("The required engine version ({version}) is not readily available! We will have to install it.", version);
}
else
logger.LogInformation("Requested engine version {version} not currently installed. Doing so now...", version);

installPath = await InstallVersionFiles(progressReporter, version, customVersionStream, deploymentPipelineProcesses, cancellationToken);
await eventConsumer.HandleEvent(EventType.EngineInstallComplete, new List<string> { versionString }, deploymentPipelineProcesses, cancellationToken);
progressReporter.StageName = "Running event";

ourTcs.SetResult();
}
catch (Exception ex)
{
if (installPath != null)
var versionString = version.ToString();
await eventConsumer.HandleEvent(EventType.EngineInstallStart, new List<string> { versionString }, deploymentPipelineProcesses, cancellationToken);

installPath = await InstallVersionFiles(progressReporter, version, customVersionStream, deploymentPipelineProcesses, cancellationToken);
await eventConsumer.HandleEvent(EventType.EngineInstallComplete, new List<string> { versionString }, deploymentPipelineProcesses, cancellationToken);

ourTcs.SetResult();
}
catch (Exception ex)
{
try
if (installPath != null)
{
logger.LogDebug("Cleaning up failed installation at {path}...", installPath);
await ioManager.DeleteDirectory(installPath, cancellationToken);
}
catch (Exception ex2)
{
logger.LogError(ex2, "Error cleaning up failed installation!");
try
{
logger.LogDebug("Cleaning up failed installation at {path}...", installPath);
await ioManager.DeleteDirectory(installPath, cancellationToken);
}
catch (Exception ex2)
{
logger.LogError(ex2, "Error cleaning up failed installation!");
}
}
}
else if (ex is not OperationCanceledException)
await eventConsumer.HandleEvent(EventType.EngineInstallFail, new List<string> { ex.Message }, deploymentPipelineProcesses, cancellationToken);
else if (ex is not OperationCanceledException)
await eventConsumer.HandleEvent(EventType.EngineInstallFail, new List<string> { ex.Message }, deploymentPipelineProcesses, cancellationToken);

lock (installedVersions)
installedVersions.Remove(version);
lock (installedVersions)
installedVersions.Remove(version);

ourTcs.SetException(ex);
throw;
}

ourTcs.SetException(ex);
return installLock;
}
catch
{
installLock.Dispose();
throw;
}

return installLock;
}
catch
{
installLock.Dispose();
throw;
}
}

Expand Down

0 comments on commit 2869eaf

Please sign in to comment.