saddle-framework 0.3.24

The single business-facing facade for Saddle applications
//! S production App entry and concrete transaction construction consumer.
#![allow(dead_code)]
#![allow(unexpected_cfgs)]
use prost::Message;
use saddle::ingress::{ProfuseGwCode, ProfuseGwContext, ProfuseGwResponse as Response};
use saddle::{BusinessConfig, application};
use serde::{Deserialize, Serialize};
use std::cell::Cell;

#[derive(Clone, PartialEq, Message, Deserialize)]
struct Input {}
#[derive(Deserialize)]
struct ParameterInput {
    text: String,
    json: String,
}
#[derive(Clone, PartialEq, Message)]
struct QueryBoundAccountsRequest {
    #[prost(string, tag = "1")]
    user_id: String,
}
#[derive(Clone, PartialEq, Message)]
struct QueryBoundAccountsResult {
    #[prost(uint64, tag = "1")]
    account_count: u64,
}
#[derive(Clone, PartialEq, Message, Serialize)]
struct Output {
    #[prost(uint64, tag = "1")]
    value: u64,
}
enum Code {
    Failure,
}
impl ProfuseGwCode for Code {
    const REGISTERED_CODES: &'static [&'static str] = &["FAILURE"];
    fn stable_code(&self) -> &'static str {
        "FAILURE"
    }
}
saddle::database_operations! {
    relational;
    pub mod ops {
        namespace "cf.account";
        schema { account { id:u64, value:u64 } }
        query Read { parameters ReadParams { id:u64 } from account as a;
            where a.id==bind(id);result optional Row {value:a.value} }
        update Write {parameters WriteParams {id:u64,value:u64} table account;
            values {value:bind(value)} where account.id==bind(id);}
    }
}
application! {
    schema "saddle-application/2";
    application App;
    deployment_app "cf-app";
    business_config ();
    profusecontract { contract_dir "examples/contracts"; capability Cap; response_code Code; functions {
        QueryBoundAccounts => query_bound_accounts { business_unit "puc"; function "查询用户绑定户号"; } (QueryBoundAccountsRequest)->QueryBoundAccountsResult;
    } }
    database_modules { Accounts {optional read(ops::Read);write store(ops::Write);} }
    service ViaModule { ingress profusegw; operation_type "cf.module"; request Input; response Output;
        handler module_handler; uses QueryBoundAccounts; database module db(Accounts); }
    service ViaRoute { ingress profusegw; operation_type "cf.route"; request Input; response Output;
        handler route_handler; database transaction transfer { optional read(ops::Read);write store(ops::Write); } }
    service WaitRoute { ingress profusegw; operation_type "cf.wait"; request Input; response Output;
        handler wait_handler; database transaction wait { optional read(ops::Read);write store(ops::Write); } }
    service Parameters { ingress profusegw; operation_type "cf.parameters"; request ParameterInput; response Output;
        handler parameter_handler; database module db(Accounts); }
}
async fn parameter_handler(
    input: ParameterInput,
    _: ProfuseGwContext,
    mut cap: Cap<Parameters>,
    _: BusinessConfig<()>,
) -> Response<Output, Code> {
    let mut db = cap.db();
    let text = db
        .text(&input.text)
        .await
        .expect("same request Text construction");
    assert_eq!(text.as_str(), input.text);
    let value = match db.json(&input.json).await {
        Ok(_) => 1,
        Err(saddle::database::ParameterConstructionError::InvalidJson) => 0,
        Err(error) => panic!("unexpected construction: {error:?}"),
    };
    Response::success(Output { value })
}

saddle::transaction_logic! {
    fn module_logic(tx: Accounts; start:u64, state:Cell<u64>) -> (u64,()) {
        for id in start..start+2 {
            let step=tx.read(ops::ReadParams {id});
            let row=step.await.map_err(|e| saddle::database::TransactionAbort::Technical(e.into_failure()))?;
            if let Some(row)=row {state.set(row.value);}
            tokio::task::yield_now().await;
            tx.store(ops::WriteParams{id,value:state.get()+1}).await
                .map_err(|e| saddle::database::TransactionAbort::Technical(e.into_failure()))?;
        }
        Ok(state.get())
    }
}
saddle::transaction_logic! {
    fn route_logic(tx: ViaRoute; state:Cell<u64>) -> (u64,()) {
        let row=tx.read(ops::ReadParams{id:1}).await
            .map_err(|e| saddle::database::TransactionAbort::Technical(e.into_failure()))?;
        tokio::task::yield_now().await;
        if let Some(row)=row {state.set(row.value);}
        Ok(state.get())
    }
}
saddle::transaction_logic! {
    fn wait_logic(tx: WaitRoute;) -> (u64,()) {
        let row=tx.read(ops::ReadParams{id:1}).await.map_err(|error|saddle::database::TransactionAbort::Technical(error.into_failure()))?.unwrap();
        tx.store(ops::WriteParams{id:1,value:row.value+100}).await.map_err(|error|saddle::database::TransactionAbort::Technical(error.into_failure()))?;
        println!("S_WAIT_ENTERED");
        std::future::pending::<()>().await;
        Ok(0)
    }
}
async fn wait_handler(
    _: Input,
    _: ProfuseGwContext,
    mut cap: Cap<WaitRoute>,
    _: BusinessConfig<()>,
) -> Response<Output, Code> {
    let _ = cap
        .wait(
            saddle::database::TransactionIsolation::RepeatableRead,
            wait_logic(),
        )
        .await;
    panic!("cancelled waiting transaction cannot return a successful handler");
}
fn accepts_actual_d<
    B: saddle::transaction_construction::ReservedTransactionBody<
            saddle::transaction_construction::Cancel,
        >,
