feat: complete Epic 1 production foundation
This commit is contained in:
@@ -8,16 +8,16 @@ use std::{
|
||||
|
||||
use async_trait::async_trait;
|
||||
use crank_core::{
|
||||
AdapterResponse, ConfirmationPolicy, ExecutionConfig, ExecutionMode, HttpMethod,
|
||||
IdempotencyMode, IdempotencyPolicy, Operation, OperationId, OperationSafetyClass,
|
||||
AdapterResponse, ConfirmationPolicy, ExecutionConfig, ExecutionErrorCode, ExecutionMode,
|
||||
HttpMethod, IdempotencyMode, IdempotencyPolicy, Operation, OperationId, OperationSafetyClass,
|
||||
OperationSafetyPolicy, OperationSecurityLevel, OperationStatus, Protocol, ProtocolAdapter,
|
||||
ProtocolAdapterError, ResponseCachePolicy, RestTarget,
|
||||
RuntimeRequestContext as ProtocolRequestContext, Target, ToolDescription,
|
||||
};
|
||||
use crank_mapping::{MappingRule, MappingSet};
|
||||
use crank_runtime::{
|
||||
InMemoryCoordinationStateStore, InMemoryResponseCacheStore, RuntimeError,
|
||||
RuntimeExecutorBuilder, RuntimeRequestContext,
|
||||
InMemoryCoordinationStateStore, InMemoryResponseCacheStore, RuntimeExecutorBuilder,
|
||||
RuntimeRequestContext,
|
||||
};
|
||||
use crank_schema::{Schema, SchemaKind};
|
||||
use metrics_util::debugging::DebuggingRecorder;
|
||||
@@ -110,10 +110,10 @@ async fn exercise_cancelled_idempotency() {
|
||||
.execute_with_context(&operation, &input, Some(&context))
|
||||
.await
|
||||
.expect_err("cancelled external outcome must not be retried automatically");
|
||||
assert!(matches!(
|
||||
retry,
|
||||
RuntimeError::IdempotencyOutcomeUnknown { .. }
|
||||
));
|
||||
assert_eq!(
|
||||
retry.error_code(),
|
||||
ExecutionErrorCode::IdempotencyOutcomeUnknown
|
||||
);
|
||||
assert_eq!(calls.load(Ordering::SeqCst), 1);
|
||||
}
|
||||
|
||||
@@ -180,7 +180,10 @@ async fn exercise_idempotency() {
|
||||
.await
|
||||
.expect_err("same idempotency key with a different input must conflict");
|
||||
|
||||
assert!(matches!(conflict, RuntimeError::IdempotencyConflict { .. }));
|
||||
assert_eq!(
|
||||
conflict.error_code(),
|
||||
ExecutionErrorCode::IdempotencyConflict
|
||||
);
|
||||
assert_eq!(calls.load(Ordering::SeqCst), 1);
|
||||
}
|
||||
|
||||
@@ -206,12 +209,15 @@ async fn exercise_confirmation() {
|
||||
.execute_with_context(&operation, &input, Some(&context))
|
||||
.await
|
||||
.expect_err("destructive operation must require confirmation");
|
||||
let RuntimeError::ConfirmationRequired {
|
||||
confirmation_token, ..
|
||||
} = required
|
||||
else {
|
||||
panic!("expected confirmation token");
|
||||
};
|
||||
assert_eq!(
|
||||
required.error_code(),
|
||||
ExecutionErrorCode::ConfirmationRequired
|
||||
);
|
||||
let confirmation_token = required
|
||||
.confirmation()
|
||||
.expect("expected confirmation token")
|
||||
.token()
|
||||
.to_owned();
|
||||
let confirmed = context
|
||||
.clone()
|
||||
.with_confirmation_token(confirmation_token.clone());
|
||||
@@ -224,10 +230,10 @@ async fn exercise_confirmation() {
|
||||
.await
|
||||
.expect_err("confirmation token must be single-use");
|
||||
|
||||
assert!(matches!(
|
||||
invalid,
|
||||
RuntimeError::InvalidConfirmationToken { .. }
|
||||
));
|
||||
assert_eq!(
|
||||
invalid.error_code(),
|
||||
ExecutionErrorCode::ConfirmationInvalid
|
||||
);
|
||||
assert_eq!(calls.load(Ordering::SeqCst), 1);
|
||||
}
|
||||
|
||||
@@ -261,9 +267,10 @@ impl ProtocolAdapter for BlockingAdapter {
|
||||
&self,
|
||||
_target: &Target,
|
||||
_prepared: &crank_core::PreparedRequest,
|
||||
_context: &ProtocolRequestContext,
|
||||
context: &ProtocolRequestContext,
|
||||
) -> Result<AdapterResponse, ProtocolAdapterError> {
|
||||
self.calls.fetch_add(1, Ordering::SeqCst);
|
||||
context.mark_dispatch_started();
|
||||
std::future::pending().await
|
||||
}
|
||||
}
|
||||
@@ -412,3 +419,6 @@ async fn wait_for_calls(calls: &AtomicUsize, expected: usize) {
|
||||
}
|
||||
panic!("adapter did not receive {expected} call(s)");
|
||||
}
|
||||
mod support;
|
||||
|
||||
use support::RuntimeExecutorTestExt;
|
||||
|
||||
Reference in New Issue
Block a user