diff --git a/Cargo.lock b/Cargo.lock index 38a68042..ab3ae552 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -611,6 +611,7 @@ dependencies = [ "napi-derive", "serde", "serde_json", + "talos_agent", "talos_certifier", "talos_certifier_adapters", "talos_cohort_replicator", diff --git a/cohort_banking_initiator_js/src/banking-app.ts b/cohort_banking_initiator_js/src/banking-app.ts index 281ce53b..1395ed35 100644 --- a/cohort_banking_initiator_js/src/banking-app.ts +++ b/cohort_banking_initiator_js/src/banking-app.ts @@ -95,7 +95,7 @@ export class BankingApp { let stateDuration = 0 let ooinstallEnd = 0 let ooinstallDuration = 0 - await this.initiator.certify( + let result = await this.initiator.certify( async () => { const s = Date.now() const newRequest = await this.createNewRequest(tx) as any @@ -114,6 +114,8 @@ export class BankingApp { } ) + // logger.info("tx: %s - [%s]; Completed in [attempts=%s, ms=%s]", result.xid, result.decision, result.metadata.attempts, result.metadata.durationMs) + return { stateDuration, stateEnd, ooinstallDuration, ooinstallEnd } } diff --git a/cohort_sdk_client/src/index.ts b/cohort_sdk_client/src/index.ts index c3020b7c..e3f76780 100644 --- a/cohort_sdk_client/src/index.ts +++ b/cohort_sdk_client/src/index.ts @@ -2,9 +2,12 @@ import { Initiator } from "./initiator" import { Replicator } from "./replicator" import { JsCertificationRequestPayload, + JsCertificationResponse, + JsDecision, JsInitiatorConfig, JsKafkaConfig, JsReplicatorConfig, + JsResponseMetadata, JsStatemapAndSnapshot, JsOutOfOrderInstallOutcome, OutOfOrderRequest, @@ -20,10 +23,13 @@ class TalosSdkError extends Error { export { Initiator, + JsDecision, JsInitiatorConfig, + JsCertificationResponse, JsCertificationRequestPayload, JsKafkaConfig, JsReplicatorConfig, + JsResponseMetadata, JsStatemapAndSnapshot, JsOutOfOrderInstallOutcome, OutOfOrderRequest, diff --git a/cohort_sdk_client/src/initiator.ts b/cohort_sdk_client/src/initiator.ts index 683d206c..4b452d86 100644 --- a/cohort_sdk_client/src/initiator.ts +++ b/cohort_sdk_client/src/initiator.ts @@ -1,4 +1,4 @@ -import { InternalInitiator, JsInitiatorConfig, OutOfOrderRequest, SdkErrorKind } from "@kindredgroup/cohort_sdk_js" +import { InternalInitiator, JsInitiatorConfig, OutOfOrderRequest, SdkErrorKind, JsCertificationResponse } from "@kindredgroup/cohort_sdk_js" import { isSdkError } from "./internal" import { TalosSdkError } from "." @@ -19,7 +19,7 @@ export class Initiator { constructor(readonly impl: InternalInitiator) {} - async certify(makeNewRequestCallback: () => Promise, oooCallback: (err: Error | null, value: OutOfOrderRequest) => any): Promise { + async certify(makeNewRequestCallback: () => Promise, oooCallback: (err: Error | null, value: OutOfOrderRequest) => any): Promise { try { return await this.impl.certify(makeNewRequestCallback, oooCallback) } catch (e) { diff --git a/packages/cohort_sdk_js/Cargo.toml b/packages/cohort_sdk_js/Cargo.toml index 358c93ee..319371e6 100644 --- a/packages/cohort_sdk_js/Cargo.toml +++ b/packages/cohort_sdk_js/Cargo.toml @@ -34,6 +34,7 @@ log = { workspace = true } tokio = { workspace = true, features = ["full"] } cohort_sdk = { path = "../cohort_sdk" } +talos_agent = { path = "../talos_agent" } talos_cohort_replicator = { path = "../talos_cohort_replicator" } talos_certifier = { path = "../talos_certifier" } talos_certifier_adapters = { path = "../talos_certifier_adapters" } diff --git a/packages/cohort_sdk_js/scripts/postinstall.sh b/packages/cohort_sdk_js/scripts/postinstall.sh index 8785fc12..9d82a685 100755 --- a/packages/cohort_sdk_js/scripts/postinstall.sh +++ b/packages/cohort_sdk_js/scripts/postinstall.sh @@ -36,9 +36,13 @@ echo "D: lenMinusOne=$lenMinusOne, lenMinusTwo=$lenMinusTwo, lenMinusThree=$lenM lastPathToken="${pathTokens[lenMinusFour]}/${pathTokens[lenMinusThree]}/${pathTokens[lenMinusTwo]}"/"${pathTokens[lenMinusOne]}" echo "D: lastPathToken=$lastPathToken" -if [ "$lastPathToken" == "cohort_sdk_client/node_modules/@kindredgroup/cohort_sdk_js" ]; then - echo "Post install script of 'cohort_sdk_js' is designed to be executed when module is installed as transitional dependency. Currently, 'npm install' is running as part of installing 'cohort_sdk_client'. Postinstall script is skipped." - exit 0 +if [ "$COHORT_SDK_CLIENT_DEV_MODE" == "true" ]; then + echo "Post install script of 'cohort_sdk_js' is running as transitional dependency. Enforced by COHORT_SDK_CLIENT_DEV_MODE=${COHORT_SDK_CLIENT_DEV_MODE}" +else + if [ "$lastPathToken" == "cohort_sdk_client/node_modules/@kindredgroup/cohort_sdk_js" ]; then + echo "Post install script of 'cohort_sdk_js' is designed to be executed when module is installed as transitional dependency. Currently, 'npm install' is running as part of installing 'cohort_sdk_client'. Postinstall script is skipped." + exit 0 + fi fi echo "Post install. Current directory is: $CURRENT_DIR" diff --git a/packages/cohort_sdk_js/src/initiator/mod.rs b/packages/cohort_sdk_js/src/initiator/mod.rs index b3c30c51..f9806130 100644 --- a/packages/cohort_sdk_js/src/initiator/mod.rs +++ b/packages/cohort_sdk_js/src/initiator/mod.rs @@ -1,4 +1,4 @@ -use crate::models::{JsBackoffConfig, JsKafkaConfig}; +use crate::models::{JsBackoffConfig, JsDecision, JsKafkaConfig}; use crate::sdk_errors::SdkErrorContainer; use async_trait::async_trait; use cohort_sdk::cohort::Cohort; @@ -6,7 +6,7 @@ use cohort_sdk::model::callback::{ CertificationCandidate, CertificationCandidateCallbackResponse, CertificationRequestPayload, OutOfOrderInstallOutcome, OutOfOrderInstallRequest, OutOfOrderInstaller, }; -use cohort_sdk::model::{ClientError, Config}; +use cohort_sdk::model::{CertificationResponse, ClientError, Config, ResponseMetadata}; use napi::bindgen_prelude::FromNapiValue; use napi::bindgen_prelude::Promise; use napi::bindgen_prelude::ToNapiValue; @@ -126,6 +126,46 @@ impl From for OutOfOrderInstallOutcome { } } +#[napi(object)] +pub struct JsCertificationResponse { + pub xid: String, + pub decision: JsDecision, + pub version: i64, + pub safepoint: Option, + pub conflict: Option, + pub metadata: JsResponseMetadata, + pub statemaps: Option>>, +} + +impl From for JsCertificationResponse { + fn from(value: CertificationResponse) -> Self { + Self { + xid: value.xid, + decision: value.decision.into(), + version: value.version as i64, + safepoint: value.safepoint.map(|v| v as i64), + conflict: value.conflict.map(|v| v as i64), + metadata: value.metadata.into(), + statemaps: value.statemaps, + } + } +} + +impl From for JsResponseMetadata { + fn from(value: ResponseMetadata) -> Self { + Self { + attempts: value.attempts, + duration_ms: value.duration_ms as i64, + } + } +} + +#[napi(object)] +pub struct JsResponseMetadata { + pub attempts: u32, + pub duration_ms: i64, +} + #[napi] pub struct InternalInitiator { cohort: Cohort, @@ -144,12 +184,12 @@ impl InternalInitiator { &self, #[napi(ts_arg_type = "() => Promise")] make_new_request_callback: ThreadsafeFunction<()>, ooo_callback: ThreadsafeFunction, - ) -> napi::Result<()> { + ) -> napi::Result { let new_request_provider = NewRequestProvider { make_new_request_callback }; let ooo_impl = OutOfOrderInstallerImpl { ooo_callback }; let make_new_request = || new_request_provider.make_new_request(); - let _res = self.cohort.certify(&make_new_request, &ooo_impl).await.map_err(map_error)?; - Ok(()) + let response = self.cohort.certify(&make_new_request, &ooo_impl).await.map_err(map_error)?; + Ok(response.into()) } } diff --git a/packages/cohort_sdk_js/src/models/mod.rs b/packages/cohort_sdk_js/src/models/mod.rs index 633201bc..4bcf5823 100644 --- a/packages/cohort_sdk_js/src/models/mod.rs +++ b/packages/cohort_sdk_js/src/models/mod.rs @@ -1,9 +1,11 @@ +use cohort_sdk::model::BackoffConfig; use std::collections::HashMap; +use talos_agent::messaging::api::Decision; +use talos_rdkafka_utils::kafka_config::KafkaConfig; -// $coverage:ignore-start -use cohort_sdk::model::BackoffConfig; +use napi::bindgen_prelude::FromNapiValue; +use napi::bindgen_prelude::ToNapiValue; use napi_derive::napi; -use talos_rdkafka_utils::kafka_config::KafkaConfig; #[napi(object)] pub struct JsBackoffConfig { @@ -57,3 +59,18 @@ impl From for KafkaConfig { } } } + +#[napi(string_enum)] +pub enum JsDecision { + Committed, + Aborted, +} + +impl From for JsDecision { + fn from(value: Decision) -> Self { + match value { + Decision::Committed => JsDecision::Committed, + Decision::Aborted => JsDecision::Aborted, + } + } +}