Skip to content

Commit

Permalink
add cell id to allow bridge calls in call
Browse files Browse the repository at this point in the history
  • Loading branch information
freesig committed Nov 6, 2020
1 parent 0db6a8f commit 1af620b
Show file tree
Hide file tree
Showing 19 changed files with 232 additions and 161 deletions.
17 changes: 13 additions & 4 deletions crates/hdk/src/host_fn/call.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::prelude::*;
use holo_hash::{AgentPubKey, DnaHash};
use holochain_wasmer_guest::SerializedBytesError;
use holochain_zome_types::{
call::Call,
Expand All @@ -8,9 +7,19 @@ use holochain_zome_types::{

use crate::host_fn;

/// # Call
/// Make a Zome call in another Zome.
/// The Zome can be in another Cell or the
/// same Cell but must be installed on the same conductor.
///
/// ## Parameters
/// - to_cell: The cell you want to call (If None will call the current cell).
/// - zome_name: The name of the zome you want to call.
/// - fn_name: The name of the function in the zome you are calling.
/// - cap_secret: The capability secret if required.
/// - request: The arguments to the function you are calling.
pub fn call<I, O>(
to_agent: AgentPubKey,
to_dna: Option<DnaHash>,
to_cell: Option<CellId>,
zome_name: ZomeName,
fn_name: FunctionName,
cap_secret: Option<CapSecret>,
Expand All @@ -25,7 +34,7 @@ where
let out = host_fn!(
__call,
CallInput::new(Call::new(
to_agent, to_dna, zome_name, fn_name, cap_secret, request, provenance
to_cell, zome_name, fn_name, cap_secret, request, provenance
)),
CallOutput
)?;
Expand Down
1 change: 1 addition & 0 deletions crates/hdk/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub use holochain_zome_types;
pub use holochain_zome_types::agent_info::AgentInfo;
pub use holochain_zome_types::call_remote::CallRemote;
pub use holochain_zome_types::capability::*;
pub use holochain_zome_types::cell::*;
pub use holochain_zome_types::crdt::CrdtType;
pub use holochain_zome_types::debug_msg;
pub use holochain_zome_types::element::{Element, ElementVec};
Expand Down
5 changes: 5 additions & 0 deletions crates/holochain/src/conductor/api/api_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ pub trait CellConductorApiT: Clone + Send + Sync + Sized {
/// A handle that cn only call zome functions to avoid
/// making write lock calls
pub trait CellConductorReadHandleT: Send + Sync {
/// Get this cell id
fn cell_id(&self) -> &CellId;
/// Invoke a zome function on a Cell
async fn call_zome(
&self,
Expand All @@ -157,6 +159,9 @@ pub trait CellConductorReadHandleT: Send + Sync {

#[async_trait]
impl CellConductorReadHandleT for CellConductorApi {
fn cell_id(&self) -> &CellId {
&self.cell_id
}
async fn call_zome(
&self,
invocation: ZomeCallInvocation,
Expand Down
133 changes: 116 additions & 17 deletions crates/holochain/src/core/ribosome/host_fn/call.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
use crate::core::ribosome::CallContext;
use crate::core::ribosome::RibosomeT;
use crate::core::ribosome::{error::RibosomeResult, ZomeCallInvocation};
use holochain_types::cell::CellId;
use holochain_zome_types::{CallInput, ZomeCallResponse};
use holochain_zome_types::{CallOutput, ExternInput};
use std::sync::Arc;

pub fn call(
ribosome: Arc<impl RibosomeT>,
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: CallInput,
) -> RibosomeResult<CallOutput> {
// Get the input
let call = input.into_inner();
let dna_hash = call
.to_dna
.unwrap_or_else(|| ribosome.dna_file().dna_hash().clone());
let to_agent = call.to_agent;
let cell_id = CellId::new(dna_hash, to_agent);

// Get the conductor handle
let host_access = call_context.host_access();
let conductor_handle = host_access.call_zome_handle();
let workspace = host_access.workspace();

// Get the cell id if it's not passed in
let cell_id = call
.to_cell
.unwrap_or_else(|| conductor_handle.cell_id().clone());

// Create the invocation for this call
let invocation = ZomeCallInvocation {
cell_id,
zome_name: call.zome_name,
Expand All @@ -25,11 +32,10 @@ pub fn call(
payload: ExternInput::new(call.request),
provenance: call.provenance,
};
let host_access = call_context.host_access();

// Make the call using this workspace
let result: ZomeCallResponse = tokio_safe_block_on::tokio_safe_block_forever_on(async move {
let call_zome_handle = host_access.call_zome_handle();
let workspace = host_access.workspace();
call_zome_handle
conductor_handle
.call_zome(invocation, workspace)
.await
.map_err(Box::new)
Expand All @@ -40,17 +46,23 @@ pub fn call(

#[cfg(test)]
pub mod wasm_test {
use std::convert::TryInto;
use std::convert::{TryFrom, TryInto};

use hdk3::prelude::AgentInfo;
use hdk3::prelude::{AgentInfo, CellId};
use holo_hash::HeaderHash;
use holochain_serialized_bytes::SerializedBytes;
use holochain_types::{
app::InstalledCell,
dna::{DnaDef, DnaFile},
};
use holochain_wasm_test_utils::TestWasm;
use holochain_zome_types::{ExternInput, ZomeCallResponse};
use holochain_zome_types::{test_utils::fake_agent_pubkey_2, ExternInput, ZomeCallResponse};
use matches::assert_matches;

use crate::{
core::ribosome::ZomeCallInvocation,
test_utils::{conductor_setup::ConductorTestData, new_invocation},
conductor::ConductorHandle,
core::{ribosome::ZomeCallInvocation, state::element_buf::ElementBuf},
test_utils::{conductor_setup::ConductorTestData, install_app, new_invocation},
};

#[tokio::test(threaded_scheduler)]
Expand Down Expand Up @@ -94,7 +106,7 @@ pub mod wasm_test {
zome_name: TestWasm::WhoAmI.into(),
cap: None,
fn_name: "who_are_they_local".into(),
payload: ExternInput::new(bob_agent_id.clone().try_into().unwrap()),
payload: ExternInput::new(bob_cell_id.clone().try_into().unwrap()),
provenance: alice_agent_id.clone(),
})
.await
Expand Down Expand Up @@ -139,6 +151,93 @@ pub mod wasm_test {
new_invocation(&alice_cell_id, "call_create_entry", (), TestWasm::Create).unwrap();
let result = handle.call_zome(invocation).await;
assert_matches!(result, Ok(Ok(ZomeCallResponse::Ok(_))));

// Get the header hash of that entry
let header_hash: HeaderHash =
unwrap_to::unwrap_to!(result.unwrap().unwrap() => ZomeCallResponse::Ok)
.clone()
.into_inner()
.try_into()
.unwrap();

// Check alice's source chain contains the new value
let alice_source_chain =
ElementBuf::authored(alice_call_data.env.clone().into(), true).unwrap();
let el = alice_source_chain.get_element(&header_hash).unwrap();
assert_matches!(el, Some(_));

ConductorTestData::shutdown_conductor(handle).await;
}

/// test calling a different zome
/// in a different cell.
#[tokio::test(threaded_scheduler)]
async fn bridge_call() {
observability::test_run().ok();

let zomes = vec![TestWasm::Create];
let conductor_test = ConductorTestData::new(zomes, false).await;
let ConductorTestData {
__tmpdir,
handle,
alice_call_data,
..
} = conductor_test;
let alice_cell_id = &alice_call_data.cell_id;

// Install a different dna for bob
let zomes = vec![TestWasm::WhoAmI];
let bob_cell_id = install_new_app("bobs_dna", zomes, &handle).await;

// Call create_entry in the create_entry zome from the whoami zome
let invocation = new_invocation(
&bob_cell_id,
"call_create_entry",
alice_cell_id.clone(),
TestWasm::WhoAmI,
)
.unwrap();
let result = handle.call_zome(invocation).await;
assert_matches!(result, Ok(Ok(ZomeCallResponse::Ok(_))));

// Get the header hash of that entry
let header_hash: HeaderHash =
unwrap_to::unwrap_to!(result.unwrap().unwrap() => ZomeCallResponse::Ok)
.clone()
.into_inner()
.try_into()
.unwrap();

// Check alice's source chain contains the new value
let alice_source_chain =
ElementBuf::authored(alice_call_data.env.clone().into(), true).unwrap();
let el = alice_source_chain.get_element(&header_hash).unwrap();
assert_matches!(el, Some(_));

ConductorTestData::shutdown_conductor(handle).await;
}

async fn install_new_app(
dna_name: &str,
zomes: Vec<TestWasm>,
handle: &ConductorHandle,
) -> CellId {
let dna_file = DnaFile::new(
DnaDef {
name: dna_name.to_string(),
uuid: "ba1d046d-ce29-4778-914b-47e6010d2faf".to_string(),
properties: SerializedBytes::try_from(()).unwrap(),
zomes: zomes.clone().into_iter().map(Into::into).collect(),
},
zomes.into_iter().map(Into::into),
)
.await
.unwrap();
let bob_agent_id = fake_agent_pubkey_2();
let bob_cell_id = CellId::new(dna_file.dna_hash().to_owned(), bob_agent_id.clone());
let bob_installed_cell = InstalledCell::new(bob_cell_id.clone(), "bob_handle".into());
let cell_data = vec![(bob_installed_cell, None)];
install_app("bob_app", cell_data, vec![dna_file], handle.clone()).await;
bob_cell_id
}
}
10 changes: 1 addition & 9 deletions crates/holochain/src/core/ribosome/host_fn/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ pub fn extract_entry_def(
#[cfg(feature = "slow_tests")]
pub mod wasm_test {
use super::create;
use crate::conductor::dna_store::MockDnaStore;
use crate::core::ribosome::error::RibosomeError;
use crate::core::ribosome::ZomeCallInvocation;
use crate::core::state::source_chain::ChainInvalidReason;
Expand Down Expand Up @@ -329,19 +328,12 @@ pub mod wasm_test {
// START CONDUCTOR
// ///////////////

let mut dna_store = MockDnaStore::new();

dna_store.expect_get().return_const(Some(dna_file.clone()));
dna_store.expect_add_dnas::<Vec<_>>().return_const(());
dna_store.expect_add_entry_defs::<Vec<_>>().return_const(());
dna_store.expect_get_entry_def().return_const(None);

let (_tmpdir, _app_api, handle) = setup_app(
vec![(
"APPropriated",
vec![(alice_installed_cell, None), (bob_installed_cell, None)],
)],
dna_store,
vec![dna_file.clone()],
)
.await;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
conductor::{dna_store::MockDnaStore, ConductorHandle},
conductor::ConductorHandle,
core::ribosome::ZomeCallInvocation,
core::state::dht_op_integration::IntegratedDhtOpsValue,
core::state::validation_db::ValidationLimboValue,
Expand Down Expand Up @@ -62,19 +62,12 @@ async fn app_validation_workflow_test() {
let bob_cell_id = CellId::new(dna_file.dna_hash().to_owned(), bob_agent_id.clone());
let bob_installed_cell = InstalledCell::new(bob_cell_id.clone(), "bob_handle".into());

let mut dna_store = MockDnaStore::new();

dna_store.expect_get().return_const(Some(dna_file.clone()));
dna_store.expect_add_dnas::<Vec<_>>().return_const(());
dna_store.expect_add_entry_defs::<Vec<_>>().return_const(());
dna_store.expect_get_entry_def().return_const(None);

let (_tmpdir, _app_api, handle) = setup_app(
vec![(
"test_app",
vec![(alice_installed_cell, None), (bob_installed_cell, None)],
)],
dna_store,
vec![dna_file.clone()],
)
.await;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use crate::{
conductor::{
api::error::ConductorApiError, dna_store::MockDnaStore, CellError, ConductorHandle,
},
conductor::{api::error::ConductorApiError, CellError, ConductorHandle},
core::workflow::error::WorkflowError,
core::SourceChainError,
test_utils::{new_invocation, setup_app},
Expand Down Expand Up @@ -33,16 +31,9 @@ async fn direct_validation_test() {
let alice_cell_id = CellId::new(dna_file.dna_hash().to_owned(), alice_agent_id.clone());
let alice_installed_cell = InstalledCell::new(alice_cell_id.clone(), "alice_handle".into());

let mut dna_store = MockDnaStore::new();

dna_store.expect_get().return_const(Some(dna_file.clone()));
dna_store.expect_add_dnas::<Vec<_>>().return_const(());
dna_store.expect_add_entry_defs::<Vec<_>>().return_const(());
dna_store.expect_get_entry_def().return_const(None);

let (_tmpdir, _app_api, handle) = setup_app(
vec![("test_app", vec![(alice_installed_cell, None)])],
dna_store,
vec![dna_file.clone()],
)
.await;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1309,9 +1309,9 @@ mod slow_tests {

use crate::test_utils::setup_app;
use crate::{
conductor::dna_store::MockDnaStore, core::state::dht_op_integration::IntegratedDhtOpsStore,
core::state::metadata::LinkMetaKey, core::state::metadata::MetadataBuf,
core::state::metadata::MetadataBufT, test_utils::host_fn_api::*,
core::state::dht_op_integration::IntegratedDhtOpsStore, core::state::metadata::LinkMetaKey,
core::state::metadata::MetadataBuf, core::state::metadata::MetadataBufT,
test_utils::host_fn_api::*,
};
use crate::{fixt::*, test_utils::wait_for_integration};
use fallible_iterator::FallibleIterator;
Expand Down Expand Up @@ -1357,19 +1357,12 @@ mod slow_tests {
let bob_cell_id = CellId::new(dna_file.dna_hash().to_owned(), bob_agent_id.clone());
let bob_installed_cell = InstalledCell::new(bob_cell_id.clone(), "bob_handle".into());

let mut dna_store = MockDnaStore::new();

dna_store.expect_get().return_const(Some(dna_file.clone()));
dna_store.expect_add_dnas::<Vec<_>>().return_const(());
dna_store.expect_add_entry_defs::<Vec<_>>().return_const(());
dna_store.expect_get_entry_def().return_const(None);

let (_tmpdir, _app_api, conductor) = setup_app(
vec![(
"test_app",
vec![(alice_installed_cell, None), (bob_installed_cell, None)],
)],
dna_store,
vec![dna_file.clone()],
)
.await;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ use holochain_zome_types::test_utils::fake_agent_pubkey_1;

use super::*;
use crate::{
conductor::dna_store::MockDnaStore, conductor::ConductorHandle,
core::state::source_chain::SourceChain, test_utils::setup_app,
conductor::ConductorHandle, core::state::source_chain::SourceChain, test_utils::setup_app,
test_utils::wait_for_integration,
};
use ::fixt::prelude::*;
Expand Down Expand Up @@ -44,16 +43,9 @@ async fn sys_validation_agent_activity_test() {
let alice_cell_id = CellId::new(dna_file.dna_hash().to_owned(), alice_agent_id.clone());
let alice_installed_cell = InstalledCell::new(alice_cell_id.clone(), "alice_handle".into());

let mut dna_store = MockDnaStore::new();

dna_store.expect_get().return_const(Some(dna_file.clone()));
dna_store.expect_add_dnas::<Vec<_>>().return_const(());
dna_store.expect_add_entry_defs::<Vec<_>>().return_const(());
dna_store.expect_get_entry_def().return_const(None);

let (_tmpdir, _app_api, handle) = setup_app(
vec![("test_app", vec![(alice_installed_cell, None)])],
dna_store,
vec![dna_file.clone()],
)
.await;

Expand Down

1 comment on commit 1af620b

@thedavidmeister
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmarking wasm_call_n/1: Analyzing
wasm_call_n/1           time:   [1.5723 ms 1.5754 ms 1.5791 ms]
                        thrpt:  [633.27   B/s 634.78   B/s 636.00   B/s]
                 change:
                        time:   [-0.3806% +0.8045% +2.2691%] (p = 0.26 > 0.05)
                        thrpt:  [-2.2188% -0.7981% +0.3820%]
                        No change in performance detected.
Found 18 outliers among 100 measurements (18.00%)
  2 (2.00%) high mild
  16 (16.00%) high severe
Benchmarking wasm_call_n/1000
Benchmarking wasm_call_n/1000: Analyzing
wasm_call_n/1000        time:   [1.5866 ms 1.5885 ms 1.5906 ms]
                        thrpt:  [613.96 KiB/s 614.78 KiB/s 615.52 KiB/s]
                 change:
                        time:   [-3.7688% -3.5163% -3.2449%] (p = 0.00 < 0.05)
                        thrpt:  [+3.3537% +3.6445% +3.9164%]
                        Performance has improved.
Found 6 outliers among 100 measurements (6.00%)
  3 (3.00%) high mild
  3 (3.00%) high severe
Benchmarking wasm_call_n/1000000
Benchmarking wasm_call_n/1000000: Analyzing
wasm_call_n/1000000     time:   [27.023 ms 27.097 ms 27.175 ms]
                        thrpt:  [35.094 MiB/s 35.194 MiB/s 35.291 MiB/s]
                 change:
                        time:   [-0.3774% +0.2122% +0.7882%] (p = 0.47 > 0.05)
                        thrpt:  [-0.7820% -0.2118% +0.3788%]
                        No change in performance detected.
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high mild```

Please sign in to comment.