diff --git a/lib/types/tunnelbroker/message-to-device-request-status-types.js b/lib/types/tunnelbroker/message-to-device-request-status-types.js index 53163a194..8d8410a10 100644 --- a/lib/types/tunnelbroker/message-to-device-request-status-types.js +++ b/lib/types/tunnelbroker/message-to-device-request-status-types.js @@ -1,56 +1,60 @@ // @flow import type { TInterface } from 'tcomb'; import t from 'tcomb'; import { tShape, tString } from '../../utils/validation-utils.js'; export type Failure = { +id: string, +error: string, }; const failureValidator: TInterface = tShape({ id: t.String, error: t.String, }); type MessageSentSuccessStatus = { +type: 'Success', +data: string }; type MessageSentErrorStatus = { +type: 'Error', +data: Failure }; type MessageSentInvalidRequestStatus = { +type: 'InvalidRequest' }; +type MessageSentUnauthenticatedStatus = { +type: 'Unauthenticated' }; type MessageSentSerializationErrorStatus = { +type: 'SerializationError', +data: string, }; export type MessageSentStatus = | MessageSentSuccessStatus | MessageSentErrorStatus | MessageSentInvalidRequestStatus | MessageSentSerializationErrorStatus; const messageSentStatusValidator = t.union([ tShape({ type: tString('Success'), data: t.String, }), tShape({ type: tString('Error'), data: failureValidator, }), tShape({ type: tString('InvalidRequest') }), + tShape({ + type: tString('Unauthenticated'), + }), tShape({ type: tString('SerializationError'), data: t.String, }), ]); export type MessageToDeviceRequestStatus = { +type: 'MessageToDeviceRequestStatus', +clientMessageIDs: $ReadOnlyArray, }; export const messageToDeviceRequestStatusValidator: TInterface = tShape({ type: tString('MessageToDeviceRequestStatus'), clientMessageIDs: t.list(messageSentStatusValidator), }); diff --git a/shared/tunnelbroker_messages/src/messages/message_to_device_request_status.rs b/shared/tunnelbroker_messages/src/messages/message_to_device_request_status.rs index 564bd0c6f..a9a51ef3c 100644 --- a/shared/tunnelbroker_messages/src/messages/message_to_device_request_status.rs +++ b/shared/tunnelbroker_messages/src/messages/message_to_device_request_status.rs @@ -1,88 +1,92 @@ //! Message sent from Tunnelbroker to WebSocket clients to inform that message //! was processed, saved in DDB, and will be delivered. use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, PartialEq, Debug)] pub struct Failure { pub id: String, pub error: String, } +// NOTE: Keep this in sync with +// lib/types/tunnelbroker/message-to-device-request-status-types.js #[derive(Serialize, Deserialize, PartialEq, Debug)] #[serde(tag = "type", content = "data")] pub enum MessageSentStatus { /// The message with the provided ID (String) has been processed /// by the Tunnelbroker and is queued for delivery. Success(String), /// 'Failure' contains information about the message ID /// along with the specific error message. Error(Failure), /// The request was invalid (e.g., Bytes instead of Text). /// In this case, the ID cannot be retrieved. InvalidRequest, /// Unauthenticated client tried to send a message. Unauthenticated, /// The JSON could not be serialized, which is why the entire message is /// returned back. /// It becomes impossible to retrieve the message ID in such circumstances. SerializationError(String), } +// NOTE: Keep this in sync with +// lib/types/tunnelbroker/message-to-device-request-status-types.js #[derive(Serialize, Deserialize, PartialEq, Debug)] #[serde(tag = "type", rename_all = "camelCase")] pub struct MessageToDeviceRequestStatus { #[serde(rename = "clientMessageIDs")] pub client_message_ids: Vec, } #[cfg(test)] mod send_confirmation_tests { use super::*; #[test] fn test_send_confirmation_deserialization() { let example_payload = r#"{ "type": "MessageToDeviceRequestStatus", "clientMessageIDs": [ {"type": "Success", "data": "id123"}, {"type": "Success", "data": "id456"}, {"type": "Error", "data": {"id": "id789", "error": "Something went wrong"}}, {"type": "SerializationError", "data": "message"}, {"type": "InvalidRequest"} ] }"#; let request = serde_json::from_str::(example_payload) .unwrap(); let expected_client_message_ids = vec![ MessageSentStatus::Success("id123".to_string()), MessageSentStatus::Success("id456".to_string()), MessageSentStatus::Error(Failure { id: String::from("id789"), error: String::from("Something went wrong"), }), MessageSentStatus::SerializationError("message".to_string()), MessageSentStatus::InvalidRequest, ]; assert_eq!(request.client_message_ids, expected_client_message_ids); } #[test] fn test_send_confirmation_deserialization_empty_vec() { let example_payload = r#"{ "type": "MessageToDeviceRequestStatus", "clientMessageIDs": [] }"#; let request = serde_json::from_str::(example_payload) .unwrap(); let expected_client_message_ids: Vec = Vec::new(); assert_eq!(request.client_message_ids, expected_client_message_ids); } }