4using System.Threading.Tasks;
6using Microsoft.EntityFrameworkCore;
7using Microsoft.Extensions.Logging;
13using Z.EntityFramework.Plus;
38 readonly ILogger<SessionPersistor>
logger;
57 ILogger<SessionPersistor>
logger,
63 this.logger =
logger ??
throw new ArgumentNullException(nameof(
logger));
64 this.metadata =
metadata ??
throw new ArgumentNullException(nameof(
metadata));
70 ArgumentNullException.ThrowIfNull(reattachInformation);
72 logger.LogDebug(
"Saving reattach information: {info}...", reattachInformation);
74 await
ClearImpl(db,
false, cancellationToken);
79 CompileJobId = reattachInformation.Dmb.CompileJob.Id.Value,
80 InitialCompileJobId = reattachInformation.InitialDmb?.CompileJob.Id.Value,
81 Port = reattachInformation.Port,
82 ProcessId = reattachInformation.ProcessId,
84 LaunchSecurityLevel = reattachInformation.LaunchSecurityLevel,
85 LaunchVisibility = reattachInformation.LaunchVisibility,
88 db.ReattachInformations.Add(dbReattachInfo);
89 await db.Save(cancellationToken);
93 public async Task<ReattachInformation>
Load(CancellationToken cancellationToken)
96 TimeSpan? topicTimeout =
null;
98 async Task KillProcess(Models.ReattachInformation reattachInfo)
105 if (reattachInfo == result)
107 logger.LogWarning(
"Killing PID {pid} associated with CompileJob-less reattach information...", reattachInfo.ProcessId);
111 logger.LogWarning(
"Killing PID {pid} associated with extra reattach information...", reattachInfo.ProcessId);
115 await process.Lifetime;
120 logger.LogWarning(ex,
"Failed to kill process!");
126 var dbReattachInfos = await db
127 .ReattachInformations
129 .Where(x => x.CompileJob.Job.Instance.Id ==
metadata.Id)
130 .Include(x => x.CompileJob)
131 .Include(x => x.InitialCompileJob)
132 .ToListAsync(cancellationToken);
133 result = dbReattachInfos.FirstOrDefault();
134 if (result ==
default)
137 var timeoutMilliseconds = await db
141 .Select(x => x.DreamDaemonSettings.TopicRequestTimeout)
142 .FirstOrDefaultAsync(cancellationToken);
144 if (timeoutMilliseconds ==
default)
146 logger.LogCritical(
"Missing TopicRequestTimeout!");
150 topicTimeout = TimeSpan.FromMilliseconds(timeoutMilliseconds.Value);
153 foreach (var reattachInfo in dbReattachInfos)
161 await KillProcess(reattachInfo);
163 db.ReattachInformations.Remove(reattachInfo);
164 logger.LogTrace(
"Deleting ReattachInformation {id}...", reattachInfo.Id);
167 await db.Save(cancellationToken);
170 if (!topicTimeout.HasValue)
172 logger.LogDebug(
"Reattach information not found!");
179 logger.LogError(
"Unable to reattach! Could not load .dmb!");
180 await KillProcess(result);
184 logger.LogTrace(
"Deleting ReattachInformation {id}...", result.
Id);
186 .ReattachInformations
188 .Where(x => x.Id == result.
Id)
189 .DeleteAsync(cancellationToken);
197 logger.LogTrace(
"Loading initial compile job...");
201 logger.LogTrace(
"Retrieved ReattachInformation");
209 logger.LogDebug(
"Reattach information loaded: {info}", info);
219 logger.LogDebug(
"Clearing reattach information");
220 return ClearImpl(db,
true, cancellationToken);
232 var baseQuery = databaseContext
235 .Where(x => x.CompileJob.Job.Instance.Id ==
metadata.Id);
239 .DeleteAsync(cancellationToken);
242 var results = await baseQuery.ToListAsync(cancellationToken);
243 foreach (var result
in results)
Metadata about a server instance.
string AccessIdentifier
Used to identify and authenticate the DreamDaemon instance.
readonly ILogger< SessionPersistor > logger
The ILogger for the SessionPersistor.
readonly IProcessExecutor processExecutor
The IProcessExecutor for the SessionPersistor.
async Task< ReattachInformation > Load(CancellationToken cancellationToken)
Load a saved ReattachInformation. A Task<TResult> resulting in the stored ReattachInformation if any.
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the SessionPersistor.
readonly Api.Models.Instance metadata
The Api.Models.Instance for the SessionPersistor.
Task Save(ReattachInformation reattachInformation, CancellationToken cancellationToken)
Save some reattachInformation . A Task representing the running operation.
readonly IDmbFactory dmbFactory
The IDmbFactory for the SessionPersistor.
async Task ClearImpl(IDatabaseContext databaseContext, bool instant, CancellationToken cancellationToken)
Clear any stored ReattachInformation.
SessionPersistor(IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory, IProcessExecutor processExecutor, ILogger< SessionPersistor > logger, Api.Models.Instance metadata)
Initializes a new instance of the SessionPersistor class.
Task Clear(CancellationToken cancellationToken)
Clear any stored ReattachInformation. A Task representing the running operation.
Factory for IDmbProviders.
Task< IDmbProvider > FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Gets a IDmbProvider for a given CompileJob.
Provides absolute paths to the latest compiled .dmbs.
Handles saving and loading ReattachInformation.
void Remove(TModel model)
Remove a given model from the the working set.
Factory for scoping usage of IDatabaseContexts. Meant for use by Components.
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext.
IDatabaseCollection< ReattachInformation > ReattachInformations
The DbSet<TEntity> for ReattachInformations.
IProcess GetProcess(int id)
Get a IProcess by id .
RebootState
Represents the action to take when /world/Reboot() is called.