feat(worker): correlate OnWriteComplete onto plain Write/Write2 replies (06/S-1 follow-up)
OtOpcUa's dominant FreeAccess write path goes out as MX_COMMAND_KIND_WRITE, not WriteSecured — the original 06/S-1 brief mis-scoped the correlation, so a refused plain write was invisible on the unary reply (verified live on windev 2026-08-09). ExecuteWrite/ExecuteWrite2 now use the same pre-call version baseline + bounded pump-wait as the secured kinds. Bulk writes stay fire-and-forget.
This commit is contained in:
@@ -8012,6 +8012,11 @@ namespace ZB.MOM.WW.MxGateway.Contracts.Proto {
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The unary reply's statuses field carries the correlated OnWriteComplete
|
||||
/// outcome when it arrives within the worker's bounded wait — see
|
||||
/// MxCommandReply.statuses.
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")]
|
||||
public sealed partial class WriteCommand : pb::IMessage<WriteCommand>
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
@@ -8330,6 +8335,9 @@ namespace ZB.MOM.WW.MxGateway.Contracts.Proto {
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Same statuses correlation as WriteCommand.
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")]
|
||||
public sealed partial class Write2Command : pb::IMessage<Write2Command>
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
@@ -17215,18 +17223,19 @@ namespace ZB.MOM.WW.MxGateway.Contracts.Proto {
|
||||
= pb::FieldCodec.ForMessage(58, global::ZB.MOM.WW.MxGateway.Contracts.Proto.MxStatusProxy.Parser);
|
||||
private readonly pbc::RepeatedField<global::ZB.MOM.WW.MxGateway.Contracts.Proto.MxStatusProxy> statuses_ = new pbc::RepeatedField<global::ZB.MOM.WW.MxGateway.Contracts.Proto.MxStatusProxy>();
|
||||
/// <summary>
|
||||
/// Correlated per-item outcome rows. For WRITE_SECURED / WRITE_SECURED2
|
||||
/// replies the worker holds the reply for a bounded window (default 1.5 s,
|
||||
/// MXGATEWAY_WORKER_WRITE_COMPLETION_WAIT_MS) waiting for the matching
|
||||
/// MXAccess OnWriteComplete callback and copies its status rows here, so
|
||||
/// statuses[0] carries the real MXAccess commit outcome (success OR failure)
|
||||
/// while protocol_status/hresult still describe command acceptance only.
|
||||
/// Empty statuses on a write reply means the completion did not arrive
|
||||
/// Correlated per-item outcome rows. For WRITE / WRITE2 / WRITE_SECURED /
|
||||
/// WRITE_SECURED2 replies the worker holds the reply for a bounded window
|
||||
/// (default 1.5 s, MXGATEWAY_WORKER_WRITE_COMPLETION_WAIT_MS) waiting for
|
||||
/// the matching MXAccess OnWriteComplete callback and copies its status rows
|
||||
/// here, so statuses[0] carries the real MXAccess commit outcome (success OR
|
||||
/// failure) while protocol_status/hresult still describe command acceptance
|
||||
/// only. Empty statuses on a write reply means the completion did not arrive
|
||||
/// within the window — the write is unconfirmed, not failed. Correlation is
|
||||
/// best-effort per (server_handle, item_handle): MXAccess's callback carries
|
||||
/// no transaction id, so concurrent writes to the same item within the
|
||||
/// window can swap rows. The OnWriteComplete event still flows on the event
|
||||
/// stream unchanged. Other command kinds leave this field as before.
|
||||
/// stream unchanged. Bulk write kinds and all non-write kinds leave this
|
||||
/// field as before.
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
|
||||
Reference in New Issue
Block a user