mirror of
https://github.com/fluencelabs/aquavm
synced 2024-12-04 23:20:18 +00:00
feat(interface)!: Use MessagePack for calls (#780)
Top-level structs use multicodec-prefixed MessagePack, the nested structures (arguments, tetraplets) use just ordinary MessagePack. * JS-compatible `CallResults` Binary format implementations like `rmp-serde` do not bother converting keys from strings, unlike `serde_json`. So, we use `CallResults` with string keys, as JS client cannot produce anything else. --------- Co-authored-by: Mike Voronov <michail.vms@gmail.com>
This commit is contained in:
parent
ccb8f025b7
commit
325eea7e91
@ -80,7 +80,9 @@ pub(super) fn handle_prev_state<'i>(
|
|||||||
RequestSentBy(Sender::PeerIdWithCallId { ref peer_id, call_id })
|
RequestSentBy(Sender::PeerIdWithCallId { ref peer_id, call_id })
|
||||||
if peer_id.as_str() == exec_ctx.run_parameters.current_peer_id.as_str() =>
|
if peer_id.as_str() == exec_ctx.run_parameters.current_peer_id.as_str() =>
|
||||||
{
|
{
|
||||||
// call results are identified by call_id that is saved in data
|
// call results are identified by call_id that is saved in data;
|
||||||
|
// for compatiblity with JavaScript with binary formats, string IDs are used
|
||||||
|
let call_id = call_id.to_string();
|
||||||
match exec_ctx.call_results.remove(&call_id) {
|
match exec_ctx.call_results.remove(&call_id) {
|
||||||
Some(call_result) => {
|
Some(call_result) => {
|
||||||
update_state_with_service_result(
|
update_state_with_service_result(
|
||||||
|
@ -35,7 +35,7 @@ fn unprocessed_call_result() {
|
|||||||
|
|
||||||
let expected_call_service_result = air_interpreter_interface::CallServiceResult::ok(&json!("null"));
|
let expected_call_service_result = air_interpreter_interface::CallServiceResult::ok(&json!("null"));
|
||||||
let expected_call_results = maplit::hashmap!(
|
let expected_call_results = maplit::hashmap!(
|
||||||
70 => expected_call_service_result,
|
"70".to_owned() => expected_call_service_result,
|
||||||
);
|
);
|
||||||
let expected_error = FarewellError::UnprocessedCallResult(expected_call_results);
|
let expected_error = FarewellError::UnprocessedCallResult(expected_call_results);
|
||||||
assert!(check_error(&result, expected_error));
|
assert!(check_error(&result, expected_error));
|
||||||
|
@ -15,16 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { CallResultsArray, InterpreterResult, CallRequest, RunParameters, JSONArray, JSONObject } from './types';
|
import { CallResultsArray, InterpreterResult, CallRequest, RunParameters, JSONArray, JSONObject } from './types';
|
||||||
import { JsonRepr } from './formats'
|
import { MulticodecRepr, MsgPackRepr } from './formats'
|
||||||
|
|
||||||
// Have to match the air-interpreter-interface.
|
// Have to match the air-interpreter-interface.
|
||||||
const callRequestsRepr = new JsonRepr();
|
const callRequestsRepr = new MulticodecRepr(new MsgPackRepr());
|
||||||
// Have to match the air-interpreter-interface.
|
// Have to match the air-interpreter-interface.
|
||||||
const argumentRepr = new JsonRepr();
|
const argumentRepr = new MsgPackRepr();
|
||||||
// Have to match the air-interpreter-interface.
|
// Have to match the air-interpreter-interface.
|
||||||
const tetrapletRepr = new JsonRepr();
|
const tetrapletRepr = new MsgPackRepr();
|
||||||
// Have to match the air-interpreter-interface.
|
// Have to match the air-interpreter-interface.
|
||||||
const callResultsRepr = new JsonRepr();
|
const callResultsRepr = new MulticodecRepr(new MsgPackRepr());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes arguments into JSON array suitable for marine-js
|
* Encodes arguments into JSON array suitable for marine-js
|
||||||
|
@ -93,7 +93,7 @@ export class MulticodecRepr implements Representation {
|
|||||||
|
|
||||||
toBinary(obj: object): Uint8Array {
|
toBinary(obj: object): Uint8Array {
|
||||||
let bareData = this.serializer.toBinary(obj);
|
let bareData = this.serializer.toBinary(obj);
|
||||||
let varintCode = multicodec.getVarintFromCode(this.serializer.get_code());
|
let codeName = multicodec.getNameFromCode(this.serializer.get_code());
|
||||||
return multicodec.addPrefix(varintCode, bareData)
|
return multicodec.addPrefix(codeName, bareData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ impl CallServiceResult {
|
|||||||
pub fn into_raw_result(call_results: CallResults) -> air_interpreter_interface::CallResults {
|
pub fn into_raw_result(call_results: CallResults) -> air_interpreter_interface::CallResults {
|
||||||
call_results
|
call_results
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(call_id, call_result)| (call_id, call_result.into_raw()))
|
.map(|(call_id, call_result)| (call_id.to_string(), call_result.into_raw()))
|
||||||
.collect::<_>()
|
.collect::<_>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -17,7 +17,7 @@ path = "src/lib.rs"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
marine-rs-sdk = {version = "0.10.2", optional = true }
|
marine-rs-sdk = {version = "0.10.2", optional = true }
|
||||||
fluence-it-types = { version = "0.4.1", optional = true }
|
fluence-it-types = { version = "0.4.1", optional = true }
|
||||||
air-interpreter-sede = { version = "0.1.0", path = "../interpreter-sede", features = ["json"] }
|
air-interpreter-sede = { version = "0.1.0", path = "../interpreter-sede", features = ["msgpack"] }
|
||||||
|
|
||||||
marine-call-parameters = { version = "0.10.3", default-features = false }
|
marine-call-parameters = { version = "0.10.3", default-features = false }
|
||||||
serde = "1.0.190"
|
serde = "1.0.190"
|
||||||
|
@ -18,7 +18,8 @@ use air_interpreter_sede::define_simple_representation;
|
|||||||
use air_interpreter_sede::derive_serialized_type;
|
use air_interpreter_sede::derive_serialized_type;
|
||||||
use air_interpreter_sede::Format;
|
use air_interpreter_sede::Format;
|
||||||
use air_interpreter_sede::FromSerialized;
|
use air_interpreter_sede::FromSerialized;
|
||||||
use air_interpreter_sede::JsonFormat;
|
use air_interpreter_sede::MsgPackFormat;
|
||||||
|
use air_interpreter_sede::MsgPackMultiformat;
|
||||||
use air_interpreter_sede::Representation;
|
use air_interpreter_sede::Representation;
|
||||||
|
|
||||||
use marine_call_parameters::SecurityTetraplet;
|
use marine_call_parameters::SecurityTetraplet;
|
||||||
@ -36,9 +37,9 @@ derive_serialized_type!(SerializedCallArguments);
|
|||||||
derive_serialized_type!(SerializedTetraplets);
|
derive_serialized_type!(SerializedTetraplets);
|
||||||
derive_serialized_type!(SerializedCallRequests);
|
derive_serialized_type!(SerializedCallRequests);
|
||||||
|
|
||||||
pub type CallArgumentsFormat = JsonFormat;
|
pub type CallArgumentsFormat = MsgPackFormat;
|
||||||
pub type TetrapletsFormat = JsonFormat;
|
pub type TetrapletsFormat = MsgPackFormat;
|
||||||
pub type CallRequestsFormat = JsonFormat;
|
pub type CallRequestsFormat = MsgPackMultiformat;
|
||||||
|
|
||||||
define_simple_representation! {
|
define_simple_representation! {
|
||||||
CallArgumentsRepr,
|
CallArgumentsRepr,
|
||||||
@ -74,7 +75,7 @@ impl FromSerialized<Vec<Vec<SecurityTetraplet>>> for TetrapletsRepr {
|
|||||||
&self,
|
&self,
|
||||||
repr: &[u8],
|
repr: &[u8],
|
||||||
) -> Result<Vec<Vec<SecurityTetraplet>>, Self::DeserializeError> {
|
) -> Result<Vec<Vec<SecurityTetraplet>>, Self::DeserializeError> {
|
||||||
CallArgumentsRepr.get_format().from_slice(repr)
|
Self.get_format().from_slice(repr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,17 +16,19 @@
|
|||||||
|
|
||||||
use air_interpreter_sede::define_simple_representation;
|
use air_interpreter_sede::define_simple_representation;
|
||||||
use air_interpreter_sede::derive_serialized_type;
|
use air_interpreter_sede::derive_serialized_type;
|
||||||
use air_interpreter_sede::JsonFormat;
|
use air_interpreter_sede::MsgPackMultiformat;
|
||||||
use air_interpreter_sede::Representation;
|
use air_interpreter_sede::Representation;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value as JValue;
|
use serde_json::Value as JValue;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub type CallResults = HashMap<u32, CallServiceResult>;
|
/// This is a map from a String to a service result for compatibility with JavaScript.
|
||||||
|
/// Binary format implementations like `rmp-serde` do not convert keys from strings, unlike `serde_json`.
|
||||||
|
pub type CallResults = HashMap<String, CallServiceResult>;
|
||||||
pub const CALL_SERVICE_SUCCESS: i32 = 0;
|
pub const CALL_SERVICE_SUCCESS: i32 = 0;
|
||||||
|
|
||||||
pub type CallResultsFormat = JsonFormat;
|
pub type CallResultsFormat = MsgPackMultiformat;
|
||||||
|
|
||||||
derive_serialized_type!(SerializedCallResults);
|
derive_serialized_type!(SerializedCallResults);
|
||||||
|
|
||||||
@ -55,6 +57,7 @@ impl CallServiceResult {
|
|||||||
pub fn ok(result: &JValue) -> Self {
|
pub fn ok(result: &JValue) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ret_code: CALL_SERVICE_SUCCESS,
|
ret_code: CALL_SERVICE_SUCCESS,
|
||||||
|
// for compatiblity with JavaScript with binary formats, string IDs are used
|
||||||
result: result.to_string(),
|
result: result.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,9 @@ where
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_vec(&self, val: &Value) -> Result<Vec<u8>, Self::SerializationError> {
|
fn to_vec(&self, val: &Value) -> Result<Vec<u8>, Self::SerializationError> {
|
||||||
rmp_serde::to_vec(val)
|
// named representation (i.e. structs are serialized as maps, not tuples) is important
|
||||||
|
// for JS interop and data compatibility detection
|
||||||
|
rmp_serde::to_vec_named(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -49,7 +51,9 @@ where
|
|||||||
value: &Value,
|
value: &Value,
|
||||||
write: &mut W,
|
write: &mut W,
|
||||||
) -> Result<(), Self::WriteError> {
|
) -> Result<(), Self::WriteError> {
|
||||||
value.serialize(&mut rmp_serde::Serializer::new(write))
|
// named representation (i.e. structs are serialized as maps, not tuples) is important
|
||||||
|
// for JS interop and data compatibility detection
|
||||||
|
rmp_serde::encode::write_named(write, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user