mirror of
https://github.com/fluencelabs/aquavm
synced 2024-12-04 15:20:16 +00:00
Non wait on json path applied to scalars (#118)
This commit is contained in:
parent
b2919b1509
commit
dc1582d02e
28
CHANGELOG.md
28
CHANGELOG.md
@ -1,7 +1,33 @@
|
||||
## Version 0.10.4 (2021-06-10)
|
||||
|
||||
- json path applied to scalar values becomes non-joinable ([PR 118](https://github.com/fluencelabs/aquavm/pull/118))
|
||||
|
||||
## Version 0.10.3 (2021-06-09)
|
||||
|
||||
- `%last_error%` includes `peer_id` now, that contains id of a peer where an error occurred ([PR 117](https://github.com/fluencelabs/aquavm/pull/117)).
|
||||
|
||||
## Version 0.10.2-0.10.1 (2021-06-04)
|
||||
|
||||
- improved logger initialization and interface for wasm-bindgen target ([PR 116](https://github.com/fluencelabs/aquavm/pull/116), [PR 115](https://github.com/fluencelabs/aquavm/pull/115)).
|
||||
|
||||
## Version 0.10.0 (2021-06-09)
|
||||
|
||||
- `%last_error%` becomes an object of type
|
||||
```rust
|
||||
pub struct LastError {
|
||||
/// text representation of an instruction that caused the last error
|
||||
pub instruction: String,
|
||||
|
||||
/// text representation of an error message
|
||||
pub msg: String,
|
||||
}
|
||||
```
|
||||
and it's possible to address its fields separately: `%last_error%.$.instruction`, `%last_error%.$.msg` ([PR 112](https://github.com/fluencelabs/aquavm/pull/112)).
|
||||
|
||||
## Version 0.1.3 (2020-11-11)
|
||||
|
||||
- Switched to the new LALRPOP parser ([PR 13](https://github.com/fluencelabs/air/pull/13)):
|
||||
- arguments should be wrapped wit square braces []
|
||||
- arguments should be wrapped with square braces []
|
||||
- empty results in call allowed and lead to forget a call result
|
||||
|
||||
- Added a few benchmarks
|
||||
|
@ -25,6 +25,7 @@ use super::ExecutionError;
|
||||
use super::ExecutionResult;
|
||||
use super::ExecutionTraceCtx;
|
||||
use crate::contexts::execution::LastErrorDescriptor;
|
||||
use crate::execution::joinable::Joinable;
|
||||
use crate::joinable_call;
|
||||
use crate::log_instruction;
|
||||
use crate::SecurityTetraplet;
|
||||
|
@ -19,6 +19,7 @@ use super::ExecutionCtx;
|
||||
use super::ExecutionError;
|
||||
use super::ExecutionResult;
|
||||
use super::ExecutionTraceCtx;
|
||||
use crate::execution::joinable::Joinable;
|
||||
use crate::joinable;
|
||||
use crate::log_instruction;
|
||||
|
||||
|
@ -19,6 +19,7 @@ use super::ExecutionCtx;
|
||||
use super::ExecutionError;
|
||||
use super::ExecutionResult;
|
||||
use super::ExecutionTraceCtx;
|
||||
use crate::execution::joinable::Joinable;
|
||||
use crate::joinable;
|
||||
use crate::log_instruction;
|
||||
|
||||
|
@ -155,7 +155,7 @@ macro_rules! log_instruction {
|
||||
macro_rules! joinable_call {
|
||||
($cmd:expr, $exec_ctx:expr) => {
|
||||
match $cmd {
|
||||
Err(e) if crate::execution::air::is_joinable_error_type(&e) => {
|
||||
Err(e) if e.is_joinable() => {
|
||||
$exec_ctx.subtree_complete = false;
|
||||
return Ok(());
|
||||
}
|
||||
@ -169,39 +169,10 @@ macro_rules! joinable_call {
|
||||
macro_rules! joinable {
|
||||
($cmd:expr, $exec_ctx:expr) => {
|
||||
match $cmd {
|
||||
Err(e) if crate::execution::air::is_joinable_error_type(&e) => {
|
||||
Err(e) if e.is_joinable() => {
|
||||
return Ok(());
|
||||
}
|
||||
v => v,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! log_join {
|
||||
($($args:tt)*) => {
|
||||
log::info!(target: crate::log_targets::JOIN_BEHAVIOUR, $($args)*)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true, if supplied error is related to variable not found errors type.
|
||||
/// Print log if this is joinable error type.
|
||||
#[rustfmt::skip::macros(log_join)]
|
||||
fn is_joinable_error_type(exec_error: &ExecutionError) -> bool {
|
||||
use ExecutionError::*;
|
||||
|
||||
match exec_error {
|
||||
VariableNotFound(var_name) => {
|
||||
log_join!(" waiting for an argument with name '{}'", var_name);
|
||||
true
|
||||
}
|
||||
JValueJsonPathError(value, json_path, _) => {
|
||||
log_join!(" waiting for an argument with path '{}' on jvalue '{:?}'", json_path, value);
|
||||
true
|
||||
}
|
||||
JValueStreamJsonPathError(stream, json_path, _) => {
|
||||
log_join!(" waiting for an argument with path '{}' on stream '{:?}'", json_path, stream);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::Joinable;
|
||||
use crate::build_targets::CallServiceResult;
|
||||
use crate::contexts::execution::ResolvedCallResult;
|
||||
use crate::contexts::execution_trace::ExecutedState;
|
||||
@ -131,6 +132,33 @@ impl ExecutionError {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! log_join {
|
||||
($($args:tt)*) => {
|
||||
log::info!(target: crate::log_targets::JOIN_BEHAVIOUR, $($args)*)
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip::macros(log_join)]
|
||||
impl Joinable for ExecutionError {
|
||||
/// Returns true, if supplied error is related to variable not found errors type.
|
||||
/// Print log if this is joinable error type.
|
||||
fn is_joinable(&self) -> bool {
|
||||
use ExecutionError::*;
|
||||
|
||||
match self {
|
||||
VariableNotFound(var_name) => {
|
||||
log_join!(" waiting for an argument with name '{}'", var_name);
|
||||
true
|
||||
}
|
||||
JValueStreamJsonPathError(stream, json_path, _) => {
|
||||
log_join!(" waiting for an argument with path '{}' on stream '{:?}'", json_path, stream);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::convert::Infallible> for ExecutionError {
|
||||
fn from(_: std::convert::Infallible) -> Self {
|
||||
unreachable!()
|
||||
|
27
air/src/execution/joinable.rs
Normal file
27
air/src/execution/joinable.rs
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/// This trait is intended to differentiate between joinable and non-joinable objects.
|
||||
/// Joinable objects are those that interpreter should wait on. F.e. if at least one of
|
||||
/// arguments of a call instructions is joinable, the interpreter won't execute such
|
||||
/// call and won't write any state for it in data. This is needed to handle collecting
|
||||
/// variable from different peers in parallel.
|
||||
///
|
||||
/// At the moment, this trait's applied only to errors.
|
||||
pub(crate) trait Joinable {
|
||||
/// Return true, if supplied object is joinable
|
||||
fn is_joinable(&self) -> bool;
|
||||
}
|
@ -17,11 +17,13 @@
|
||||
mod air;
|
||||
mod boxed_value;
|
||||
mod errors;
|
||||
mod joinable;
|
||||
mod utils;
|
||||
|
||||
pub(super) use self::air::ExecutableInstruction;
|
||||
pub(super) use self::air::FoldState;
|
||||
pub(super) use errors::ExecutionError;
|
||||
pub(self) use joinable::Joinable;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -23,7 +23,7 @@ use air_test_utils::ExecutionTrace;
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn non_wait_on_json_path() {
|
||||
fn dont_wait_on_json_path() {
|
||||
let status = json!({
|
||||
"err_msg": "",
|
||||
"is_authenticated": 1,
|
||||
@ -106,3 +106,62 @@ fn wait_on_stream_json_path_by_id() {
|
||||
assert_eq!(res.ret_code, 0);
|
||||
assert_eq!(trace.len(), 2); // par and the first call emit traces, second call doesn't
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dont_wait_on_json_path_on_scalars() {
|
||||
let array = json!([1, 2, 3, 4, 5]);
|
||||
|
||||
let object = json!({
|
||||
"err_msg": "",
|
||||
"is_authenticated": 1,
|
||||
"ret_code": 0,
|
||||
});
|
||||
|
||||
let variables = maplit::hashmap!(
|
||||
"array".to_string() => array.to_string(),
|
||||
"object".to_string() => object.to_string(),
|
||||
);
|
||||
|
||||
let set_variables_call_service = set_variables_call_service(variables);
|
||||
|
||||
let set_variable_peer_id = "set_variable";
|
||||
let mut set_variable_vm = create_avm(set_variables_call_service, set_variable_peer_id);
|
||||
|
||||
let array_consumer_peer_id = "array_consumer_peer_id";
|
||||
let mut array_consumer = create_avm(unit_call_service(), array_consumer_peer_id);
|
||||
|
||||
let object_consumer_peer_id = "object_consumer_peer_id";
|
||||
let mut object_consumer = create_avm(unit_call_service(), object_consumer_peer_id);
|
||||
|
||||
let script = format!(
|
||||
r#"
|
||||
(seq
|
||||
(seq
|
||||
(call "{0}" ("" "") ["array"] array)
|
||||
(call "{0}" ("" "") ["object"] object)
|
||||
)
|
||||
(par
|
||||
(call "{1}" ("" "") [array.$.[5]!] auth_result)
|
||||
(call "{2}" ("" "") [object.$.non_exist_path])
|
||||
)
|
||||
)
|
||||
"#,
|
||||
set_variable_peer_id, array_consumer_peer_id, object_consumer_peer_id,
|
||||
);
|
||||
|
||||
let init_peer_id = "asd";
|
||||
let res = call_vm!(set_variable_vm, init_peer_id, &script, "", "");
|
||||
let array_res = call_vm!(array_consumer, init_peer_id, &script, "", res.data.clone());
|
||||
assert_eq!(array_res.ret_code, 1006);
|
||||
assert_eq!(
|
||||
array_res.error_message,
|
||||
r#"variable with path '$.[5]' not found in '[1,2,3,4,5]' with an error: 'json value not set'"#
|
||||
);
|
||||
|
||||
let object_res = call_vm!(object_consumer, init_peer_id, script, "", res.data);
|
||||
assert_eq!(object_res.ret_code, 1006);
|
||||
assert_eq!(
|
||||
object_res.error_message,
|
||||
r#"variable with path '$.non_exist_path' not found in '{"err_msg":"","is_authenticated":1,"ret_code":0}' with an error: 'json value not set'"#
|
||||
);
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
use air_test_utils::call_vm;
|
||||
use air_test_utils::create_avm;
|
||||
use air_test_utils::echo_string_call_service;
|
||||
use air_test_utils::ExecutionTrace;
|
||||
|
||||
#[test]
|
||||
fn json_path_not_allowed_for_non_objects_and_arrays() {
|
||||
|
Loading…
Reference in New Issue
Block a user