feat(headless): share immutable process content

This commit is contained in:
Erik 2026-07-27 08:37:24 +02:00
parent fbdb58a962
commit 12b500d383
11 changed files with 617 additions and 18 deletions

View file

@ -12,6 +12,7 @@ internal sealed class HeadlessProcessHost : IDisposable
private readonly HeadlessSessionHost[] _sessions;
private readonly HeadlessProcessScheduler _scheduler;
private readonly HeadlessDiagnosticWriter _diagnostics;
private readonly HeadlessProcessContentOwner? _content;
private int _disposeIndex;
private bool _disposed;
@ -21,7 +22,8 @@ internal sealed class HeadlessProcessHost : IDisposable
TextReader standardInput,
TextWriter diagnostics,
ILiveSessionOperations? sessionOperations = null,
TimeProvider? timeProvider = null)
TimeProvider? timeProvider = null,
IHeadlessProcessContentFactory? contentFactory = null)
{
ArgumentNullException.ThrowIfNull(configuration);
ArgumentNullException.ThrowIfNull(paths);
@ -39,8 +41,19 @@ internal sealed class HeadlessProcessHost : IDisposable
paths.ConfigDirectory);
var sessions = new List<HeadlessSessionHost>(
configuration.Sessions.Count);
HeadlessProcessContentOwner? content = null;
try
{
if (configuration.Process?.Content is { } contentDescriptor)
{
content = new HeadlessProcessContentOwner(
contentDescriptor,
message => _diagnostics.Message(
"process-content",
message),
contentFactory);
}
foreach (HeadlessSessionDescriptor? candidate
in configuration.Sessions)
{
@ -51,6 +64,8 @@ internal sealed class HeadlessProcessHost : IDisposable
credentials.Resolve(
descriptor.Id,
descriptor.Credential);
HeadlessProcessContentOwner.HeadlessProcessContentLease?
contentLease = content?.AcquireLease(descriptor.Id);
try
{
sessions.Add(new HeadlessSessionHost(
@ -58,10 +73,12 @@ internal sealed class HeadlessProcessHost : IDisposable
secret,
_diagnostics,
sessionOperations,
timeProvider));
timeProvider,
contentLease: contentLease));
}
catch
{
contentLease?.Dispose();
secret.Dispose();
throw;
}
@ -71,12 +88,14 @@ internal sealed class HeadlessProcessHost : IDisposable
_scheduler = new HeadlessProcessScheduler(
_sessions,
timeProvider);
_content = content;
_disposeIndex = _sessions.Length - 1;
}
catch
{
for (int index = sessions.Count - 1; index >= 0; index--)
sessions[index].Dispose();
content?.Dispose();
throw;
}
}
@ -88,6 +107,8 @@ internal sealed class HeadlessProcessHost : IDisposable
internal IReadOnlyList<HeadlessSessionHost> Sessions => _sessions;
internal HeadlessSchedulerSnapshot Scheduler =>
_scheduler.CaptureSnapshot();
internal HeadlessProcessContentSnapshot? Content =>
_content?.CaptureSnapshot();
internal async Task<HeadlessExitCode> RunAsync(
CancellationToken cancellationToken)
@ -141,6 +162,7 @@ internal sealed class HeadlessProcessHost : IDisposable
_sessions[_disposeIndex].Dispose();
_disposeIndex--;
}
_content?.Dispose();
_disposed = true;
}
}