mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-29 08:00:19 +01:00
Merge pull request #722 from tgstation/599-DreamDaemonReattachShit
Real Robust Reattachment Reststructuring
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
"profiles": {
|
||||
"Tgstation.Server.Host.Console": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "--attach-host-debugger",
|
||||
"workingDirectory": "bin\\Debug\\netcoreapp2.1",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
|
||||
@@ -70,8 +70,11 @@ namespace Tgstation.Server.Host.Watchdog
|
||||
logger.LogInformation("Detected dotnet executable at {0}", dotnetPath);
|
||||
|
||||
var rootLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
|
||||
|
||||
var assemblyStoragePath = Path.Combine(rootLocation, "lib"); //always always next to watchdog
|
||||
#if DEBUG
|
||||
Directory.CreateDirectory(assemblyStoragePath);
|
||||
#endif
|
||||
var defaultAssemblyPath = Path.GetFullPath(Path.Combine(assemblyStoragePath, "Default"));
|
||||
#if DEBUG
|
||||
//just copy the shit where it belongs
|
||||
@@ -121,7 +124,8 @@ namespace Tgstation.Server.Host.Watchdog
|
||||
'"' + assemblyPath + '"',
|
||||
'"' + updateDirectory + '"'
|
||||
};
|
||||
if (Debugger.IsAttached)
|
||||
|
||||
if (Environment.GetCommandLineArgs().Any(x => x == "--attach-host-debugger"))
|
||||
arguments.Add("--attach-debugger");
|
||||
arguments.AddRange(args);
|
||||
|
||||
|
||||
@@ -546,7 +546,7 @@ namespace Tgstation.Server.Host.Components.Chat
|
||||
{
|
||||
trackingContexts.Add(context);
|
||||
lock (mappedChannels)
|
||||
task = Task.WhenAll(trackingContexts.Select(x => x.SetChannels(mappedChannels.Select(y => y.Value.Channel), cancellationToken)));
|
||||
task = context.SetChannels(mappedChannels.Select(y => y.Value.Channel), cancellationToken);
|
||||
}
|
||||
await task.ConfigureAwait(false);
|
||||
return context;
|
||||
|
||||
@@ -186,6 +186,8 @@ namespace Tgstation.Server.Host.Components.Compiler
|
||||
/// <inheritdoc />
|
||||
public async Task<IDmbProvider> FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
|
||||
{
|
||||
if (compileJob == null)
|
||||
throw new ArgumentNullException(nameof(compileJob));
|
||||
logger.LogTrace("Loading compile job {0}...", compileJob.Id);
|
||||
var providerSubmitted = false;
|
||||
var newProvider = new DmbProvider(compileJob, ioManager, () =>
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||
using Tgstation.Server.Host.Components.Compiler;
|
||||
using Tgstation.Server.Host.Components.Watchdog;
|
||||
using Tgstation.Server.Host.Core;
|
||||
using Z.EntityFramework.Plus;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
@@ -56,6 +57,8 @@ namespace Tgstation.Server.Host.Components
|
||||
|
||||
logger.LogDebug("Saving reattach information: {0}...", reattachInformation);
|
||||
|
||||
var deleteTask = db.WatchdogReattachInformations.Where(x => x.InstanceId == metadata.Id).DeleteAsync(cancellationToken);
|
||||
|
||||
var instance = new Models.Instance { Id = metadata.Id };
|
||||
db.Instances.Attach(instance);
|
||||
|
||||
@@ -84,6 +87,7 @@ namespace Tgstation.Server.Host.Components
|
||||
Bravo = ConvertReattachInfo(reattachInformation.Bravo),
|
||||
AlphaIsActive = reattachInformation.AlphaIsActive,
|
||||
};
|
||||
await deleteTask.ConfigureAwait(false);
|
||||
await db.Save(cancellationToken).ConfigureAwait(false);
|
||||
});
|
||||
|
||||
@@ -92,8 +96,18 @@ namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
Models.WatchdogReattachInformation result = null;
|
||||
await databaseContextFactory.UseContext(async (db) =>
|
||||
result = await db.Instances.Where(x => x.Id == metadata.Id).Select(x => x.WatchdogReattachInformation).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false)
|
||||
).ConfigureAwait(false);
|
||||
{
|
||||
var instance = await db.Instances.Where(x => x.Id == metadata.Id)
|
||||
.Include(x => x.WatchdogReattachInformation).ThenInclude(x => x.Alpha).ThenInclude(x => x.CompileJob)
|
||||
.Include(x => x.WatchdogReattachInformation).ThenInclude(x => x.Bravo).ThenInclude(x => x.CompileJob)
|
||||
.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
|
||||
result = instance.WatchdogReattachInformation;
|
||||
if (result == default)
|
||||
return;
|
||||
instance.WatchdogReattachInformation = null;
|
||||
db.WatchdogReattachInformations.Remove(result);
|
||||
await db.Save(cancellationToken).ConfigureAwait(false);
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
if (result == default)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Watchdog
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a fake "dead" <see cref="ISessionController"/>
|
||||
/// </summary>
|
||||
sealed class DeadSessionController : ISessionController
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task<LaunchResult> LaunchResult { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsPrimary => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TerminationWasRequested => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ApiValidationStatus ApiValidationStatus => throw new NotSupportedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public IDmbProvider Dmb { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public ushort? Port => null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool ClosePortOnReboot
|
||||
{
|
||||
get => false;
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public RebootState RebootState => throw new NotSupportedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task OnReboot { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> Lifetime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="DeadSessionController"/> was <see cref="Dispose"/>d
|
||||
/// </summary>
|
||||
bool disposed;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="DeadSessionController"/>
|
||||
/// </summary>
|
||||
/// <param name="dmbProvider">The value of <see cref="Dmb"/></param>
|
||||
public DeadSessionController(IDmbProvider dmbProvider)
|
||||
{
|
||||
Dmb = dmbProvider ?? throw new ArgumentNullException(nameof(dmbProvider));
|
||||
LaunchResult = Task.FromResult(new LaunchResult
|
||||
{
|
||||
StartupTime = TimeSpan.FromSeconds(0)
|
||||
});
|
||||
Lifetime = Task.FromResult(-1);
|
||||
OnReboot = new TaskCompletionSource<object>().Task;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
disposed = true;
|
||||
}
|
||||
Dmb.Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void EnableCustomChatCommands() => throw new NotSupportedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ReattachInformation Release() => throw new NotSupportedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ResetRebootState() => throw new NotSupportedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<string> SendCommand(string command, CancellationToken cancellationToken) => throw new NotSupportedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetHighPriority() => throw new NotSupportedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> SetPort(ushort newPort, CancellationToken cancellatonToken) => throw new NotSupportedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> SetRebootState(RebootState newRebootState, CancellationToken cancellationToken) => throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,14 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
/// </summary>
|
||||
/// <param name="reattachInformation">The <see cref="ReattachInformation"/> to use</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in a new <see cref="ISessionController"/></returns>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in a new <see cref="ISessionController"/> on success or <see langword="null"/> on failure to reattach</returns>
|
||||
Task<ISessionController> Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ISessionController"/> that appears to have started and died with exit code -1
|
||||
/// </summary>
|
||||
/// <param name="dmbProvider">The <see cref="IDmbProvider"/> for the <see cref="ISessionController"/></param>
|
||||
/// <returns>A dead <see cref="ISessionController"/></returns>
|
||||
ISessionController CreateDeadSession(IDmbProvider dmbProvider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,11 +26,6 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
/// </summary>
|
||||
Models.CompileJob ActiveCompileJob { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The latest <see cref="LaunchResult"/> of the twin servers
|
||||
/// </summary>
|
||||
LaunchResult LastLaunchResult { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="DreamDaemonLaunchParameters"/> the active server is using
|
||||
/// </summary>
|
||||
@@ -50,8 +45,8 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
/// Start the <see cref="IWatchdog"/>
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="WatchdogLaunchResult"/> or <see langword="null"/> if it was already running</returns>
|
||||
Task<WatchdogLaunchResult> Launch(CancellationToken cancellationToken);
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task Launch(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Changes the <see cref="ActiveLaunchParameters"/>. If currently <see cref="Running"/> triggers a graceful restart
|
||||
@@ -66,8 +61,8 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
/// </summary>
|
||||
/// <param name="graceful">If <see langword="true"/> the restart will be delayed until a reboot is detected in the active server's DMAPI and this function will retrun immediately</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="WatchdogLaunchResult"/> or <see langword="null"/> if it was already running or <paramref name="graceful"/> is <see langword="true"/> and <see cref="Running"/> is <see langword="false"/></returns>
|
||||
Task<WatchdogLaunchResult> Restart(bool graceful, CancellationToken cancellationToken);
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task Restart(bool graceful, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Stops the watchdog
|
||||
|
||||
@@ -401,7 +401,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
reattachInformation.Dmb = null;
|
||||
released = true;
|
||||
Dispose();
|
||||
Dmb.KeepAlive();
|
||||
tmpProvider.KeepAlive();
|
||||
reattachInformation.Dmb = tmpProvider;
|
||||
return reattachInformation;
|
||||
}
|
||||
|
||||
@@ -268,6 +268,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
if (reattachInformation == null)
|
||||
throw new ArgumentNullException(nameof(reattachInformation));
|
||||
|
||||
SessionController result = null;
|
||||
var basePath = reattachInformation.IsPrimary ? reattachInformation.Dmb.PrimaryDirectory : reattachInformation.Dmb.SecondaryDirectory;
|
||||
var chatJsonTrackingContext = await chat.TrackJsons(basePath, reattachInformation.ChatChannelsJson, reattachInformation.ChatCommandsJson, cancellationToken).ConfigureAwait(false);
|
||||
try
|
||||
@@ -279,34 +280,40 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
try
|
||||
{
|
||||
var process = processExecutor.GetProcess(reattachInformation.ProcessId);
|
||||
try
|
||||
{
|
||||
networkPromptReaper.RegisterProcess(process);
|
||||
return new SessionController(reattachInformation, process, byondLock, byondTopicSender, chatJsonTrackingContext, context, chat, loggerFactory.CreateLogger<SessionController>(), null, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
process.Dispose();
|
||||
throw;
|
||||
}
|
||||
|
||||
if (process != null)
|
||||
try
|
||||
{
|
||||
networkPromptReaper.RegisterProcess(process);
|
||||
result = new SessionController(reattachInformation, process, byondLock, byondTopicSender, chatJsonTrackingContext, context, chat, loggerFactory.CreateLogger<SessionController>(), null, null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (result == null)
|
||||
process.Dispose();
|
||||
}
|
||||
}
|
||||
catch
|
||||
finally
|
||||
{
|
||||
context.Dispose();
|
||||
throw;
|
||||
if (result == null)
|
||||
context.Dispose();
|
||||
}
|
||||
}
|
||||
catch
|
||||
finally
|
||||
{
|
||||
byondLock.Dispose();
|
||||
throw;
|
||||
if (result == null)
|
||||
byondLock.Dispose();
|
||||
}
|
||||
}
|
||||
catch
|
||||
finally
|
||||
{
|
||||
chatJsonTrackingContext.Dispose();
|
||||
throw;
|
||||
if (result == null)
|
||||
chatJsonTrackingContext.Dispose();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ISessionController CreateDeadSession(IDmbProvider dmbProvider) => new DeadSessionController(dmbProvider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,9 +36,6 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
/// <inheritdoc />
|
||||
public Models.CompileJob ActiveCompileJob => (AlphaIsActive ? alphaServer : bravoServer)?.Dmb.CompileJob;
|
||||
|
||||
/// <inheritdoc />
|
||||
public LaunchResult LastLaunchResult { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public DreamDaemonLaunchParameters ActiveLaunchParameters { get; private set; }
|
||||
|
||||
@@ -109,7 +106,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
readonly Api.Models.Instance instance;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="Watchdog"/> should <see cref="LaunchNoLock(bool, bool, bool, CancellationToken)"/> in <see cref="StartAsync(CancellationToken)"/>
|
||||
/// If the <see cref="Watchdog"/> should <see cref="LaunchImplNoLock(bool, bool, WatchdogReattachInformation, CancellationToken)"/> in <see cref="StartAsync(CancellationToken)"/>
|
||||
/// </summary>
|
||||
readonly bool autoStart;
|
||||
|
||||
@@ -288,6 +285,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
try
|
||||
{
|
||||
monitorState.InactiveServer = await sessionControllerFactory.LaunchNew(ActiveLaunchParameters, newDmb, null, false, !monitorState.ActiveServer.IsPrimary, false, cancellationToken).ConfigureAwait(false);
|
||||
monitorState.InactiveServer.SetHighPriority();
|
||||
usedMostRecentDmb = true;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@@ -310,6 +308,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
throw new JobException("Creating backup DMB provider failed!");
|
||||
|
||||
monitorState.InactiveServer = await sessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbBackup, null, false, !monitorState.ActiveServer.IsPrimary, false, cancellationToken).ConfigureAwait(false);
|
||||
monitorState.InactiveServer.SetHighPriority();
|
||||
usedMostRecentDmb = false;
|
||||
await chat.SendWatchdogMessage("Staging newest DMB on inactive server failed: {0} Falling back to previous dmb...", cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
@@ -448,7 +447,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
monitorState.NextAction = MonitorAction.Continue;
|
||||
break;
|
||||
case MonitorActivationReason.NewDmbAvailable:
|
||||
monitorState.InactiveServerHasStagedDmb = true;
|
||||
monitorState.InactiveServerHasStagedDmb = true;
|
||||
goto case MonitorActivationReason.ActiveLaunchParametersUpdated;
|
||||
case MonitorActivationReason.ActiveLaunchParametersUpdated:
|
||||
await UpdateAndRestartInactiveServer(true).ConfigureAwait(false);
|
||||
@@ -570,21 +569,29 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
|
||||
for (var retryAttempts = 1; monitorState.NextAction == MonitorAction.Restart; ++retryAttempts)
|
||||
{
|
||||
WatchdogLaunchResult result;
|
||||
Exception launchException = null;
|
||||
using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
result = await LaunchNoLock(false, false, false, cancellationToken).ConfigureAwait(false);
|
||||
if (Running)
|
||||
try
|
||||
{
|
||||
logger.LogDebug("Relaunch successful, resetting monitor state...");
|
||||
monitorState = new MonitorState(); //clean the slate
|
||||
await LaunchImplNoLock(false, false, null, cancellationToken).ConfigureAwait(false);
|
||||
if (Running)
|
||||
{
|
||||
logger.LogDebug("Relaunch successful, resetting monitor state...");
|
||||
monitorState = new MonitorState(); //clean the slate
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
launchException = e;
|
||||
}
|
||||
}
|
||||
|
||||
await chatTask.ConfigureAwait(false);
|
||||
if (!Running)
|
||||
{
|
||||
logger.LogWarning("Failed to automatically restart the watchdog! Alpha: {0}; Bravo: {1}", result.Alpha.ToString(), result.Bravo.ToString());
|
||||
if (launchException == null)
|
||||
logger.LogWarning("Failed to automatically restart the watchdog!");
|
||||
else
|
||||
logger.LogWarning("Failed to automatically restart the watchdog! Exception: {0}", launchException);
|
||||
var retryDelay = Math.Min(Math.Pow(2, retryAttempts), 3600); //max of one hour
|
||||
chatTask = chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Failed to restart watchdog (Attempt: {0}), retrying in {1} seconds...", retryAttempts, retryDelay), cancellationToken);
|
||||
await Task.WhenAll(Task.Delay((int)retryDelay, cancellationToken), chatTask).ConfigureAwait(false);
|
||||
@@ -633,35 +640,32 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
}
|
||||
}
|
||||
|
||||
async Task<WatchdogLaunchResult> LaunchNoLock(bool startMonitor, bool announce, bool doReattach, CancellationToken cancellationToken)
|
||||
async Task LaunchImplNoLock(bool startMonitor, bool announce, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
logger.LogTrace("Begin LaunchNoLock");
|
||||
using (var alphaStartCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
|
||||
{
|
||||
if (Running)
|
||||
{
|
||||
logger.LogTrace("Aborted due to already running!");
|
||||
return null;
|
||||
}
|
||||
throw new JobException("Watchdog already running!");
|
||||
|
||||
Task chatTask;
|
||||
//this is necessary, the monitor could be in it's sleep loop trying to restart
|
||||
if (startMonitor && await StopMonitor().ConfigureAwait(false))
|
||||
chatTask = chat.SendWatchdogMessage("Automatic retry sequence cancelled by manual launch. Restarting...", cancellationToken);
|
||||
else if (announce)
|
||||
chatTask = chat.SendWatchdogMessage(doReattach ? "Reattaching..." : "Starting...", cancellationToken);
|
||||
chatTask = chat.SendWatchdogMessage(reattachInfo == null ? "Starting..." : "Reattaching...", cancellationToken);
|
||||
else
|
||||
chatTask = Task.CompletedTask;
|
||||
//start both servers
|
||||
LastLaunchParameters = ActiveLaunchParameters;
|
||||
var ignoreNestedException = false;
|
||||
try
|
||||
{
|
||||
//good ole sanity
|
||||
if (alphaServer != null || bravoServer != null)
|
||||
throw new InvalidOperationException("Entered LaunchNoLock with one or more of the servers not being null!");
|
||||
|
||||
var reattachInfo = doReattach ? await reattachInfoHandler.Load(cancellationToken).ConfigureAwait(false) : null;
|
||||
var doesntNeedNewDmb = doReattach && reattachInfo?.Alpha != null && reattachInfo?.Bravo != null;
|
||||
var doesntNeedNewDmb = reattachInfo?.Alpha != null && reattachInfo?.Bravo != null;
|
||||
var dmbToUse = doesntNeedNewDmb ? null : dmbFactory.LockNextDmb(2);
|
||||
|
||||
try
|
||||
@@ -675,13 +679,13 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
//wait until this boy officially starts so as not to confuse the servers as to who came first
|
||||
var startTime = DateTimeOffset.Now;
|
||||
alphaServer = await alphaServerTask.ConfigureAwait(false);
|
||||
alphaServer.SetHighPriority();
|
||||
alphaServer?.SetHighPriority();
|
||||
|
||||
//extra delay for total ordering
|
||||
var now = DateTimeOffset.Now;
|
||||
var delay = now - startTime;
|
||||
|
||||
if (delay.TotalSeconds < AlphaBravoStartupSeperationInterval)
|
||||
if (reattachInfo == null && delay.TotalSeconds < AlphaBravoStartupSeperationInterval)
|
||||
await Task.Delay(startTime.AddSeconds(AlphaBravoStartupSeperationInterval) - now, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
Task<ISessionController> bravoServerTask;
|
||||
@@ -691,7 +695,38 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
bravoServerTask = sessionControllerFactory.Reattach(reattachInfo.Bravo, cancellationToken);
|
||||
|
||||
bravoServer = await bravoServerTask.ConfigureAwait(false);
|
||||
bravoServer.SetHighPriority();
|
||||
bravoServer?.SetHighPriority();
|
||||
|
||||
//possiblity of null servers due to failed reattaches
|
||||
if (alphaServer == null || bravoServer == null)
|
||||
{
|
||||
await chatTask.ConfigureAwait(false);
|
||||
var bothServersDead = alphaServer == null && bravoServer == null;
|
||||
if (bothServersDead
|
||||
|| (alphaServer == null && reattachInfo.AlphaIsActive)
|
||||
|| (bravoServer == null && !reattachInfo.AlphaIsActive))
|
||||
{
|
||||
//we lost the active server, just restart
|
||||
DisposeAndNullControllers();
|
||||
const string FailReattachMessage = "Unable to properly reattach to active server! Restarting...";
|
||||
logger.LogWarning(FailReattachMessage);
|
||||
logger.LogDebug(bothServersDead ? "Also could not reattach to inactive server!" : "Inactive server was reattached successfully!");
|
||||
chatTask = chat.SendWatchdogMessage(FailReattachMessage, cancellationToken);
|
||||
ignoreNestedException = true;
|
||||
await LaunchImplNoLock(true, false, null, cancellationToken).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const string InactiveReattachFailureMessage = "Unable to reattach to inactive server. Leaving for monitor to reboot...";
|
||||
chatTask = chat.SendWatchdogMessage(InactiveReattachFailureMessage, cancellationToken);
|
||||
logger.LogWarning(InactiveReattachFailureMessage);
|
||||
|
||||
//we still have the active server but the other one is dead to us, hand it off to the monitor to restart
|
||||
if (reattachInfo.AlphaIsActive)
|
||||
bravoServer = sessionControllerFactory.CreateDeadSession(reattachInfo.Bravo.Dmb);
|
||||
else
|
||||
alphaServer = sessionControllerFactory.CreateDeadSession(reattachInfo.Alpha.Dmb);
|
||||
}
|
||||
|
||||
async Task<LaunchResult> CheckLaunch(ISessionController controller, string serverName)
|
||||
{
|
||||
@@ -716,8 +751,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
//both servers are now running, alpha is the active server(unless reattach), huzzah
|
||||
AlphaIsActive = doReattach ? reattachInfo?.AlphaIsActive ?? true : true;
|
||||
LastLaunchResult = alphaLrt.Result;
|
||||
AlphaIsActive = reattachInfo?.AlphaIsActive ?? true;
|
||||
|
||||
var activeServer = AlphaIsActive ? alphaServer : bravoServer;
|
||||
activeServer.EnableCustomChatCommands();
|
||||
@@ -731,11 +765,6 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
monitorCts = new CancellationTokenSource();
|
||||
monitorTask = MonitorLifetimes(monitorCts.Token);
|
||||
}
|
||||
return new WatchdogLaunchResult
|
||||
{
|
||||
Alpha = alphaLrt.Result,
|
||||
Bravo = bravoLrt.Result
|
||||
};
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -750,14 +779,17 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var originalChatTask = chatTask;
|
||||
async Task ChainChatTaskWithErrorMessage()
|
||||
if (!ignoreNestedException && !cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
await originalChatTask.ConfigureAwait(false);
|
||||
await chat.SendWatchdogMessage("Startup failed!", cancellationToken).ConfigureAwait(false);
|
||||
var originalChatTask = chatTask;
|
||||
async Task ChainChatTaskWithErrorMessage()
|
||||
{
|
||||
await originalChatTask.ConfigureAwait(false);
|
||||
await chat.SendWatchdogMessage("Startup failed!", cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
chatTask = ChainChatTaskWithErrorMessage();
|
||||
logger.LogWarning("Failed to start watchdog: {0}", e.ToString());
|
||||
}
|
||||
chatTask = ChainChatTaskWithErrorMessage();
|
||||
logger.LogWarning("Failed to start watchdog: {0}", e.ToString());
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
@@ -772,10 +804,10 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<WatchdogLaunchResult> Launch(CancellationToken cancellationToken)
|
||||
public async Task Launch(CancellationToken cancellationToken)
|
||||
{
|
||||
using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
|
||||
return await LaunchNoLock(true, true, false, cancellationToken).ConfigureAwait(false);
|
||||
await LaunchImplNoLock(true, true, null, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -792,7 +824,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<WatchdogLaunchResult> Restart(bool graceful, CancellationToken cancellationToken)
|
||||
public async Task Restart(bool graceful, CancellationToken cancellationToken)
|
||||
{
|
||||
logger.LogTrace("Begin Restart. Graceful: {0}", graceful);
|
||||
using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
|
||||
@@ -807,9 +839,8 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
}
|
||||
else
|
||||
chatTask = Task.CompletedTask;
|
||||
var result = await LaunchNoLock(true, !Running, false, cancellationToken).ConfigureAwait(false);
|
||||
await LaunchImplNoLock(true, !Running, null, cancellationToken).ConfigureAwait(false);
|
||||
await chatTask.ConfigureAwait(false);
|
||||
return result;
|
||||
}
|
||||
var toReboot = AlphaIsActive ? alphaServer : bravoServer;
|
||||
if (toReboot != null)
|
||||
@@ -817,7 +848,6 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
if (!await toReboot.SetRebootState(Components.Watchdog.RebootState.Restart, cancellationToken).ConfigureAwait(false))
|
||||
logger.LogWarning("Unable to send reboot state change event!");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -825,13 +855,14 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
public async Task Terminate(bool graceful, CancellationToken cancellationToken)
|
||||
{
|
||||
using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
|
||||
await TerminateNoLock(graceful, true, cancellationToken).ConfigureAwait(false);
|
||||
await TerminateNoLock(graceful, !releaseServers, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (!autoStart)
|
||||
var reattachInfo = await reattachInfoHandler.Load(cancellationToken).ConfigureAwait(false);
|
||||
if (!autoStart && reattachInfo == null)
|
||||
return;
|
||||
|
||||
long? adminUserId = null;
|
||||
@@ -851,7 +882,11 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
CancelRight = (ulong)DreamDaemonRights.Shutdown,
|
||||
CancelRightsType = RightsType.DreamDaemon
|
||||
};
|
||||
await jobManager.RegisterOperation(job, (j, databaseContext, progressFunction, ct) => Launch(ct), cancellationToken).ConfigureAwait(false);
|
||||
await jobManager.RegisterOperation(job, async (j, databaseContext, progressFunction, ct) =>
|
||||
{
|
||||
using (await SemaphoreSlimContext.Lock(semaphore, ct).ConfigureAwait(false))
|
||||
await LaunchImplNoLock(true, true, reattachInfo, ct).ConfigureAwait(false);
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -859,6 +894,8 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
{
|
||||
if (releaseServers && Running)
|
||||
{
|
||||
await StopMonitor().ConfigureAwait(false);
|
||||
|
||||
var reattachInformation = new WatchdogReattachInformation
|
||||
{
|
||||
AlphaIsActive = AlphaIsActive
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Watchdog
|
||||
{
|
||||
/// <summary>
|
||||
/// Launch results for a <see cref="IWatchdog"/>
|
||||
/// </summary>
|
||||
public sealed class WatchdogLaunchResult
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="LaunchResult"/> for the alpha process
|
||||
/// </summary>
|
||||
public LaunchResult Alpha { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="LaunchResult"/> for the bravo process
|
||||
/// </summary>
|
||||
public LaunchResult Bravo { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -66,14 +66,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
Instance = Instance,
|
||||
StartedBy = AuthenticationContext.User
|
||||
};
|
||||
await jobManager.RegisterOperation(job,
|
||||
async (paramJob, databaseContext, progressHandler, innerCt) =>
|
||||
{
|
||||
var result = await instance.Watchdog.Launch(innerCt).ConfigureAwait(false);
|
||||
if (result == null)
|
||||
throw new JobException("Watchdog already running!");
|
||||
},
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressHandler, innerCt) => instance.Watchdog.Launch(innerCt), cancellationToken).ConfigureAwait(false);
|
||||
return Accepted(job.ToApi());
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
/// Get a <see cref="IProcess"/> by <paramref name="id"/>
|
||||
/// </summary>
|
||||
/// <param name="id">The <see cref="IProcess.Id"/></param>
|
||||
/// <returns>The <see cref="IProcess"/> represented by <paramref name="id"/></returns>
|
||||
/// <returns>The <see cref="IProcess"/> represented by <paramref name="id"/> on success, <see langword="null"/> on failure</returns>
|
||||
IProcess GetProcess(int id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Tgstation.Server.Host.Core
|
||||
/// </summary>
|
||||
readonly ILogger<Process> logger;
|
||||
|
||||
public Process(System.Diagnostics.Process handle, Task<int> lifetime, StringBuilder outputStringBuilder, StringBuilder errorStringBuilder, StringBuilder combinedStringBuilder, ILogger<Process> logger)
|
||||
public Process(System.Diagnostics.Process handle, Task<int> lifetime, StringBuilder outputStringBuilder, StringBuilder errorStringBuilder, StringBuilder combinedStringBuilder, ILogger<Process> logger, bool preExisting)
|
||||
{
|
||||
this.handle = handle ?? throw new ArgumentNullException(nameof(handle));
|
||||
Lifetime = lifetime ?? throw new ArgumentNullException(nameof(lifetime));
|
||||
@@ -40,6 +40,13 @@ namespace Tgstation.Server.Host.Core
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
Id = handle.Id;
|
||||
|
||||
if (preExisting)
|
||||
{
|
||||
Startup = Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
Startup = Task.Factory.StartNew(() =>
|
||||
{
|
||||
try
|
||||
|
||||
@@ -58,10 +58,19 @@ namespace Tgstation.Server.Host.Core
|
||||
public IProcess GetProcess(int id)
|
||||
{
|
||||
logger.LogDebug("Attaching to process {0}...", id);
|
||||
var handle = System.Diagnostics.Process.GetProcessById(id);
|
||||
System.Diagnostics.Process handle;
|
||||
try
|
||||
{
|
||||
return new Process(handle, AttachExitHandler(handle), null, null, null, loggerFactory.CreateLogger<Process>());
|
||||
handle = System.Diagnostics.Process.GetProcessById(id);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
logger.LogDebug("Unable to get process {0}! Exception: {1}", id, e);
|
||||
return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
return new Process(handle, AttachExitHandler(handle), null, null, null, loggerFactory.CreateLogger<Process>(), true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -129,7 +138,7 @@ namespace Tgstation.Server.Host.Core
|
||||
}
|
||||
catch (InvalidOperationException) { }
|
||||
|
||||
return new Process(handle, lifetimeTask, outputStringBuilder, errorStringBuilder, combinedStringBuilder, loggerFactory.CreateLogger<Process>());
|
||||
return new Process(handle, lifetimeTask, outputStringBuilder, errorStringBuilder, combinedStringBuilder, loggerFactory.CreateLogger<Process>(), false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
Generated
+680
@@ -0,0 +1,680 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace Tgstation.Server.Host.Models.Migrations
|
||||
{
|
||||
[DbContext(typeof(SqlServerDatabaseContext))]
|
||||
[Migration("20180926033145_MSReattachCompileJobRequired")]
|
||||
partial class MSReattachCompileJobRequired
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds the target model
|
||||
/// </summary>
|
||||
/// <param name="modelBuilder">The <see cref="ModelBuilder"/> to use</param>
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128)
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("ConnectionString")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("Enabled");
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int?>("Provider");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("InstanceId");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("ChatBots");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<long>("ChatSettingsId");
|
||||
|
||||
b.Property<decimal?>("DiscordChannelId")
|
||||
.HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
|
||||
|
||||
b.Property<string>("IrcChannel");
|
||||
|
||||
b.Property<bool?>("IsAdminChannel")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("IsUpdatesChannel")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("IsWatchdogChannel")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Tag");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ChatSettingsId", "DiscordChannelId")
|
||||
.IsUnique()
|
||||
.HasFilter("[DiscordChannelId] IS NOT NULL");
|
||||
|
||||
b.HasIndex("ChatSettingsId", "IrcChannel")
|
||||
.IsUnique()
|
||||
.HasFilter("[IrcChannel] IS NOT NULL");
|
||||
|
||||
b.ToTable("ChatChannels");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("ByondVersion")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<Guid?>("DirectoryName")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("DmeName")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long>("JobId");
|
||||
|
||||
b.Property<int>("MinimumSecurityLevel");
|
||||
|
||||
b.Property<string>("Output")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long>("RevisionInformationId");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("DirectoryName");
|
||||
|
||||
b.HasIndex("JobId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RevisionInformationId");
|
||||
|
||||
b.ToTable("CompileJobs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("AccessToken");
|
||||
|
||||
b.Property<bool?>("AllowWebClient")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("AutoStart")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<int>("PrimaryPort");
|
||||
|
||||
b.Property<int?>("ProcessId");
|
||||
|
||||
b.Property<int>("SecondaryPort");
|
||||
|
||||
b.Property<int>("SecurityLevel");
|
||||
|
||||
b.Property<bool?>("SoftRestart")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("SoftShutdown")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long>("StartupTimeout");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("InstanceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("DreamDaemonSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<int>("ApiValidationPort");
|
||||
|
||||
b.Property<int>("ApiValidationSecurityLevel");
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<string>("ProjectName");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("InstanceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("DreamMakerSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<long>("AutoUpdateInterval");
|
||||
|
||||
b.Property<int>("ConfigurationType");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("Online")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Path")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Path")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Instances");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<decimal>("ByondRights")
|
||||
.HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
|
||||
|
||||
b.Property<decimal>("ChatBotRights")
|
||||
.HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
|
||||
|
||||
b.Property<decimal>("ConfigurationRights")
|
||||
.HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
|
||||
|
||||
b.Property<decimal>("DreamDaemonRights")
|
||||
.HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
|
||||
|
||||
b.Property<decimal>("DreamMakerRights")
|
||||
.HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<decimal>("InstanceUserRights")
|
||||
.HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
|
||||
|
||||
b.Property<decimal>("RepositoryRights")
|
||||
.HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
|
||||
|
||||
b.Property<long?>("UserId")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("InstanceId");
|
||||
|
||||
b.HasIndex("UserId", "InstanceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("InstanceUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<decimal?>("CancelRight")
|
||||
.HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
|
||||
|
||||
b.Property<decimal?>("CancelRightsType")
|
||||
.HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
|
||||
|
||||
b.Property<bool?>("Cancelled")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long?>("CancelledById");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ExceptionDetails");
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<DateTimeOffset?>("StartedAt")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long>("StartedById");
|
||||
|
||||
b.Property<DateTimeOffset?>("StoppedAt");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CancelledById");
|
||||
|
||||
b.HasIndex("InstanceId");
|
||||
|
||||
b.HasIndex("StartedById");
|
||||
|
||||
b.ToTable("Jobs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("AccessIdentifier")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ChatChannelsJson")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ChatCommandsJson")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long>("CompileJobId");
|
||||
|
||||
b.Property<bool>("IsPrimary");
|
||||
|
||||
b.Property<int>("Port");
|
||||
|
||||
b.Property<int>("ProcessId");
|
||||
|
||||
b.Property<int>("RebootState");
|
||||
|
||||
b.Property<string>("ServerCommandsJson")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CompileJobId");
|
||||
|
||||
b.ToTable("ReattachInformations");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("AccessToken");
|
||||
|
||||
b.Property<string>("AccessUser");
|
||||
|
||||
b.Property<bool?>("AutoUpdatesKeepTestMerges")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("AutoUpdatesSynchronize")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("CommitterEmail")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("CommitterName")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<bool?>("PushTestMergeCommits")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("ShowTestMergeCommitters")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("InstanceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("RepositorySettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<long>("RevisionInformationId");
|
||||
|
||||
b.Property<long>("TestMergeId");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RevisionInformationId");
|
||||
|
||||
b.HasIndex("TestMergeId");
|
||||
|
||||
b.ToTable("RevInfoTestMerges");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("CommitSha")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40);
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<string>("OriginCommitSha")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40);
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CommitSha")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("InstanceId");
|
||||
|
||||
b.ToTable("RevisionInformations");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("Author")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("BodyAtMerge")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Comment");
|
||||
|
||||
b.Property<DateTimeOffset>("MergedAt");
|
||||
|
||||
b.Property<long>("MergedById");
|
||||
|
||||
b.Property<int?>("Number")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long?>("PrimaryRevisionInformationId")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("PullRequestRevision")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("TitleAtMerge")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Url")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MergedById");
|
||||
|
||||
b.HasIndex("PrimaryRevisionInformationId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("TestMerges");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<decimal>("AdministrationRights")
|
||||
.HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
|
||||
|
||||
b.Property<string>("CanonicalName")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<DateTimeOffset?>("CreatedAt")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long?>("CreatedById");
|
||||
|
||||
b.Property<bool?>("Enabled")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<decimal>("InstanceManagerRights")
|
||||
.HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
|
||||
|
||||
b.Property<DateTimeOffset?>("LastPasswordUpdate");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("PasswordHash");
|
||||
|
||||
b.Property<string>("SystemIdentifier");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CanonicalName")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("CreatedById");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<long?>("AlphaId");
|
||||
|
||||
b.Property<bool>("AlphaIsActive");
|
||||
|
||||
b.Property<long?>("BravoId");
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AlphaId");
|
||||
|
||||
b.HasIndex("BravoId");
|
||||
|
||||
b.HasIndex("InstanceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("WatchdogReattachInformations");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithMany("ChatSettings")
|
||||
.HasForeignKey("InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
|
||||
.WithMany("Channels")
|
||||
.HasForeignKey("ChatSettingsId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
|
||||
.WithOne()
|
||||
.HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
|
||||
.WithMany("CompileJobs")
|
||||
.HasForeignKey("RevisionInformationId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithOne("DreamDaemonSettings")
|
||||
.HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithOne("DreamMakerSettings")
|
||||
.HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithMany("InstanceUsers")
|
||||
.HasForeignKey("InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.User")
|
||||
.WithMany("InstanceUsers")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
|
||||
.WithMany()
|
||||
.HasForeignKey("CancelledById");
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithMany("Jobs")
|
||||
.HasForeignKey("InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
|
||||
.WithMany()
|
||||
.HasForeignKey("StartedById")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
|
||||
.WithMany()
|
||||
.HasForeignKey("CompileJobId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithOne("RepositorySettings")
|
||||
.HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
|
||||
.WithMany("ActiveTestMerges")
|
||||
.HasForeignKey("RevisionInformationId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
|
||||
.WithMany("RevisonInformations")
|
||||
.HasForeignKey("TestMergeId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithMany("RevisionInformations")
|
||||
.HasForeignKey("InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
|
||||
.WithMany("TestMerges")
|
||||
.HasForeignKey("MergedById")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
|
||||
.WithOne("PrimaryTestMerge")
|
||||
.HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
|
||||
.WithMany("CreatedUsers")
|
||||
.HasForeignKey("CreatedById");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
|
||||
.WithMany()
|
||||
.HasForeignKey("AlphaId");
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
|
||||
.WithMany()
|
||||
.HasForeignKey("BravoId");
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance")
|
||||
.WithOne("WatchdogReattachInformation")
|
||||
.HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Tgstation.Server.Host.Models.Migrations
|
||||
{
|
||||
/// <summary>
|
||||
/// Marks the <see cref="CompileJob"/>s of <see cref="ReattachInformation"/>s as non-nullable for MSSQL
|
||||
/// </summary>
|
||||
public partial class MSReattachCompileJobRequired : Migration
|
||||
{
|
||||
/// <summary>
|
||||
/// Applies the migration
|
||||
/// </summary>
|
||||
/// <param name="migrationBuilder">The <see cref="MigrationBuilder"/> to use</param>
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_ReattachInformations_CompileJobs_CompileJobId",
|
||||
table: "ReattachInformations");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "CompileJobId",
|
||||
table: "ReattachInformations",
|
||||
nullable: false,
|
||||
oldClrType: typeof(long),
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_ReattachInformations_CompileJobs_CompileJobId",
|
||||
table: "ReattachInformations",
|
||||
column: "CompileJobId",
|
||||
principalTable: "CompileJobs",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unapplies the migration
|
||||
/// </summary>
|
||||
/// <param name="migrationBuilder">The <see cref="MigrationBuilder"/> to use</param>
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_ReattachInformations_CompileJobs_CompileJobId",
|
||||
table: "ReattachInformations");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "CompileJobId",
|
||||
table: "ReattachInformations",
|
||||
nullable: true,
|
||||
oldClrType: typeof(long));
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_ReattachInformations_CompileJobs_CompileJobId",
|
||||
table: "ReattachInformations",
|
||||
column: "CompileJobId",
|
||||
principalTable: "CompileJobs",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+653
@@ -0,0 +1,653 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Tgstation.Server.Host.Models.Migrations
|
||||
{
|
||||
[DbContext(typeof(MySqlDatabaseContext))]
|
||||
[Migration("20180926034014_MYReattachCompileJobRequired")]
|
||||
partial class MYReattachCompileJobRequired
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds the target model
|
||||
/// </summary>
|
||||
/// <param name="modelBuilder">The <see cref="ModelBuilder"/> to use</param>
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("ConnectionString")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("Enabled");
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int?>("Provider");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("InstanceId");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("ChatBots");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<long>("ChatSettingsId");
|
||||
|
||||
b.Property<ulong?>("DiscordChannelId");
|
||||
|
||||
b.Property<string>("IrcChannel");
|
||||
|
||||
b.Property<bool?>("IsAdminChannel")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("IsUpdatesChannel")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("IsWatchdogChannel")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Tag");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ChatSettingsId", "DiscordChannelId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ChatSettingsId", "IrcChannel")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("ChatChannels");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("ByondVersion")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<Guid?>("DirectoryName")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("DmeName")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long>("JobId");
|
||||
|
||||
b.Property<int>("MinimumSecurityLevel");
|
||||
|
||||
b.Property<string>("Output")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long>("RevisionInformationId");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("DirectoryName");
|
||||
|
||||
b.HasIndex("JobId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RevisionInformationId");
|
||||
|
||||
b.ToTable("CompileJobs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("AccessToken");
|
||||
|
||||
b.Property<bool?>("AllowWebClient")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("AutoStart")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<ushort?>("PrimaryPort")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int?>("ProcessId");
|
||||
|
||||
b.Property<ushort?>("SecondaryPort")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int>("SecurityLevel");
|
||||
|
||||
b.Property<bool?>("SoftRestart")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("SoftShutdown")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<uint?>("StartupTimeout")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("InstanceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("DreamDaemonSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<ushort?>("ApiValidationPort")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int>("ApiValidationSecurityLevel");
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<string>("ProjectName");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("InstanceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("DreamMakerSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<uint?>("AutoUpdateInterval")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int>("ConfigurationType");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("Online")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Path")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Path")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Instances");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<ulong>("ByondRights");
|
||||
|
||||
b.Property<ulong>("ChatBotRights");
|
||||
|
||||
b.Property<ulong>("ConfigurationRights");
|
||||
|
||||
b.Property<ulong>("DreamDaemonRights");
|
||||
|
||||
b.Property<ulong>("DreamMakerRights");
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<ulong>("InstanceUserRights");
|
||||
|
||||
b.Property<ulong>("RepositoryRights");
|
||||
|
||||
b.Property<long?>("UserId")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("InstanceId");
|
||||
|
||||
b.HasIndex("UserId", "InstanceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("InstanceUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<ulong?>("CancelRight");
|
||||
|
||||
b.Property<ulong?>("CancelRightsType");
|
||||
|
||||
b.Property<bool?>("Cancelled")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long?>("CancelledById");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ExceptionDetails");
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<DateTimeOffset?>("StartedAt")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long>("StartedById");
|
||||
|
||||
b.Property<DateTimeOffset?>("StoppedAt");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CancelledById");
|
||||
|
||||
b.HasIndex("InstanceId");
|
||||
|
||||
b.HasIndex("StartedById");
|
||||
|
||||
b.ToTable("Jobs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("AccessIdentifier")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ChatChannelsJson")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ChatCommandsJson")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long>("CompileJobId");
|
||||
|
||||
b.Property<bool>("IsPrimary");
|
||||
|
||||
b.Property<ushort>("Port");
|
||||
|
||||
b.Property<int>("ProcessId");
|
||||
|
||||
b.Property<int>("RebootState");
|
||||
|
||||
b.Property<string>("ServerCommandsJson")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CompileJobId");
|
||||
|
||||
b.ToTable("ReattachInformations");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("AccessToken");
|
||||
|
||||
b.Property<string>("AccessUser");
|
||||
|
||||
b.Property<bool?>("AutoUpdatesKeepTestMerges")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("AutoUpdatesSynchronize")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("CommitterEmail")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("CommitterName")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<bool?>("PushTestMergeCommits")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<bool?>("ShowTestMergeCommitters")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("InstanceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("RepositorySettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<long>("RevisionInformationId");
|
||||
|
||||
b.Property<long>("TestMergeId");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RevisionInformationId");
|
||||
|
||||
b.HasIndex("TestMergeId");
|
||||
|
||||
b.ToTable("RevInfoTestMerges");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("CommitSha")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40);
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.Property<string>("OriginCommitSha")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40);
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CommitSha")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("InstanceId");
|
||||
|
||||
b.ToTable("RevisionInformations");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Author")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("BodyAtMerge")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Comment");
|
||||
|
||||
b.Property<DateTimeOffset>("MergedAt");
|
||||
|
||||
b.Property<long>("MergedById");
|
||||
|
||||
b.Property<int?>("Number")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long?>("PrimaryRevisionInformationId")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("PullRequestRevision")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("TitleAtMerge")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Url")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MergedById");
|
||||
|
||||
b.HasIndex("PrimaryRevisionInformationId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("TestMerges");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<ulong>("AdministrationRights");
|
||||
|
||||
b.Property<string>("CanonicalName")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<DateTimeOffset?>("CreatedAt")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long?>("CreatedById");
|
||||
|
||||
b.Property<bool?>("Enabled")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<ulong>("InstanceManagerRights");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastPasswordUpdate");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("PasswordHash");
|
||||
|
||||
b.Property<string>("SystemIdentifier");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CanonicalName")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("CreatedById");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<long?>("AlphaId");
|
||||
|
||||
b.Property<bool>("AlphaIsActive");
|
||||
|
||||
b.Property<long?>("BravoId");
|
||||
|
||||
b.Property<long>("InstanceId");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AlphaId");
|
||||
|
||||
b.HasIndex("BravoId");
|
||||
|
||||
b.HasIndex("InstanceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("WatchdogReattachInformations");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithMany("ChatSettings")
|
||||
.HasForeignKey("InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
|
||||
.WithMany("Channels")
|
||||
.HasForeignKey("ChatSettingsId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
|
||||
.WithOne()
|
||||
.HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
|
||||
.WithMany("CompileJobs")
|
||||
.HasForeignKey("RevisionInformationId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithOne("DreamDaemonSettings")
|
||||
.HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithOne("DreamMakerSettings")
|
||||
.HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithMany("InstanceUsers")
|
||||
.HasForeignKey("InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.User")
|
||||
.WithMany("InstanceUsers")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
|
||||
.WithMany()
|
||||
.HasForeignKey("CancelledById");
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithMany("Jobs")
|
||||
.HasForeignKey("InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
|
||||
.WithMany()
|
||||
.HasForeignKey("StartedById")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
|
||||
.WithMany()
|
||||
.HasForeignKey("CompileJobId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithOne("RepositorySettings")
|
||||
.HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
|
||||
.WithMany("ActiveTestMerges")
|
||||
.HasForeignKey("RevisionInformationId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
|
||||
.WithMany("RevisonInformations")
|
||||
.HasForeignKey("TestMergeId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
|
||||
.WithMany("RevisionInformations")
|
||||
.HasForeignKey("InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
|
||||
.WithMany("TestMerges")
|
||||
.HasForeignKey("MergedById")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
|
||||
.WithOne("PrimaryTestMerge")
|
||||
.HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
|
||||
.WithMany("CreatedUsers")
|
||||
.HasForeignKey("CreatedById");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
|
||||
.WithMany()
|
||||
.HasForeignKey("AlphaId");
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
|
||||
.WithMany()
|
||||
.HasForeignKey("BravoId");
|
||||
|
||||
b.HasOne("Tgstation.Server.Host.Models.Instance")
|
||||
.WithOne("WatchdogReattachInformation")
|
||||
.HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Tgstation.Server.Host.Models.Migrations
|
||||
{
|
||||
/// <summary>
|
||||
/// Marks the <see cref="CompileJob"/>s of <see cref="ReattachInformation"/>s as non-nullable for MySQL/MariaDB
|
||||
/// </summary>
|
||||
public partial class MYReattachCompileJobRequired : Migration
|
||||
{
|
||||
/// <summary>
|
||||
/// Applies the migration
|
||||
/// </summary>
|
||||
/// <param name="migrationBuilder">The <see cref="MigrationBuilder"/> to use</param>
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_ReattachInformations_CompileJobs_CompileJobId",
|
||||
table: "ReattachInformations");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "CompileJobId",
|
||||
table: "ReattachInformations",
|
||||
nullable: false,
|
||||
oldClrType: typeof(long),
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_ReattachInformations_CompileJobs_CompileJobId",
|
||||
table: "ReattachInformations",
|
||||
column: "CompileJobId",
|
||||
principalTable: "CompileJobs",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unapplies the migration
|
||||
/// </summary>
|
||||
/// <param name="migrationBuilder">The <see cref="MigrationBuilder"/> to use</param>
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_ReattachInformations_CompileJobs_CompileJobId",
|
||||
table: "ReattachInformations");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "CompileJobId",
|
||||
table: "ReattachInformations",
|
||||
nullable: true,
|
||||
oldClrType: typeof(long));
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_ReattachInformations_CompileJobs_CompileJobId",
|
||||
table: "ReattachInformations",
|
||||
column: "CompileJobId",
|
||||
principalTable: "CompileJobs",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,7 +290,7 @@ namespace Tgstation.Server.Host.Models.Migrations
|
||||
b.Property<string>("ChatCommandsJson")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long?>("CompileJobId");
|
||||
b.Property<long>("CompileJobId");
|
||||
|
||||
b.Property<bool>("IsPrimary");
|
||||
|
||||
@@ -575,7 +575,8 @@ namespace Tgstation.Server.Host.Models.Migrations
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
|
||||
.WithMany()
|
||||
.HasForeignKey("CompileJobId");
|
||||
.HasForeignKey("CompileJobId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
|
||||
|
||||
+3
-2
@@ -308,7 +308,7 @@ namespace Tgstation.Server.Host.Models.Migrations
|
||||
b.Property<string>("ChatCommandsJson")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<long?>("CompileJobId");
|
||||
b.Property<long>("CompileJobId");
|
||||
|
||||
b.Property<bool>("IsPrimary");
|
||||
|
||||
@@ -601,7 +601,8 @@ namespace Tgstation.Server.Host.Models.Migrations
|
||||
{
|
||||
b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
|
||||
.WithMany()
|
||||
.HasForeignKey("CompileJobId");
|
||||
.HasForeignKey("CompileJobId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Tgstation.Server.Host.Models
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Tgstation.Server.Host.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Database representation of <see cref="Components.Watchdog.ReattachInformation"/>
|
||||
@@ -13,6 +15,7 @@
|
||||
/// <summary>
|
||||
/// The <see cref="Models.CompileJob"/> for the <see cref="Components.Watchdog.ReattachInformation.Dmb"/>
|
||||
/// </summary>
|
||||
[Required]
|
||||
public CompileJob CompileJob { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ namespace Tgstation.Server.Host
|
||||
using (var cts = new CancellationTokenSource())
|
||||
{
|
||||
var cancellationToken = cts.Token;
|
||||
var eventsTask = Task.WhenAll(restartHandlers.Select(x => x.HandleRestart(newVersion, cancellationToken)));
|
||||
var eventsTask = Task.WhenAll(restartHandlers.Select(x => x.HandleRestart(newVersion, cancellationToken)).ToList());
|
||||
//YA GOT 10 SECONDS
|
||||
var expiryTask = Task.Delay(TimeSpan.FromSeconds(10));
|
||||
await Task.WhenAny(eventsTask, expiryTask).ConfigureAwait(false);
|
||||
|
||||
Reference in New Issue
Block a user