#pragma warning restore CA1506 /// <inheritdoc /> public async Task <ISessionController> Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken) { 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 { var byondLock = await byond.UseExecutables(Version.Parse(reattachInformation.Dmb.CompileJob.ByondVersion), cancellationToken).ConfigureAwait(false); try { var context = new CommContext(ioManager, loggerFactory.CreateLogger <CommContext>(), basePath, reattachInformation.ServerCommandsJson); try { var process = processExecutor.GetProcess(reattachInformation.ProcessId); if (process != null) { try { networkPromptReaper.RegisterProcess(process); result = new SessionController(reattachInformation, process, byondLock, byondTopicSender, chatJsonTrackingContext, context, chat, loggerFactory.CreateLogger <SessionController>(), null, null); process = null; context = null; byondLock = null; chatJsonTrackingContext = null; } finally { process?.Dispose(); } } } finally { context?.Dispose(); } } finally { byondLock?.Dispose(); } } finally { chatJsonTrackingContext?.Dispose(); } return(result); }
/// <inheritdoc /> public async Task <ReattachInformation> Load(CancellationToken cancellationToken) { Models.ReattachInformation result = null; TimeSpan?topicTimeout = null; await databaseContextFactory.UseContext(async (db) => { var dbReattachInfos = await db .ReattachInformations .AsQueryable() .Where(x => x.CompileJob.Job.Instance.Id == metadata.Id) .Include(x => x.CompileJob) .ToListAsync(cancellationToken).ConfigureAwait(false); result = dbReattachInfos.FirstOrDefault(); if (result == default) { return; } var timeoutMilliseconds = await db .Instances .AsQueryable() .Where(x => x.Id == metadata.Id) .Select(x => x.DreamDaemonSettings.TopicRequestTimeout) .FirstOrDefaultAsync(cancellationToken) .ConfigureAwait(false); if (timeoutMilliseconds == default) { logger.LogCritical("Missing TopicRequestTimeout!"); return; } topicTimeout = TimeSpan.FromMilliseconds(timeoutMilliseconds.Value); bool first = true; foreach (var reattachInfo in dbReattachInfos) { if (!first) { logger.LogWarning("Killing PID {0} associated with extra reattach information...", reattachInfo.ProcessId); try { using var process = processExecutor.GetProcess(reattachInfo.ProcessId); process.Terminate(); await process.Lifetime.ConfigureAwait(false); } catch (Exception ex) { logger.LogWarning(ex, "Failed to kill process!"); } } db.ReattachInformations.Remove(reattachInfo); first = false; } await db.Save(cancellationToken).ConfigureAwait(false); }).ConfigureAwait(false); if (!topicTimeout.HasValue) { logger.LogDebug("Reattach information not found!"); return(null); } var dmb = await dmbFactory.FromCompileJob(result.CompileJob, cancellationToken).ConfigureAwait(false); if (dmb == null) { logger.LogError("Unable to reattach! Could not load .dmb!"); return(null); } var info = new ReattachInformation( result, dmb, topicTimeout.Value); logger.LogDebug("Reattach information loaded: {0}", info); return(info); }