Skip to content

Commit

Permalink
feat: remove configuration dependency from user index (#230)
Browse files Browse the repository at this point in the history
* add configuration methods and remove calls to configuration canister; drop known_principal_ids from canisterdata

* remove custom install code; recharge canister before resetting them

* ignore tests which involves upgrading cansiter

* send init args to indvidual canister

* fix: pick version from init args in user_index canister

* added tests

* stop upgrading individual canister in post-upgrade of user_index
  • Loading branch information
ravi-sawlani-yral authored Jan 12, 2024
1 parent 08db52e commit 8224058
Show file tree
Hide file tree
Showing 27 changed files with 477 additions and 101 deletions.
2 changes: 0 additions & 2 deletions .cargo/config.toml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ fn init_impl(init_args: IndividualUserTemplateInitArgs, data: &mut CanisterData)
data.profile.principal_id = init_args.profile_owner;

data.configuration.url_to_send_canister_metrics_to = init_args.url_to_send_canister_metrics_to;

data.version_details.version_number = init_args.upgrade_version_number.unwrap_or_default();
data.version_details.version = init_args.version;
}

pub fn send_canister_metrics() {
Expand Down Expand Up @@ -115,5 +118,7 @@ mod test {
data.configuration.url_to_send_canister_metrics_to,
Some("http://metrics-url.com/receive-metrics".to_string())
);

assert!(data.version_details.version.eq("v1.0.0"));
}
}
11 changes: 8 additions & 3 deletions src/canister/user_index/can.did
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ type Result = variant {
Err : record { RejectionCode; text };
};
type Result_1 = variant { Ok : text; Err : text };
type Result_2 = variant { Ok; Err : SetUniqueUsernameError };
type Result_2 = variant { Ok; Err : text };
type Result_3 = variant { Ok; Err : SetUniqueUsernameError };
type SetUniqueUsernameError = variant {
UsernameAlreadyTaken;
SendingCanisterDoesNotMatchUserCanisterId;
Expand Down Expand Up @@ -69,7 +70,11 @@ type UserIndexInitArgs = record {
access_control_map : opt vec record { principal; vec UserAccessRole };
};
service : (UserIndexInitArgs) -> {
are_signups_enabled : () -> (bool) query;
backup_all_individual_user_canisters : () -> ();
get_current_list_of_all_well_known_principal_values : () -> (
vec record { KnownPrincipalType; principal },
) query;
get_index_details_is_user_name_taken : (text) -> (bool) query;
get_index_details_last_upgrade_status : () -> (UpgradeStatus) query;
get_list_of_available_canisters : () -> (vec principal) query;
Expand All @@ -94,15 +99,15 @@ service : (UserIndexInitArgs) -> {
reset_user_individual_canisters : (vec principal) -> (Result_1);
set_permission_to_upgrade_individual_canisters : (bool) -> (text);
start_upgrades_for_individual_canisters : () -> (text);
toggle_signups_enabled : () -> (Result_2);
update_index_with_unique_user_name_corresponding_to_user_principal_id : (
text,
principal,
) -> (Result_2);
) -> (Result_3);
upgrade_specific_individual_user_canister_with_latest_wasm : (
principal,
principal,
opt CanisterInstallMode,
bool,
) -> (text);
validate_reset_user_individual_canisters : (vec principal) -> (
Result_1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ async fn backup_all_individual_user_canisters() {
let global_super_admin_principal_id = CANISTER_DATA.with(|canister_data_ref_cell| {
canister_data_ref_cell
.borrow()
.configuration
.known_principal_ids
.get(&KnownPrincipalType::UserIdGlobalSuperAdmin)
.cloned()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ fn receive_data_from_backup_canister_and_restore_data_to_heap_impl(
unique_user_name: String,
) {
if *canister_data
.configuration
.known_principal_ids
.get(&KnownPrincipalType::CanisterIdDataBackup)
.unwrap()
Expand Down Expand Up @@ -64,7 +65,7 @@ mod test {
fn test_receive_data_from_backup_canister_and_restore_data_to_heap_impl() {
let mut canister_data = CanisterData::default();

canister_data.known_principal_ids.insert(
canister_data.configuration.known_principal_ids.insert(
KnownPrincipalType::CanisterIdDataBackup,
get_mock_canister_id_data_backup(),
);
Expand Down
18 changes: 14 additions & 4 deletions src/canister/user_index/src/api/canister_lifecycle/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ fn init_impl(init_args: UserIndexInitArgs, data: &mut CanisterData) {
.unwrap_or_default()
.iter()
.for_each(|(principal_belongs_to, principal_id)| {
data.known_principal_ids
data.configuration.known_principal_ids
.insert(*principal_belongs_to, *principal_id);
});
data.allow_upgrades_for_individual_canisters = true;
data.last_run_upgrade_status.version = init_args.version;
}

#[cfg(test)]
Expand Down Expand Up @@ -83,22 +84,31 @@ mod test {

// * Check the data
assert_eq!(
data.known_principal_ids
data
.configuration
.known_principal_ids
.get(&KnownPrincipalType::UserIdGlobalSuperAdmin)
.unwrap(),
&get_global_super_admin_principal_id()
);
assert_eq!(
data.known_principal_ids
data
.configuration
.known_principal_ids
.get(&KnownPrincipalType::CanisterIdConfiguration)
.unwrap(),
&get_mock_canister_id_configuration()
);
assert_eq!(
data.known_principal_ids
data
.configuration
.known_principal_ids
.get(&KnownPrincipalType::CanisterIdUserIndex)
.unwrap(),
&get_mock_canister_id_user_index()
);
assert!(
data.last_run_upgrade_status.version.eq("v1.0.0")
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,7 @@ use super::pre_upgrade::BUFFER_SIZE_BYTES;
fn post_upgrade() {
restore_data_from_stable_memory();
update_version_from_args();
refetch_well_known_principals();
upgrade_all_indexed_user_canisters();

CANISTER_DATA.with(|canister_data_ref_cell| {
let well_known_principals = canister_data_ref_cell.borrow().known_principal_ids.clone();

canister_data_ref_cell.borrow_mut().configuration = Configuration {
known_principal_ids: well_known_principals,
signups_open_on_this_subnet: false,
url_to_send_canister_metrics_to:
// "https://amused-welcome-anemone.ngrok-free.app/receive-metrics".to_string(),
"https://receive-canister-metrics-and-push-to-timeseries-d-74gsa5ifla-uc.a.run.app/receive-metrics"
.to_string(),
};
});
// upgrade_all_indexed_user_canisters();
}

fn update_version_from_args() {
Expand Down
21 changes: 12 additions & 9 deletions src/canister/user_index/src/api/canister_management/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub async fn get_user_canister_status(canister_id: Principal) -> CallResult<(Can
#[ic_cdk::update]
pub async fn set_permission_to_upgrade_individual_canisters(flag: bool) -> String {
let api_caller = ic_cdk::caller();
let known_principal_ids = CANISTER_DATA.with(|canister_data_ref_cell| canister_data_ref_cell.borrow().known_principal_ids.clone());
let known_principal_ids = CANISTER_DATA.with(|canister_data_ref_cell| canister_data_ref_cell.borrow().configuration.known_principal_ids.clone());
if *known_principal_ids
.get(&KnownPrincipalType::UserIdGlobalSuperAdmin)
.unwrap()
Expand All @@ -39,7 +39,7 @@ pub async fn set_permission_to_upgrade_individual_canisters(flag: bool) -> Strin
#[ic_cdk::update]
pub async fn start_upgrades_for_individual_canisters() -> String {
let api_caller = ic_cdk::caller();
let known_principal_ids = CANISTER_DATA.with(|canister_data_ref_cell| canister_data_ref_cell.borrow().known_principal_ids.clone());
let known_principal_ids = CANISTER_DATA.with(|canister_data_ref_cell| canister_data_ref_cell.borrow().configuration.known_principal_ids.clone());
if *known_principal_ids
.get(&KnownPrincipalType::UserIdGlobalSuperAdmin)
.unwrap()
Expand Down Expand Up @@ -68,7 +68,7 @@ pub fn get_list_of_available_canisters() -> Vec<Principal> {
pub fn validate_reset_user_individual_canisters(_canisters: Vec<Principal>) -> Result<String, String> {
let caller_id = caller();
let governance_canister_id = CANISTER_DATA.with(|canister_data_ref| {
canister_data_ref.borrow().known_principal_ids.get(&KnownPrincipalType::CanisterIdSnsGovernance).cloned()
canister_data_ref.borrow().configuration.known_principal_ids.get(&KnownPrincipalType::CanisterIdSnsGovernance).cloned()
}).ok_or("Governance Canister Id not found")?;

if caller_id != governance_canister_id {
Expand All @@ -84,25 +84,28 @@ pub fn validate_reset_user_individual_canisters(_canisters: Vec<Principal>) -> R
pub async fn reset_user_individual_canisters(canisters: Vec<Principal>) -> Result<String, String> {
let caller_id = caller();
let governance_canister_id = CANISTER_DATA.with(|canister_data_ref| {
canister_data_ref.borrow().known_principal_ids.get(&KnownPrincipalType::CanisterIdSnsGovernance).cloned()
canister_data_ref.borrow().configuration.known_principal_ids.get(&KnownPrincipalType::CanisterIdSnsGovernance).cloned()
}).ok_or("Governance Canister Id not found")?;

if caller_id != governance_canister_id {
return Err("This method can only be executed through DAO".to_string())
};

let canister_reinstall_futures = canisters.iter().map(|canister| async {
let canister_reinstall_futures = canisters.iter().map(|canister| async move {
canister_management::recharge_canister_if_below_threshold(&canister).await?;
canister_management::upgrade_individual_user_canister(canister.clone(), CanisterInstallMode::Reinstall, IndividualUserTemplateInitArgs {
known_principal_ids: Some(CANISTER_DATA.with(|canister_data_ref| {canister_data_ref.borrow().known_principal_ids.clone()})),
known_principal_ids: Some(CANISTER_DATA.with(|canister_data_ref| {canister_data_ref.borrow().configuration.known_principal_ids.clone()})),
profile_owner: None,
upgrade_version_number: Some(CANISTER_DATA.with(|canister_data_ref| canister_data_ref.borrow().last_run_upgrade_status.version_number)),
url_to_send_canister_metrics_to: Some(CANISTER_DATA.with(|canister_data_ref| canister_data_ref.borrow().configuration.url_to_send_canister_metrics_to.clone())),
version: CANISTER_DATA.with(|canister_data_ref_cell| canister_data_ref_cell.borrow().last_run_upgrade_status.version.clone())
}, false).await?;
Ok(canister.clone())
})
.await
.map_err(|e| (*canister, e.1))?;
Ok(*canister)
});

let result_callback = |reinstall_res: CallResult<Principal>| {
let result_callback = |reinstall_res: Result<Principal, (Principal, String)>| {

match reinstall_res {
Ok(canister_id) => {
Expand Down
1 change: 1 addition & 0 deletions src/canister/user_index/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pub mod upgrade_individual_user_template;
pub mod user_record;
pub mod well_known_principal;
pub mod canister_management;
pub mod user_signup;
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ use ic_cdk::api::management_canister::{
use shared_utils::{
canister_specific::individual_user_template::types::arg::IndividualUserTemplateInitArgs,
common::utils::{system_time, task},
constant::{CYCLES_THRESHOLD_TO_INITIATE_RECHARGE, INDIVIDUAL_USER_CANISTER_RECHARGE_AMOUNT},
};

use crate::{
data_model::{configuration::Configuration, CanisterData},
util::canister_management,
util::canister_management::{self, recharge_canister_if_below_threshold},
CANISTER_DATA,
};

Expand Down Expand Up @@ -90,45 +89,13 @@ pub async fn upgrade_user_canisters_with_latest_wasm() {


async fn recharge_and_upgrade(user_canister_id: Principal, user_principal_id: Principal, version_number: u64, configuration: Configuration, version: String) -> Result<Principal, (Principal, String)> {
let is_canister_below_threshold_balance = is_canister_below_threshold_balance(&user_canister_id).await;

if is_canister_below_threshold_balance {
recharge_canister(&user_canister_id).await.map_err(|s| (user_principal_id, s))?;
}
recharge_canister_if_below_threshold(&user_canister_id).await?;

upgrade_user_canister(&user_principal_id, &user_canister_id, version_number, &configuration, version).await.map_err(|s| (user_principal_id, s))?;

Ok(user_principal_id)
}

async fn is_canister_below_threshold_balance(canister_id: &Principal) -> bool {
let response: Result<(u128,), (_, _)> =
ic_cdk::call(*canister_id, "get_user_caniser_cycle_balance", ()).await;

if response.is_err() {
return true;
}

let (balance,): (u128,) = response.unwrap();

if balance < CYCLES_THRESHOLD_TO_INITIATE_RECHARGE {
return true;
}

false
}

async fn recharge_canister(canister_id: &Principal) -> Result<(), String> {
main::deposit_cycles(
CanisterIdRecord {
canister_id: *canister_id,
},
INDIVIDUAL_USER_CANISTER_RECHARGE_AMOUNT,
)
.await
.map_err(|e| e.1)
}

async fn upgrade_user_canister(
user_principal_id: &Principal,
canister_id: &Principal,
Expand All @@ -148,7 +115,6 @@ async fn upgrade_user_canister(
),
version
},
false
)
.await
.map_err(|e| e.1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ async fn upgrade_specific_individual_user_canister_with_latest_wasm(
user_principal_id: Principal,
user_canister_id: Principal,
upgrade_mode: Option<CanisterInstallMode>,
unsafe_drop_stable_memory: bool
) -> String {
let api_caller = ic_cdk::caller();

let known_principal_ids = CANISTER_DATA
.with(|canister_data_ref_cell| canister_data_ref_cell.borrow().known_principal_ids.clone());
.with(|canister_data_ref_cell| canister_data_ref_cell.borrow().configuration.known_principal_ids.clone());

if *known_principal_ids
.get(&KnownPrincipalType::UserIdGlobalSuperAdmin)
Expand All @@ -44,15 +43,12 @@ async fn upgrade_specific_individual_user_canister_with_latest_wasm(
user_canister_id,
upgrade_mode.unwrap_or(CanisterInstallMode::Upgrade),
IndividualUserTemplateInitArgs {
known_principal_ids: Some(CANISTER_DATA.with(|canister_data_ref_cell| {
canister_data_ref_cell.borrow().known_principal_ids.clone()
})),
known_principal_ids: Some(known_principal_ids.clone()),
profile_owner: Some(user_principal_id),
upgrade_version_number: Some(saved_upgrade_status.version_number + 1),
url_to_send_canister_metrics_to: Some(configuration.url_to_send_canister_metrics_to),
version: saved_upgrade_status.version
},
unsafe_drop_stable_memory
)
.await
{
Expand Down
41 changes: 41 additions & 0 deletions src/canister/user_index/src/api/user_signup/are_signups_enabled.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use crate::{CANISTER_DATA, data_model::CanisterData};


#[ic_cdk::query]
#[candid::candid_method(query)]
fn are_signups_enabled() -> bool {
CANISTER_DATA.with(|canister_data_ref_cell| {
let canister_data = canister_data_ref_cell.borrow();
are_signups_enabled_impl(&canister_data)
})
}

fn are_signups_enabled_impl(canister_data: &CanisterData) -> bool {
canister_data.configuration.signups_open_on_this_subnet
}

#[cfg(test)]
mod test {
use std::collections::HashMap;

use crate::data_model::configuration::Configuration;

use super::*;

#[test]
fn test_are_signups_enabled_impl() {
let mut canister_data = CanisterData {
configuration: Configuration {
known_principal_ids: HashMap::default(),
signups_open_on_this_subnet: true,
url_to_send_canister_metrics_to: String::from("http://example.com")
},
..Default::default()
};

assert!(are_signups_enabled_impl(&canister_data));

canister_data.configuration.signups_open_on_this_subnet = false;
assert!(!are_signups_enabled_impl(&canister_data));
}
}
2 changes: 2 additions & 0 deletions src/canister/user_index/src/api/user_signup/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod are_signups_enabled;
pub mod toggle_signups_enabled;
Loading

0 comments on commit 8224058

Please sign in to comment.