perf(adminui): pooled DbContext factory; role-grants reads per-call, not per-circuit

This commit is contained in:
Joseph Doherty
2026-08-16 04:05:34 -04:00
parent 34f836e03c
commit 140bf0c131
11 changed files with 346 additions and 50 deletions
@@ -240,6 +240,7 @@ public sealed class ContinuousHistorizationRecorder : ReceiveActor, IWithTimers
_maxWriteAttempts = maxWriteAttempts > 0 ? maxWriteAttempts : 1;
ReceiveAsync<VirtualTagActor.DependencyValueChanged>(OnValueChangedAsync);
ReceiveAsync<VirtualTagActor.DependencyValueBatch>(OnValueBatchAsync);
Receive<UpdateHistorizedRefs>(OnUpdateHistorizedRefs);
Receive<DrainTick>(_ => OnDrainTick());
Receive<DrainResult>(OnDrainResult);
@@ -275,6 +276,30 @@ public sealed class ContinuousHistorizationRecorder : ReceiveActor, IWithTimers
base.PostStop();
}
/// <summary>
/// The mux's batched delivery: one message carrying this recorder's whole matched slice of a driver
/// burst. Each item is appended by the existing per-value handler, in order — the saving here is the
/// mailbox hop, not the append (a genuinely batched append is a later change).
/// <para>
/// ⚠️ The await below deliberately does NOT use <c>ConfigureAwait(false)</c>. <see
/// cref="OnValueChangedAsync"/> reads <c>Self</c> before its own first await, so it must start
/// each item ON the actor thread; a context-dropping await here would leave item 2 onward with
/// no ActorContext and throw <c>NotSupportedException</c> — the Gitea #491 failure, which
/// supervision turns into a restart that silently discards every historized ref. A plain await
/// resumes on Akka's ActorTaskScheduler context, so the context is restored before the next
/// iteration.
/// </para>
/// </summary>
/// <param name="msg">The batch of matched dependency values.</param>
private async Task OnValueBatchAsync(VirtualTagActor.DependencyValueBatch msg)
{
IReadOnlyList<VirtualTagActor.DependencyValueChanged> items = msg.Items;
for (int i = 0; i < items.Count; i++)
{
await OnValueChangedAsync(items[i]);
}
}
private async Task OnValueChangedAsync(VirtualTagActor.DependencyValueChanged msg)
{
// The mux fans values keyed by the driver ref (msg.TagId == the mux ref). Only historize refs we