2021-01-15 00:38:58 +03:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2021-08-24 16:14:15 +03:00
|
|
|
mod catchable;
|
2021-08-26 15:01:58 +03:00
|
|
|
mod joinable;
|
2021-08-24 16:14:15 +03:00
|
|
|
|
|
|
|
pub(crate) use catchable::Catchable;
|
2021-08-26 15:01:58 +03:00
|
|
|
pub(crate) use joinable::Joinable;
|
2021-08-24 16:14:15 +03:00
|
|
|
|
|
|
|
use super::trace_handler::MergerApResult;
|
|
|
|
use super::trace_handler::TraceHandlerError;
|
|
|
|
use super::ResolvedCallResult;
|
|
|
|
use super::Stream;
|
2021-01-15 00:38:58 +03:00
|
|
|
use crate::JValue;
|
|
|
|
|
|
|
|
use jsonpath_lib::JsonPathError;
|
2021-09-02 18:01:21 +03:00
|
|
|
use strum::IntoEnumIterator;
|
|
|
|
use strum_macros::EnumDiscriminants;
|
|
|
|
use strum_macros::EnumIter;
|
2021-01-15 00:38:58 +03:00
|
|
|
use thiserror::Error as ThisError;
|
|
|
|
|
2021-02-11 15:39:37 +03:00
|
|
|
use std::rc::Rc;
|
|
|
|
|
2021-01-15 00:38:58 +03:00
|
|
|
/// Errors arised while executing AIR script.
|
2021-09-02 18:01:21 +03:00
|
|
|
#[derive(ThisError, EnumDiscriminants, Debug)]
|
|
|
|
#[strum_discriminants(derive(EnumIter))]
|
2021-01-15 00:38:58 +03:00
|
|
|
pub(crate) enum ExecutionError {
|
2021-08-24 16:14:15 +03:00
|
|
|
/// Semantic errors in a call instructions.
|
|
|
|
#[error("call should have service id specified by peer part or function part")]
|
|
|
|
IncorrectCallTriplet,
|
2021-01-15 00:38:58 +03:00
|
|
|
|
|
|
|
/// An error is occurred while calling local service via call_service.
|
2021-06-10 10:48:19 +03:00
|
|
|
#[error("Local service error, ret_code is {0}, error message is '{1}'")]
|
2021-02-11 15:39:37 +03:00
|
|
|
LocalServiceError(i32, Rc<String>),
|
2021-01-15 00:38:58 +03:00
|
|
|
|
|
|
|
/// Value for such name isn't presence in data.
|
|
|
|
#[error("variable with name '{0}' isn't present in data")]
|
|
|
|
VariableNotFound(String),
|
|
|
|
|
|
|
|
/// Multiple values for such name found.
|
|
|
|
#[error("multiple variables found for name '{0}' in data")]
|
|
|
|
MultipleVariablesFound(String),
|
|
|
|
|
|
|
|
/// An error occurred while trying to apply json path to this JValue.
|
2021-02-11 15:39:37 +03:00
|
|
|
#[error("variable with path '{1}' not found in '{0}' with an error: '{2}'")]
|
2021-01-15 00:38:58 +03:00
|
|
|
JValueJsonPathError(JValue, String, JsonPathError),
|
|
|
|
|
2021-08-24 16:14:15 +03:00
|
|
|
/// An error occurred while trying to apply json path to this stream generation with JValue's.
|
|
|
|
#[error("variable with path '{1}' not found in '{0:?}' with error: '{2}'")]
|
|
|
|
GenerationStreamJsonPathError(Vec<ResolvedCallResult>, String, JsonPathError),
|
|
|
|
|
2021-03-26 17:13:28 +03:00
|
|
|
/// An error occurred while trying to apply json path to this stream with JValue's.
|
2021-02-11 15:39:37 +03:00
|
|
|
#[error("variable with path '{1}' not found in '{0:?}' with error: '{2}'")]
|
2021-08-24 16:14:15 +03:00
|
|
|
StreamJsonPathError(Stream, String, JsonPathError),
|
2021-01-15 00:38:58 +03:00
|
|
|
|
2021-08-26 15:01:58 +03:00
|
|
|
/// An error occurred while trying to apply json path to an empty stream.
|
|
|
|
#[error("json path {0} is applied to an empty stream")]
|
|
|
|
EmptyStreamJsonPathError(String),
|
|
|
|
|
2021-01-15 00:38:58 +03:00
|
|
|
/// Provided JValue has incompatible with target type.
|
2021-02-11 15:39:37 +03:00
|
|
|
#[error("expected JValue type '{1}', but got '{0}' JValue")]
|
2021-01-15 00:38:58 +03:00
|
|
|
IncompatibleJValueType(JValue, &'static str),
|
|
|
|
|
|
|
|
/// Provided AValue has incompatible with target type.
|
2021-02-11 15:39:37 +03:00
|
|
|
#[error("expected AValue type '{1}', but got '{0}' AValue")]
|
2021-01-15 00:38:58 +03:00
|
|
|
IncompatibleAValueType(String, String),
|
|
|
|
|
|
|
|
/// Multiple values found for such json path.
|
|
|
|
#[error("multiple variables found for this json path '{0}'")]
|
|
|
|
MultipleValuesInJsonPath(String),
|
|
|
|
|
|
|
|
/// Fold state wasn't found for such iterator name.
|
|
|
|
#[error("fold state not found for this iterable '{0}'")]
|
|
|
|
FoldStateNotFound(String),
|
|
|
|
|
|
|
|
/// Multiple fold states found for such iterator name.
|
|
|
|
#[error("multiple fold states found for iterable '{0}'")]
|
|
|
|
MultipleFoldStates(String),
|
|
|
|
|
|
|
|
/// Errors encountered while shadowing non-scalar values.
|
2021-08-24 16:14:15 +03:00
|
|
|
#[error("variable with name '{0}' can't be shadowed, shadowing isn't supported for iterables")]
|
|
|
|
IterableShadowing(String),
|
2021-01-27 00:37:58 +03:00
|
|
|
|
|
|
|
/// This error type is produced by a match to notify xor that compared values aren't equal.
|
|
|
|
#[error("match is used without corresponding xor")]
|
|
|
|
MatchWithoutXorError,
|
2021-02-11 15:39:37 +03:00
|
|
|
|
|
|
|
/// This error type is produced by a mismatch to notify xor that compared values aren't equal.
|
|
|
|
#[error("mismatch is used without corresponding xor")]
|
|
|
|
MismatchWithoutXorError,
|
2021-02-18 17:30:14 +03:00
|
|
|
|
|
|
|
/// This error type is produced by a mismatch to notify xor that compared values aren't equal.
|
2021-06-01 18:43:11 +03:00
|
|
|
#[error("jvalue '{0}' can't be flattened, to be flattened a jvalue should have an array type and consist of zero or one values")]
|
2021-02-18 17:30:14 +03:00
|
|
|
FlatteningError(JValue),
|
2021-06-09 19:58:59 +03:00
|
|
|
|
|
|
|
/// Json path is applied to scalar that have inappropriate type.
|
|
|
|
#[error(
|
|
|
|
"json path can't be applied to scalar '{0}',\
|
|
|
|
it could be applied only to streams and variables of array and object types"
|
|
|
|
)]
|
|
|
|
JsonPathVariableTypeError(JValue),
|
2021-08-24 16:14:15 +03:00
|
|
|
|
|
|
|
/// Errors bubbled from a trace handler.
|
2021-09-20 14:49:20 +03:00
|
|
|
#[error(transparent)]
|
2021-08-24 16:14:15 +03:00
|
|
|
TraceError(#[from] TraceHandlerError),
|
|
|
|
|
|
|
|
/// Errors occurred while insertion of a value inside stream that doesn't have corresponding generation.
|
|
|
|
#[error("stream {0:?} doesn't have generation with number {1}, probably a supplied to the interpreter data is corrupted")]
|
|
|
|
StreamDontHaveSuchGeneration(Stream, usize),
|
|
|
|
|
|
|
|
/// Errors occurred when result from data doesn't match to a instruction, f.e. an instruction
|
|
|
|
/// could be applied to a stream, but result doesn't contain generation in a source position.
|
|
|
|
#[error("ap result {0:?} doesn't match corresponding instruction")]
|
|
|
|
ApResultNotCorrespondToInstr(MergerApResult),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<TraceHandlerError> for Rc<ExecutionError> {
|
|
|
|
fn from(trace_error: TraceHandlerError) -> Self {
|
|
|
|
Rc::new(ExecutionError::TraceError(trace_error))
|
|
|
|
}
|
2021-01-15 00:38:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ExecutionError {
|
|
|
|
pub(crate) fn to_error_code(&self) -> u32 {
|
2021-09-02 18:01:21 +03:00
|
|
|
let mut errors = ExecutionErrorDiscriminants::iter();
|
|
|
|
let actual_error_type = ExecutionErrorDiscriminants::from(self);
|
|
|
|
|
|
|
|
// unwrap is safe here because errors are guaranteed to contain all errors variants
|
|
|
|
errors.position(|et| et == actual_error_type).unwrap() as _
|
2021-01-15 00:38:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 13:00:11 +03:00
|
|
|
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
|
|
|
|
}
|
2021-08-24 16:14:15 +03:00
|
|
|
StreamJsonPathError(stream, json_path, _) => {
|
2021-06-10 13:00:11 +03:00
|
|
|
log_join!(" waiting for an argument with path '{}' on stream '{:?}'", json_path, stream);
|
|
|
|
true
|
|
|
|
}
|
2021-08-26 15:01:58 +03:00
|
|
|
EmptyStreamJsonPathError(json_path) => {
|
|
|
|
log_join!(" waiting on empty stream for path '{}'", json_path);
|
|
|
|
true
|
|
|
|
}
|
2021-08-24 16:14:15 +03:00
|
|
|
|
2021-06-10 13:00:11 +03:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-24 16:14:15 +03:00
|
|
|
impl Catchable for ExecutionError {
|
|
|
|
fn is_catchable(&self) -> bool {
|
|
|
|
// this kind is related to an invalid data and should treat as a non-catchable error
|
|
|
|
!matches!(self, ExecutionError::TraceError(_))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-15 00:38:58 +03:00
|
|
|
impl From<std::convert::Infallible> for ExecutionError {
|
|
|
|
fn from(_: std::convert::Infallible) -> Self {
|
|
|
|
unreachable!()
|
|
|
|
}
|
|
|
|
}
|