fix(inbound): single-flight method compile so concurrent first callers share one assembly (review 2026-10-21 05/M1)

This commit is contained in:
Joseph Doherty
2026-10-22 08:28:34 -04:00
parent 37c25db2f1
commit d7e87c0688
2 changed files with 58 additions and 2 deletions
@@ -514,6 +514,37 @@ public class InboundScriptExecutorTests
Assert.Empty(errors);
}
/// <summary>Verifies that concurrent first callers of a new method share a single compile.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ExecuteAsync_ConcurrentFirstCallers_ShareOneCompile()
{
// Review 2026-10-21 05/M1: N concurrent first-callers used to each run Roslyn (N
// non-collectible loaded assemblies for one revision). Single-flight per name+revision.
var logger = new CompileCountingLogger();
var executor = new InboundScriptExecutor(logger, Substitute.For<IServiceProvider>());
var method = new ApiMethod("burst", "var x = 0; for (int i = 0; i < 10; i++) x += i; return x;") { Id = 1, TimeoutSeconds = 30 };
var results = await Task.WhenAll(Enumerable.Range(0, 12).Select(_ => Task.Run(() =>
executor.ExecuteAsync(method, new Dictionary<string, object?>(), _route, TimeSpan.FromSeconds(30)))));
Assert.All(results, r => Assert.True(r.Success, r.ErrorMessage));
Assert.Equal(1, logger.CompileCount);
}
private sealed class CompileCountingLogger : ILogger<InboundScriptExecutor>
{
private int _count;
public int CompileCount => _count;
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null;
public bool IsEnabled(LogLevel logLevel) => true;
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
if (formatter(state, exception).EndsWith("script compiled", StringComparison.Ordinal))
Interlocked.Increment(ref _count);
}
}
/// <summary>Verifies that executing after a non-compiling update surfaces the compile failure.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]