Skip to content

Commit

Permalink
Reuse the runtime on blocking initializations
Browse files Browse the repository at this point in the history
  • Loading branch information
giarc3 committed Oct 24, 2024
1 parent 8ad9e95 commit 3f6e3c7
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 21 deletions.
56 changes: 38 additions & 18 deletions src/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,29 @@ use crate::{
InitAndRotationCheck::{NoRotationNeeded, RotationNeeded},
Result,
};
use std::collections::HashMap;
use std::{collections::HashMap, sync::Arc};

#[cfg(feature = "beta")]
use crate::search::{BlindIndexSearchInitialize, EncryptedBlindIndexSalt};
use tokio::runtime::Runtime;

/// Struct that is used to hold the regular DeviceContext as well as a runtime that will be used
/// when initializing a BlockingIronOxide. This was added to fix a bug where initializing multiple
/// SDK instances with a single device would hang indefinitely (as each initialization call would
/// create its own runtime but share a request client)
#[derive(Clone, Debug)]
pub struct BlockingDeviceContext {
pub device: DeviceContext,
pub(crate) rt: Arc<Runtime>,
}

/// Struct that is used to make authenticated requests to the IronCore API. Instantiated with the details
/// of an account's various ids, device, and signing keys. Once instantiated all operations will be
/// performed in the context of the account provided. Identical to IronOxide but also contains a Runtime.
#[derive(Debug)]
pub struct BlockingIronOxide {
pub(crate) ironoxide: IronOxide,
pub(crate) runtime: tokio::runtime::Runtime,
pub(crate) runtime: Arc<tokio::runtime::Runtime>,
}

impl BlockingIronOxide {
Expand Down Expand Up @@ -237,14 +248,20 @@ impl BlockingIronOxide {
password: &str,
device_create_options: &DeviceCreateOpts,
timeout: Option<std::time::Duration>,
) -> Result<DeviceAddResult> {
) -> Result<BlockingDeviceContext> {
let rt = create_runtime();
rt.block_on(IronOxide::generate_new_device(
jwt,
password,
device_create_options,
timeout,
))
let device: DeviceContext = rt
.block_on(IronOxide::generate_new_device(
jwt,
password,
device_create_options,
timeout,
))?
.into();
Ok(BlockingDeviceContext {
device,
rt: Arc::new(rt),
})
}
/// See [ironoxide::user::UserOps::user_delete_device](trait.UserOps.html#tymethod.user_delete_device)
pub fn user_delete_device(&self, device_id: Option<&DeviceId>) -> Result<DeviceId> {
Expand Down Expand Up @@ -293,35 +310,38 @@ fn create_runtime() -> tokio::runtime::Runtime {
/// Initialize the BlockingIronOxide SDK with a device. Verifies that the provided user/segment exists and the provided device
/// keys are valid and exist for the provided account. If successful, returns instance of the BlockingIronOxide SDK.
pub fn initialize(
device_context: &DeviceContext,
device_context: &BlockingDeviceContext,
config: &IronOxideConfig,
) -> Result<BlockingIronOxide> {
let rt = create_runtime();
let maybe_io = rt.block_on(crate::initialize(device_context, config));
let maybe_io = device_context
.rt
.block_on(crate::initialize(&device_context.device, config));
maybe_io.map(|io| BlockingIronOxide {
ironoxide: io,
runtime: rt,
runtime: device_context.rt.clone(),
})
}

/// Initialize the BlockingIronOxide SDK and check to see if the user that owns this `DeviceContext` is
/// marked for private key rotation, or if any of the groups that the user is an admin of are marked
/// for private key rotation.
pub fn initialize_check_rotation(
device_context: &DeviceContext,
device_context: &BlockingDeviceContext,
config: &IronOxideConfig,
) -> Result<InitAndRotationCheck<BlockingIronOxide>> {
let rt = create_runtime();
let maybe_init = rt.block_on(crate::initialize_check_rotation(device_context, config));
let maybe_init = device_context.rt.block_on(crate::initialize_check_rotation(
&device_context.device,
config,
));
maybe_init.map(|init| match init {
NoRotationNeeded(io) => NoRotationNeeded(BlockingIronOxide {
ironoxide: io,
runtime: rt,
runtime: device_context.rt.clone(),
}),
RotationNeeded(io, rot) => RotationNeeded(
BlockingIronOxide {
ironoxide: io,
runtime: rt,
runtime: device_context.rt.clone(),
},
rot,
),
Expand Down
2 changes: 1 addition & 1 deletion src/internal/rest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ impl<'a> HeaderIronCoreRequestSig<'a> {
pub struct IronCoreRequest {
base_url: &'static str,
#[serde(skip_serializing, skip_deserializing, default = "default_client")]
client: reqwest::Client,
pub(crate) client: reqwest::Client,
}

fn default_client() -> reqwest::Client {
Expand Down
4 changes: 2 additions & 2 deletions tests/blocking_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mod common;
// Note: The blocking functions need minimal testing as they primarily just call their async counterparts

#[cfg(feature = "blocking")]
mod integration_tests {
mod blocking_integration_tests {
use crate::common::{create_id_all_classes, gen_jwt, USER_PASSWORD};
use galvanic_assert::{matchers::*, *};
use ironoxide::prelude::*;
Expand All @@ -23,7 +23,7 @@ mod integration_tests {
)?
.into();
let creator_sdk = ironoxide::blocking::initialize(&device, &Default::default())?;
// making non-default groups so I can specify needs_rotation of true
// // making non-default groups so I can specify needs_rotation of true
let group_create = creator_sdk.group_create(&GroupCreateOpts::new(
None,
None,
Expand Down

0 comments on commit 3f6e3c7

Please sign in to comment.