>(
    _: B,
) {
}
async fn module_handler(
    _: Input,
    _: ProfuseGwContext,
    mut cap: Cap<ViaModule>,
    _: BusinessConfig<()>,
) -> Response<Output, Code> {
    let value = {
        let mut db = cap.db();
        let _before = db
            .read(ops::ReadParams { id: 1 })
            .await
            .expect("ordinary query succeeds");
        match db
            .transaction(
                saddle::database::TransactionIsolation::RepeatableRead,
                module_logic(1, Cell::new(0)),
            )
            .await
        {
            saddle::database::TransactionOutcome::Committed(value) => value,
            other => panic!("module transaction must commit: {other:?}"),
        }
    };
    match cap
        .query_bound_accounts(QueryBoundAccountsRequest {
            user_id: "test-user".into(),
        })
        .await
    {
        saddle::profusecontract::ExternalFunctionResult::TechnicalFailure(failure) => {
            assert!(matches!(
                failure.code(),
                saddle::profusecontract::TechnicalFailureCode::DependencyUnavailable
                    | saddle::profusecontract::TechnicalFailureCode::TransportFailure
            ))
        }
        _ => panic!("owned closed loopback endpoint cannot return success"),
    }
    Response::success(Output { value })
}
async fn route_handler(
    _: Input,
    _: ProfuseGwContext,
    mut cap: Cap<ViaRoute>,
    _: BusinessConfig<()>,
) -> Response<Output, Code> {
    match cap
        .transfer(
            saddle::database::TransactionIsolation::RepeatableRead,
            route_logic(Cell::new(0)),
        )
        .await
    {
        saddle::database::TransactionOutcome::Committed(value) => {
            Response::success(Output { value })
        }
        other => panic!("route transaction must commit: {other:?}"),
    }
}
fn main() {
    if std::env::args().any(|arg| arg == "--config") {
        App::run().unwrap();
        return;
    }
    println!(
        "S_ENTRY_CURRENT {:?}",
        saddle::__private::reserved_entry_layouts_for(&App::__execute_profusegw).unwrap()
    );
    let module = module_logic(1, Cell::new(0));
    let route = route_logic(Cell::new(0));
    let small = small_layout([0; 8]);
    let large = large_layout([0; 4096]);
    assert!(
        __saddle_cf::body_layout::<Accounts, _>(&large).size()
            > __saddle_cf::body_layout::<Accounts, _>(&small).size() + 4000
    );
    println!("S_LAYOUT_VARIATION_PASS before_execute no_session");
    println!(
        "S actual D body module={:?} route={:?}",
        __saddle_cf::body_layout::<Accounts, _>(&module),
        __saddle_cf::body_layout::<ViaRoute, _>(&route)
    );
    println!(
        "S layout mode only; live entry/SQL/cancellation evidence is produced by run-database.sh"
    );
    for (name, (_, layout)) in saddle_core::request_context::request_context_layouts()
        .into_iter()
        .enumerate()
    {
        println!(
            "S_CORE_DYNAMIC {name} bytes={} align={}",
            layout.size(),
            layout.align()
        );
    }
    for (name, layout) in saddle_runtime::request_task::reserved::supervised_scope_layouts() {
        println!(
            "S_SCOPE_DYNAMIC {name} bytes={} align={}",
            layout.size(),
            layout.align()
        );
    }
    println!(
        "S_INLINE_X attempt={} delivery={} (already in enclosing body; no double charge)",
        std::mem::size_of::<saddle_boundary::reserved_diagnostics::ReservedAttempt<'static>>(),
        std::mem::size_of::<saddle_boundary::reserved_diagnostics::ReservedDelivery<'static>>()
    );
    let (stream, cycle, _) = saddle_observability::root_diagnostic::original_capture_layout();
    let logging = saddle_observability::root_diagnostic::request_logging_layouts();
    println!(
        "S_LOG_DOMAIN stream={} cycle={} frame={} packet={} slots={}; source synchronous stack != retained task heap; queue remains existing log domain",
        stream.size(),
        cycle.size(),
        logging.source_frame.size(),
        logging.emergency_packet.size(),
        logging.emergency_slots
    );
}

saddle::transaction_logic! {
    fn small_layout(_tx:Accounts; bytes:[u8;8])->(u64,()) {
        tokio::task::yield_now().await;
        Ok(std::hint::black_box(bytes)[0] as u64)
    }
}
saddle::transaction_logic! {
    fn large_layout(_tx:Accounts; bytes:[u8;4096])->(u64,()) {
        tokio::task::yield_now().await;
        Ok(std::hint::black_box(bytes)[0] as u64)
    }
}
#[cfg(cf_non_send)]
saddle::transaction_logic! {
    fn forbidden_send(_tx:Accounts; value:std::rc::Rc<u64>)->(u64,()) {
        tokio::task::yield_now().await; Ok(*value)
    }
}
#[cfg(cf_undeclared)]
saddle::transaction_logic! {
    fn forbidden_operation(tx:Accounts;)->(u64,()) {
        tx.not_declared().await; Ok(0)
    }
}
#[cfg(cf_escape)]
saddle::transaction_logic! {
    fn forbidden_escape(tx:Accounts;)->(&'static str,()) {
        tokio::spawn(async move {tx.read(ops::ReadParams{id:1}).await}); Ok("no")
    }
}