Usando as APIs de mensagens - AWS SimSpace Weaver

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Usando as APIs de mensagens

As APIs de mensagens estão contidas no SDK do SimSpace Weaver aplicativo (versão mínima 1.16.0). O sistema de mensagens é compatível com C++, Python e nossas integrações com o Unreal Engine 5 e o Unity.

Há duas funções que lidam com transações de mensagens: SendMessage ReceiveMessages e. Todas as mensagens enviadas contêm um destino e uma carga útil. A ReceiveMessages API retorna uma lista das mensagens atualmente na fila de mensagens de entrada de um aplicativo.

C++

Enviar mensagem

AWS_WEAVERRUNTIME_API Result<void> SendMessage( Transaction& txn, const MessagePayload& payload, const MessageEndpoint& destination, MessageDeliveryType deliveryType = MessageDeliveryType::BestEffort ) noexcept;

Receba mensagens

AWS_WEAVERRUNTIME_API Result<MessageList> ReceiveMessages( Transaction& txn) noexcept;
Python

Enviar mensagem

api.send_message( txn, # Transaction payload, # api.MessagePayload destination, # api.MessageDestination api.MessageDeliveryType.BestEffort # api.MessageDeliveryType )

Receba mensagens

api.receive_messages( txn, # Transaction ) -> api.MessageList

Enviar mensagens

As mensagens consistem em uma transação (semelhante a outras chamadas da API Weaver), uma carga útil e um destino.

Carga útil da mensagem

A carga útil da mensagem é uma estrutura de dados flexível de até 256 bytes. Recomendamos o seguinte como uma prática recomendada para criar suas cargas de mensagens.

Para criar a carga útil da mensagem
  1. Crie uma estrutura de dados (como a struct em C++) que defina o conteúdo da mensagem.

  2. Crie a carga útil da mensagem que contém os valores a serem enviados em sua mensagem.

  3. Crie o MessagePayload objeto.

Destino da mensagem

O destino de uma mensagem é definido pelo MessageEndpoint objeto. Isso inclui um tipo de endpoint e uma ID de endpoint. O único tipo de endpoint atualmente suportado éPartition, que permite endereçar mensagens para outras partições na simulação. O ID do endpoint é o ID da partição do seu destino.

Você só pode fornecer 1 endereço de destino em uma mensagem. Crie e envie várias mensagens se quiser enviar mensagens para mais de uma partição ao mesmo tempo.

Para obter orientação sobre como resolver um endpoint de mensagem a partir de uma posição, consulteDicas para trabalhar com mensagens.

Envie a mensagem

Você pode usar a SendMessage API depois de criar os objetos de destino e de carga útil.

C++
Api::SendMessage(transaction, payload, destination, MessageDeliveryType::BestEffort);
Python
api.send_message(txn, payload, destination, api.MessageDeliveryType.BestEffort)
Exemplo completo de envio de mensagens

O exemplo a seguir demonstra como você pode criar e enviar uma mensagem genérica. Este exemplo envia 16 mensagens individuais. Cada mensagem contém uma carga útil com um valor entre 0 e 15 e a marca de simulação atual.

C++
// Message struct definition struct MessageTickAndId { uint32_t id; uint32_t tick; }; Aws::WeaverRuntime::Result<void> SendMessages(Txn& txn) noexcept { // Fetch the destination MessageEndpoint with the endpoint resolver WEAVERRUNTIME_TRY( Api::MessageEndpoint destination, Api::Utils::MessageEndpointResolver::ResolveFromPosition( txn, "MySpatialSimulation", Api::Vector2F32 {231.3, 654.0} ) ); Log::Info("destination: ", destination); WEAVERRUNTIME_TRY(auto tick, Api::CurrentTick(txn)); uint16_t numSentMessages = 0; for (std::size_t i=0; i<16; i++) { // Create the message that'll be serialized into payload MessageTickAndId message {i, tick.value}; // Create the payload out of the struct const Api::MessagePayload& payload = Api::Utils::CreateMessagePayload( reinterpret_cast<const std::uint8_t*>(&message), sizeof(MessageTickAndId) ); // Send the payload to the destination Result<void> result = Api::SendMessage(txn, payload, destination); if (result.has_failure()) { // SendMessage has failure modes, log them auto error = result.as_failure().error(); std::cout<< "SendMessage failed, ErrorCode: " << error << std::endl; continue; } numSentMessages++; } std::cout << numSentMessages << " messages is sent to endpoint" << destination << std::endl; return Aws::WeaverRuntime::Success(); }
Python
# Message data class @dataclasses.dataclass class MessageTickAndId: tick: int = 0 id: int = 0 # send messages def _send_messages(self, txn): tick = api.current_tick(txn) num_messages_to_send = 16 # Fetch the destination MessageEndpoint with the endpoint resolver destination = api.utils.resolve_endpoint_from_domain_name_position( txn, "MySpatialSimulation", pos ) Log.debug("Destination_endpoint = %s", destination_endpoint) for id in range(num_messages_to_send): # Message struct that'll be serialized into payload message_tick_and_id = MessageTickAndId(id = id, tick = tick.value) # Create the payload out of the struct message_tick_and_id_data = struct.pack( '<ii', message_tick_and_id.id, message_tick_and_id.tick ) payload = api.MessagePayload(list(message_tick_and_id_data)) # Send the payload to the destination Log.debug("Sending message: %s, endpoint: %s", message_tick_and_id, destination ) api.send_message( txn, payload, destination, api.MessageDeliveryType.BestEffort ) Log.info("Sent %s messages to %s", num_messages_to_send, destination) return True

Recebimento de mensagens

SimSpace Weaverentrega mensagens na fila de mensagens de entrada de uma partição. Use a ReceiveMessages API para obter um MessageList objeto que contém as mensagens da fila. Processe cada mensagem com a ExtractMessage API para obter os dados da mensagem.

C++
Result<void> ReceiveMessages(Txn& txn) noexcept { // Fetch all the messages sent to the partition owned by the app WEAVERRUNTIME_TRY(auto messages, Api::ReceiveMessages(txn)); std::cout << "Received" << messages.messages.size() << " messages" << std::endl; for (Api::Message& message : messages.messages) { std::cout << "Received message: " << message << std::endl; // Deserialize payload to the message struct const MessageTickAndId& receivedMessage = Api::Utils::ExtractMessage<MessageTickAndId>(message); std::cout << "Received MessageTickAndId, Id: " << receivedMessage.id <<", Tick: " << receivedMessage.tick << std::endl; } return Aws::WeaverRuntime::Success(); }
Python
# process incoming messages def _process_incoming_messages(self, txn): messages = api.receive_messages(txn) for message in messages: payload_list = message.payload.data payload_bytes = bytes(payload_list) message_tick_and_id_data_struct = MessageTickAndId(*struct.unpack('<ii', payload_bytes)) Log.debug("Received message. Header: %s, message: %s", message.header, message_tick_and_id_data_struct) Log.info("Received %s messages", len(messages)) return True

Respondendo ao remetente

Cada mensagem recebida contém um cabeçalho com informações sobre o remetente original da mensagem. Você pode usar o message.header.source_endpoint para enviar uma resposta.

C++
Result<void> ReceiveMessages(Txn& txn) noexcept { // Fetch all the messages sent to the partition owned by the app WEAVERRUNTIME_TRY(auto messages, Api::ReceiveMessages(txn)); std::cout << "Received" << messages.messages.size() << " messages" << std::endl; for (Api::Message& message : messages.messages) { std::cout << "Received message: " << message << std::endl; // Deserialize payload to the message struct const MessageTickAndId& receivedMessage = Api::Utils::ExtractMessage<MessageTickAndId>(message); std::cout << "Received MessageTickAndId, Id: " << receivedMessage.id <<", Tick: " << receivedMessage.tick << std::endl; // Get the sender endpoint and payload to bounce the message back Api::MessageEndpoint& sender = message.header.source_endpoint; Api::MessagePayload& payload = message.payload; Api::SendMessage(txn, payload, sender); } return Aws::WeaverRuntime::Success(); }
Python
# process incoming messages def _process_incoming_messages(self, txn): messages = api.receive_messages(txn) for message in messages: payload_list = message.payload.data payload_bytes = bytes(payload_list) message_tick_and_id_data_struct = MessageTickAndId(*struct.unpack('<ii', payload_bytes)) Log.debug("Received message. Header: %s, message: %s", message.header, message_tick_and_id_data_struct) # Get the sender endpoint and payload # to bounce the message back sender = message.header.source_endpoint payload = payload_list api.send_message( txn, payload_list, sender, api.MessageDeliveryType.BestEffort Log.info("Received %s messages", len(messages)) return True