refactor(runtime): capture-first in HandleWriteAsync; assert no handler leak on resubscribe; fix stale comment
This commit is contained in:
@@ -88,9 +88,10 @@ public sealed class DriverInstanceActor : ReceiveActor, IWithTimers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Queue<DateTime> _faultTimestamps = new();
|
private readonly Queue<DateTime> _faultTimestamps = new();
|
||||||
|
|
||||||
/// <summary>Active subscription handle (null when not subscribed). Lifetime is one-per-actor —
|
/// <summary>Active subscription handle (null when not subscribed). Tracks the current live
|
||||||
/// re-subscribe across reconnects is the consumer's responsibility today (subscribe-once
|
/// subscription; the actor auto-(re)subscribes on (re)connect and on each <see cref="Subscribe"/>
|
||||||
/// semantics keep the actor simple; mux-driven re-subscribe is tracked as F8b/#113).</summary>
|
/// message via <see cref="ResubscribeDesired"/> / <see cref="HandleSubscribeAsync"/>, so callers
|
||||||
|
/// do not need to re-send subscription requests after a reconnect.</summary>
|
||||||
private ISubscriptionHandle? _subscriptionHandle;
|
private ISubscriptionHandle? _subscriptionHandle;
|
||||||
private EventHandler<DataChangeEventArgs>? _dataChangeHandler;
|
private EventHandler<DataChangeEventArgs>? _dataChangeHandler;
|
||||||
|
|
||||||
@@ -314,13 +315,13 @@ public sealed class DriverInstanceActor : ReceiveActor, IWithTimers
|
|||||||
|
|
||||||
private async Task HandleWriteAsync(WriteAttribute msg)
|
private async Task HandleWriteAsync(WriteAttribute msg)
|
||||||
{
|
{
|
||||||
|
var replyTo = Sender;
|
||||||
if (_driver is not IWritable writable)
|
if (_driver is not IWritable writable)
|
||||||
{
|
{
|
||||||
Sender.Tell(new WriteAttributeResult(false, "Driver does not implement IWritable"));
|
replyTo.Tell(new WriteAttributeResult(false, "Driver does not implement IWritable"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var replyTo = Sender;
|
|
||||||
var request = new[] { new WriteRequest(msg.TagId, msg.Value) };
|
var request = new[] { new WriteRequest(msg.TagId, msg.Value) };
|
||||||
// Bound the write so a hung backend can't pin this actor forever — decision #44/#45 keeps
|
// Bound the write so a hung backend can't pin this actor forever — decision #44/#45 keeps
|
||||||
// retry off by default, but a stalled call still needs an answer.
|
// retry off by default, but a stalled call still needs an answer.
|
||||||
|
|||||||
@@ -215,6 +215,8 @@ public sealed class DriverInstanceActorTests : RuntimeActorTestBase
|
|||||||
|
|
||||||
reply.ReferenceCount.ShouldBe(2);
|
reply.ReferenceCount.ShouldBe(2);
|
||||||
driver.SubscribeCount.ShouldBe(2);
|
driver.SubscribeCount.ShouldBe(2);
|
||||||
|
// Old handler must have been detached before the new one was attached — no leak.
|
||||||
|
driver.OnDataChangeSubscriberCount.ShouldBe(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Verifies that subscribing to a non-ISubscribable driver replies with failure.</summary>
|
/// <summary>Verifies that subscribing to a non-ISubscribable driver replies with failure.</summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user