saddle-framework 0.3.0-alpha.4

The single business-facing facade for Saddle applications
#![allow(dead_code)]

use prost::Message;
use saddle::{
    application,
    ingress::{ProfuseGwContext, ProfuseGwDispatchError},
    profusecontract::{ExternalFunctionResult, testing::FakeProfuseContractBoundary},
};
use serde::Deserialize;

#[derive(Clone, PartialEq, Message, Deserialize)]
#[serde(deny_unknown_fields)]
struct QueryMyBoundAccountsRequest {}
#[derive(Clone, PartialEq, Message)]
struct QueryMyBoundAccountsResult {
    #[prost(bool, tag = "1")]
    found: bool,
}
#[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,
}

async fn query_my_bound_accounts(
    _request: QueryMyBoundAccountsRequest,
    context: ProfuseGwContext,
    contract: PucProfuseContract,
) -> QueryMyBoundAccountsResult {
    let result = contract
        .query_bound_accounts(QueryBoundAccountsRequest {
            user_id: context.user_id().to_owned(),
        })
        .await;
    match result {
        ExternalFunctionResult::Completed(result) => QueryMyBoundAccountsResult {
            found: result.account_count > 0,
        },
        ExternalFunctionResult::TechnicalFailure(failure) => {
            panic!("unexpected fake failure: {:?}", failure.code())
        }
    }
}

application! {
    schema "saddle-application/2";
    application PucBackend;
    deployment_app "puc-backend";
    profusecontract {
        contract_dir "examples/contracts";
        capability PucProfuseContract;
        functions {
            QueryBoundAccounts => query_bound_accounts {
                business_unit "puc";
                function "查询用户绑定户号";
            } (
                QueryBoundAccountsRequest
            ) -> QueryBoundAccountsResult;
        }
    }
    service QueryMyBoundAccounts {
        ingress profusegw;
        operation_type "alipay.profuse.industry.puc.queryMyBoundAccounts";
        request QueryMyBoundAccountsRequest;
        response QueryMyBoundAccountsResult;
        handler query_my_bound_accounts;
        uses QueryBoundAccounts;
    }
}

#[tokio::main]
async fn main() {
    assert_eq!(PucBackend::PROFUSECONTRACT_DIR, "examples/contracts");
    assert!(!PucBackend::__PROFUSECONTRACT_DESCRIPTOR.is_empty());
    assert_eq!(
        QueryMyBoundAccounts::OPERATION_TYPE,
        "alipay.profuse.industry.puc.queryMyBoundAccounts"
    );
    assert_eq!(
        PucBackend::dispatch_profusegw_operation(
            "alipay.profuse.industry.puc.queryMyBoundAccounts"
        ),
        Some(ProfuseGwDispatch::QueryMyBoundAccounts)
    );
    assert_eq!(PucBackend::dispatch_profusegw_operation("unknown"), None);

    let identity = saddle_boundary::ingress::IngressIdentity::new(
        "request-1",
        "ingress-call",
        1_800_000_000_000,
    )
    .unwrap();
    let accepted = PucBackend::__profusegw_listener_adapter()
        .accept(
            saddle_boundary::ingress::METHOD,
            saddle_boundary::ingress::PATH,
            saddle_boundary::ingress::MEDIA_TYPE,
            identity,
            br#"{
              "target":{"app":"puc-backend","interfaceId":"alipay.profuse.industry.puc.queryMyBoundAccounts"},
              "profuseGwContext":{"userInfo":{"userId":"2088-user"}},
              "requestData":{}
            }"#,
        )
        .unwrap();
    let fake =
        FakeProfuseContractBoundary::completed(QueryBoundAccountsResult { account_count: 2 });
    let observed = fake.clone();
    let seal = fake.bind_accepted(&accepted).unwrap().into_contract_seal();
    let response = PucBackend::__dispatch_accepted_profusegw(
        accepted,
        PucProfuseContract::__from_framework(seal),
    )
    .await
    .unwrap();
    match response {
        ProfuseGwResponse::QueryMyBoundAccounts(response) => assert!(response.found),
    }
    let attempts = observed.attempts();
    assert_eq!(attempts[0].request_id, "request-1");
    assert_eq!(attempts[0].call_id, "ingress-call-1");
    assert_eq!(attempts[0].user_id, "2088-user");

    let foreign = PucBackend::__profusegw_listener_adapter()
        .accept(
            saddle_boundary::ingress::METHOD,
            saddle_boundary::ingress::PATH,
            saddle_boundary::ingress::MEDIA_TYPE,
            saddle_boundary::ingress::IngressIdentity::new("foreign", "call", 1_800_000_000_000)
                .unwrap(),
            br#"{
              "target":{"app":"other-app","interfaceId":"alipay.profuse.industry.puc.queryMyBoundAccounts"},
              "profuseGwContext":{"userInfo":{"userId":"2088-user"}},
              "requestData":{}
            }"#,
        )
        .unwrap_err();
    assert_eq!(foreign.code, "APPLICATION_NOT_FOUND");

    let unknown = PucBackend::__profusegw_listener_adapter()
        .accept(
            saddle_boundary::ingress::METHOD,
            saddle_boundary::ingress::PATH,
            saddle_boundary::ingress::MEDIA_TYPE,
            saddle_boundary::ingress::IngressIdentity::new("unknown", "call", 1_800_000_000_000)
                .unwrap(),
            br#"{
              "target":{"app":"puc-backend","interfaceId":"unknown.interface"},
              "profuseGwContext":{"userInfo":{"userId":"2088-user"}},
              "requestData":{}
            }"#,
        )
        .unwrap();
    let seal =
        FakeProfuseContractBoundary::completed(QueryBoundAccountsResult { account_count: 0 })
            .bind_accepted(&unknown)
            .unwrap()
            .into_contract_seal();
    assert!(matches!(
        PucBackend::__dispatch_accepted_profusegw(
            unknown,
            PucProfuseContract::__from_framework(seal)
        )
        .await,
        Err(ProfuseGwDispatchError::InterfaceNotFound)
    ));

    let invalid_request = PucBackend::__profusegw_listener_adapter()
        .accept(
            saddle_boundary::ingress::METHOD,
            saddle_boundary::ingress::PATH,
            saddle_boundary::ingress::MEDIA_TYPE,
            saddle_boundary::ingress::IngressIdentity::new("invalid", "call", 1_800_000_000_000)
                .unwrap(),
            br#"{
              "target":{"app":"puc-backend","interfaceId":"alipay.profuse.industry.puc.queryMyBoundAccounts"},
              "profuseGwContext":{"userInfo":{"userId":"2088-user"}},
              "requestData":{"unexpected":true}
            }"#,
        )
        .unwrap();
    let seal =
        FakeProfuseContractBoundary::completed(QueryBoundAccountsResult { account_count: 0 })
            .bind_accepted(&invalid_request)
            .unwrap()
            .into_contract_seal();
    assert!(matches!(
        PucBackend::__dispatch_accepted_profusegw(
            invalid_request,
            PucProfuseContract::__from_framework(seal)
        )
        .await,
        Err(ProfuseGwDispatchError::RequestDataInvalid)
    ));

    let binding =
        FakeProfuseContractBoundary::completed(QueryBoundAccountsResult { account_count: 2 })
            .bind("2088-user", 1_800_000_000_000);
    let context = binding.profusegw_context();
    let seal = binding.into_contract_seal();
    let response = query_my_bound_accounts(
        QueryMyBoundAccountsRequest {},
        context,
        PucProfuseContract::__from_framework(seal),
    )
    .await;
    assert!(response.found);
}