fix(clients): resolve 2026-06-18 array-write review findings
- Client.Dotnet-030: add advise-supervisory to IsKnownGatewayCommand (was dead/unreachable, exit 2) - Client.Go-035/036/037: usage+README list advise-supervisory; add session-id guard test; fix write2 README wording - Client.Python-037/038: drop regressed 'scaffold' from pyproject; add advise-supervisory CLI tests - Client.Rust-039/040: document write_array_elements/advise-supervisory in design doc; pin outer MxValue data_type==0 - Client.Java-049/050/051: sync CLIENT_VERSION to 0.1.2; add advise-supervisory test; guard negative uint32 inputs (pending windev gradle verification) Client READMEs also updated for Server-057 add-family normalization wording. .NET/Go/Python/Rust verified green locally; Java pending windev.
This commit is contained in:
@@ -196,10 +196,10 @@ the existing attribute value.
|
||||
|
||||
#### Bare-name array AddItem normalisation
|
||||
|
||||
`AddItem` for a bare array attribute name (e.g. `Tank01.Temperature`) is
|
||||
automatically normalised to `Tank01.Temperature[]` by the gateway so the
|
||||
worker can resolve the full array. You do not need to append `[]` in client
|
||||
code; the gateway handles it.
|
||||
Adding a bare array attribute name (e.g. `Tank01.Temperature`) via `AddItem`,
|
||||
`AddItem2`, `AddItemBulk`, or `AddBufferedItem` is automatically normalised to
|
||||
`Tank01.Temperature[]` by the gateway so the worker can resolve the full array.
|
||||
You do not need to append `[]` in client code; the gateway handles it.
|
||||
|
||||
## Galaxy Repository browse
|
||||
|
||||
|
||||
@@ -121,6 +121,7 @@ impl Session {
|
||||
pub async fn read_bulk<S: AsRef<str>>(&self, server_handle: i32, tag_addresses: &[S], timeout_ms: u32) -> Result<Vec<BulkReadResult>, Error>;
|
||||
pub async fn write(&self, server_handle: i32, item_handle: i32, value: MxValue, user_id: i32) -> Result<(), Error>;
|
||||
pub async fn write2(&self, server_handle: i32, item_handle: i32, value: MxValue, timestamp_value: MxValue, user_id: i32) -> Result<(), Error>;
|
||||
pub async fn write_array_elements(&self, server_handle: i32, item_handle: i32, element_data_type: MxDataType, total_length: u32, elements: impl IntoIterator<Item = (u32, MxValue)>, user_id: i32) -> Result<(), Error>;
|
||||
pub async fn write_bulk(&self, server_handle: i32, entries: Vec<WriteBulkEntry>) -> Result<Vec<BulkWriteResult>, Error>;
|
||||
pub async fn write2_bulk(&self, server_handle: i32, entries: Vec<Write2BulkEntry>) -> Result<Vec<BulkWriteResult>, Error>;
|
||||
pub async fn write_secured_bulk(&self, server_handle: i32, entries: Vec<WriteSecuredBulkEntry>) -> Result<Vec<BulkWriteResult>, Error>;
|
||||
@@ -333,6 +334,7 @@ mxgw close-session --session-id <id>
|
||||
mxgw register --session-id <id>
|
||||
mxgw add-item --session-id <id> --server-handle <h> --item <tag>
|
||||
mxgw advise --session-id <id> --server-handle <h> --item-handle <h>
|
||||
mxgw advise-supervisory --session-id <id> --server-handle <h> --item-handle <h>
|
||||
mxgw subscribe-bulk --session-id <id> --server-handle <h> --items <csv>
|
||||
mxgw unsubscribe-bulk --session-id <id> --server-handle <h> --item-handles <csv>
|
||||
mxgw read-bulk --session-id <id> --server-handle <h> --items <csv> [--timeout-ms <ms>]
|
||||
|
||||
@@ -1212,7 +1212,9 @@ fn sparse_int32_value(
|
||||
.collect();
|
||||
|
||||
MxValue {
|
||||
data_type: MxDataType::Integer as i32,
|
||||
// outer data_type must be 0 (Unspecified); the element type lives only
|
||||
// inside MxSparseArray.element_data_type, matching the
|
||||
// `..ProtoMxValue::default()` used in Session::write_array_elements.
|
||||
variant_type: String::new(),
|
||||
kind: Some(Kind::SparseArrayValue(MxSparseArray {
|
||||
element_data_type: MxDataType::Integer as i32,
|
||||
@@ -1227,6 +1229,11 @@ fn sparse_int32_value(
|
||||
fn write_array_elements_proto_shape_has_sparse_oneof_kind() {
|
||||
let proto = sparse_int32_value(5, [(0, 10), (3, 30)]);
|
||||
|
||||
assert_eq!(
|
||||
proto.data_type, 0,
|
||||
"outer MxValue.data_type must be 0 (Unspecified); element type lives in element_data_type"
|
||||
);
|
||||
|
||||
let Kind::SparseArrayValue(ref sparse) = proto.kind.as_ref().unwrap() else {
|
||||
panic!("expected SparseArrayValue kind, got {:?}", proto.kind);
|
||||
};
|
||||
@@ -1253,6 +1260,10 @@ fn write_array_elements_proto_shape_has_sparse_oneof_kind() {
|
||||
#[test]
|
||||
fn write_array_elements_empty_elements_is_valid_all_defaults() {
|
||||
let proto = sparse_int32_value(8, []);
|
||||
assert_eq!(
|
||||
proto.data_type, 0,
|
||||
"outer MxValue.data_type must be 0 (Unspecified) even with no elements"
|
||||
);
|
||||
let Kind::SparseArrayValue(ref sparse) = proto.kind.as_ref().unwrap() else {
|
||||
panic!("expected SparseArrayValue kind");
|
||||
};
|
||||
@@ -1269,6 +1280,10 @@ fn sparse_array_value_round_trips_through_client_mx_value_projection_as_unset()
|
||||
// (e.g. a future version bug), the projection should degrade to Unset
|
||||
// rather than panic, because the enum variant is not readable.
|
||||
let proto = sparse_int32_value(4, [(1, 99)]);
|
||||
assert_eq!(
|
||||
proto.data_type, 0,
|
||||
"outer MxValue.data_type must be 0 (Unspecified)"
|
||||
);
|
||||
let client_value = ClientMxValue::from_proto(proto);
|
||||
assert_eq!(
|
||||
client_value.projection(),
|
||||
|
||||
Reference in New Issue
Block a user