Skip to content

Commit

Permalink
feat: upgrade user_index with generic proposal to reset canisters and…
Browse files Browse the repository at this point in the history
… use semver version(#224)

* add generic proposal to reset individual canisters

* add semver version to canisters

* recharge below threshold cnisters with 1 trillion cycles; enable test for it

* update github workflow

* update scripts for semver version string
  • Loading branch information
ravi-sawlani-yral authored Jan 8, 2024
1 parent d9e9ed4 commit 8d0b2ed
Show file tree
Hide file tree
Showing 28 changed files with 164 additions and 18 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/create_release_on_tag_push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ jobs:
--url 'https://hotornot.wtf' \
--target-canister-id $CANISTER_ID \
--wasm-path .dfx/ic/canisters/${CANISTER_NAME}/${CANISTER_NAME}.wasm.gz \
--canister-upgrade-arg '(record {})' \
--canister-upgrade-arg "(record {version=\"${{ github.ref_name }}\"})" \
$NEURON_ID > "proposals/${CANISTER_NAME}/upgrade.json"
./quill send proposals/${CANISTER_NAME}/upgrade.json --yes
- name: Submit upgrade proposal for post_cache canister
Expand Down
1 change: 1 addition & 0 deletions scripts/canisters/local_deploy/install_all_canisters.sh
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,5 @@ dfx canister install user_index --argument "(record {
vec { variant { CanisterAdmin }; variant { CanisterController }; }
};
};
version= \"v1.0.0\"
})"
4 changes: 3 additions & 1 deletion scripts/canisters/local_deploy/upgrade_all_canisters.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ fi
dfx canister install configuration --mode upgrade --argument "(record {})"
dfx canister install data_backup --mode upgrade --argument "(record {})"
dfx canister install post_cache --mode upgrade --argument "(record {})"
dfx canister install user_index --mode upgrade --argument "(record {})"
dfx canister install user_index --mode upgrade --argument "(record {
version= \"v1.1.0\"
})"
1 change: 1 addition & 0 deletions src/canister/configuration/can.did
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type KnownPrincipalType = variant {
CanisterIdDataBackup;
CanisterIdPostCache;
CanisterIdSNSController;
CanisterIdSnsGovernance;
UserIdGlobalSuperAdmin;
};
type Result = variant { Ok; Err : text };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::str::FromStr;

use candid::Principal;
use ic_cdk::storage;
use shared_utils::{common::types::known_principal::KnownPrincipalType, constant::GOVERNANCE_CANISTER_ID};

use crate::CANISTER_DATA;

Expand All @@ -8,6 +12,7 @@ fn post_upgrade() {
Ok((canister_data,)) => {
CANISTER_DATA.with(|canister_data_ref_cell| {
*canister_data_ref_cell.borrow_mut() = canister_data;
canister_data_ref_cell.borrow_mut().known_principal_ids.insert(KnownPrincipalType::CanisterIdSnsGovernance, Principal::from_str(GOVERNANCE_CANISTER_ID).unwrap());
});
}
Err(_) => {
Expand Down
1 change: 1 addition & 0 deletions src/canister/data_backup/can.did
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type KnownPrincipalType = variant {
CanisterIdDataBackup;
CanisterIdPostCache;
CanisterIdSNSController;
CanisterIdSnsGovernance;
UserIdGlobalSuperAdmin;
};
type MintEvent = variant {
Expand Down
3 changes: 3 additions & 0 deletions src/canister/individual_user_template/can.did
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ type HotOrNotOutcomePayoutEvent = variant {
};
type IndividualUserTemplateInitArgs = record {
known_principal_ids : opt vec record { KnownPrincipalType; principal };
version : text;
url_to_send_canister_metrics_to : opt text;
profile_owner : opt principal;
upgrade_version_number : opt nat64;
Expand All @@ -102,6 +103,7 @@ type KnownPrincipalType = variant {
CanisterIdDataBackup;
CanisterIdPostCache;
CanisterIdSNSController;
CanisterIdSnsGovernance;
UserIdGlobalSuperAdmin;
};
type MintEvent = variant {
Expand Down Expand Up @@ -304,6 +306,7 @@ service : (IndividualUserTemplateInitArgs) -> {
nat64,
) -> (Result_5) query;
get_utility_token_balance : () -> (nat64) query;
get_version : () -> (text) query;
get_version_number : () -> (nat64) query;
get_well_known_principal_value : (KnownPrincipalType) -> (
opt principal,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ mod test {
url_to_send_canister_metrics_to: Some(
"http://metrics-url.com/receive-metrics".to_string(),
),
version: String::from("v1.0.0")
};
let mut data = CanisterData::default();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::time::Duration;
use std::{time::Duration, borrow::BorrowMut};
use ciborium::de;
use ic_stable_structures::Memory;

Expand Down Expand Up @@ -57,6 +57,8 @@ fn save_upgrade_args_to_memory() {
canister_data_ref_cell.version_details.version_number = upgrade_version_number;
}

canister_data_ref_cell.borrow_mut().version_details.version = upgrade_args.version;

if let Some(url_to_send_canister_metrics_to) = upgrade_args.url_to_send_canister_metrics_to
{
canister_data_ref_cell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,13 @@ pub fn get_version_number() -> u64 {
CANISTER_DATA.with(|canister_data_ref| {
canister_data_ref.borrow().version_details.version_number
})
}
}

#[candid::candid_method(query)]
#[ic_cdk::query]
pub fn get_version() -> String {
CANISTER_DATA.with(|canister_data_ref| {
canister_data_ref.borrow().version_details.version.clone()
})
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ use serde::Serialize;
#[derive(Default, CandidType, Deserialize, Serialize)]
pub struct VersionDetails {
pub version_number: u64,
#[serde(default)]
pub version: String
}
1 change: 1 addition & 0 deletions src/canister/post_cache/can.did
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type KnownPrincipalType = variant {
CanisterIdDataBackup;
CanisterIdPostCache;
CanisterIdSNSController;
CanisterIdSnsGovernance;
UserIdGlobalSuperAdmin;
};
type PostCacheInitArgs = record {
Expand Down
13 changes: 11 additions & 2 deletions src/canister/user_index/can.did
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type KnownPrincipalType = variant {
CanisterIdDataBackup;
CanisterIdPostCache;
CanisterIdSNSController;
CanisterIdSnsGovernance;
UserIdGlobalSuperAdmin;
};
type RejectionCode = variant {
Expand All @@ -38,7 +39,8 @@ type Result = variant {
Ok : record { CanisterStatusResponse };
Err : record { RejectionCode; text };
};
type Result_1 = variant { Ok; Err : SetUniqueUsernameError };
type Result_1 = variant { Ok : text; Err : text };
type Result_2 = variant { Ok; Err : SetUniqueUsernameError };
type SetUniqueUsernameError = variant {
UsernameAlreadyTaken;
SendingCanisterDoesNotMatchUserCanisterId;
Expand All @@ -50,6 +52,7 @@ type SystemTime = record {
};
type UpgradeStatus = record {
version_number : nat64;
version : text;
last_run_on : SystemTime;
failed_canister_ids : vec record { principal; principal; text };
successful_upgrade_count : nat32;
Expand All @@ -62,12 +65,14 @@ type UserAccessRole = variant {
};
type UserIndexInitArgs = record {
known_principal_ids : opt vec record { KnownPrincipalType; principal };
version : text;
access_control_map : opt vec record { principal; vec UserAccessRole };
};
service : (UserIndexInitArgs) -> {
backup_all_individual_user_canisters : () -> ();
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;
get_requester_principals_canister_id_create_if_not_exists_and_optionally_allow_referrer : (
opt principal,
) -> (principal);
Expand All @@ -86,16 +91,20 @@ service : (UserIndexInitArgs) -> {
principal,
text,
) -> ();
reset_user_individual_canisters : (vec principal) -> (Result_1);
set_permission_to_upgrade_individual_canisters : (bool) -> (text);
start_upgrades_for_individual_canisters : () -> (text);
update_index_with_unique_user_name_corresponding_to_user_principal_id : (
text,
principal,
) -> (Result_1);
) -> (Result_2);
upgrade_specific_individual_user_canister_with_latest_wasm : (
principal,
principal,
opt CanisterInstallMode,
bool,
) -> (text);
validate_reset_user_individual_canisters : (vec principal) -> (
Result_1,
) query;
}
3 changes: 3 additions & 0 deletions src/canister/user_index/src/api/canister_lifecycle/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ fn init_impl(init_args: UserIndexInitArgs, data: &mut CanisterData) {
data.known_principal_ids
.insert(*principal_belongs_to, *principal_id);
});
data.allow_upgrades_for_individual_canisters = true;
}

#[cfg(test)]
Expand Down Expand Up @@ -72,6 +73,8 @@ mod test {
let init_args = UserIndexInitArgs {
known_principal_ids: Some(known_principal_ids),
access_control_map: Some(access_control_map),
version: String::from("v1.0.0")

};
let mut data = CanisterData::default();

Expand Down
21 changes: 19 additions & 2 deletions src/canister/user_index/src/api/canister_lifecycle/post_upgrade.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::time::Duration;

use shared_utils::common::utils::stable_memory_serializer_deserializer;
use shared_utils::{common::utils::{stable_memory_serializer_deserializer, system_time}, canister_specific::user_index::types::args::UserIndexInitArgs};

use crate::{
api::{
upgrade_individual_user_template::update_user_index_upgrade_user_canisters_with_latest_wasm,
well_known_principal::update_locally_stored_well_known_principals,
},
data_model::{configuration::Configuration, CanisterData},
data_model::{configuration::Configuration, CanisterData, canister_upgrade::UpgradeStatus},
CANISTER_DATA,
};

Expand All @@ -16,6 +16,7 @@ use super::pre_upgrade::BUFFER_SIZE_BYTES;
#[ic_cdk::post_upgrade]
fn post_upgrade() {
restore_data_from_stable_memory();
update_version_from_args();
refetch_well_known_principals();
upgrade_all_indexed_user_canisters();

Expand All @@ -33,6 +34,22 @@ fn post_upgrade() {
});
}

fn update_version_from_args() {
let (upgrade_args, ) = ic_cdk::api::call::arg_data::<(UserIndexInitArgs,)>();
CANISTER_DATA.with(|canister_data_ref| {
let last_upgrade_status = canister_data_ref.borrow().last_run_upgrade_status.clone();
let upgrade_status = UpgradeStatus {
last_run_on: system_time::get_current_system_time_from_ic(),
failed_canister_ids: vec![],
version_number: last_upgrade_status.version_number,
successful_upgrade_count: 0,
version: upgrade_args.version
};
canister_data_ref.borrow_mut().last_run_upgrade_status = upgrade_status;
})

}

fn restore_data_from_stable_memory() {
match stable_memory_serializer_deserializer::deserialize_from_stable_memory::<CanisterData>(
BUFFER_SIZE_BYTES,
Expand Down
72 changes: 69 additions & 3 deletions src/canister/user_index/src/api/canister_management/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use ic_cdk::api::{management_canister::{main::{canister_status, CanisterStatusResponse}, provisional::CanisterIdRecord}, call::CallResult};

use ic_cdk::{api::{management_canister::{main::{canister_status, CanisterStatusResponse, CanisterInstallMode}, provisional::CanisterIdRecord}, call::CallResult}, caller};
use candid::Principal;
use shared_utils::common::types::known_principal::KnownPrincipalType;
use shared_utils::{common::{types::known_principal::KnownPrincipalType, utils::task::run_task_concurrently}, canister_specific::individual_user_template::types::arg::IndividualUserTemplateInitArgs};

use crate::CANISTER_DATA;
use crate::{CANISTER_DATA, util::canister_management};

use super::upgrade_individual_user_template::update_user_index_upgrade_user_canisters_with_latest_wasm;

Expand Down Expand Up @@ -52,4 +53,69 @@ pub async fn start_upgrades_for_individual_canisters() -> String {
});
ic_cdk::spawn(update_user_index_upgrade_user_canisters_with_latest_wasm::upgrade_user_canisters_with_latest_wasm());
"Success".to_string()
}

#[ic_cdk::query]
#[candid::candid_method(query)]
pub fn get_list_of_available_canisters() -> Vec<Principal> {
CANISTER_DATA.with(|canister_data_ref|{
canister_data_ref.borrow().available_canisters.clone().into_iter().collect()
})
}

#[ic_cdk::query]
#[candid::candid_method(query)]
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()
}).ok_or("Governance Canister Id not found")?;

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

Ok("Success".to_string())
}


#[ic_cdk::update]
#[candid::candid_method(update)]
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()
}).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 {
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()})),
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())
});

let result_callback = |reinstall_res: CallResult<Principal>| {

match reinstall_res {
Ok(canister_id) => {
CANISTER_DATA.with(|canister_data_ref| {
canister_data_ref.borrow_mut().available_canisters.insert(canister_id);
})
},
Err(e) => ic_cdk::println!("Failed to reinstall canister {}", e.1)
}
};


run_task_concurrently(canister_reinstall_futures, 10, result_callback, || false).await;

Ok(format!("Sucess {}", canisters[0].to_string()))
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub async fn upgrade_user_canisters_with_latest_wasm() {

let upgrade_individual_canister_futures = user_principal_id_to_canister_id_map.iter()
.map(|(user_principal_id, user_canister_id)| {
recharge_and_upgrade(*user_canister_id, *user_principal_id, saved_upgrade_status.version_number, configuration.clone())
recharge_and_upgrade(*user_canister_id, *user_principal_id, saved_upgrade_status.version_number, configuration.clone(), saved_upgrade_status.version.clone())
});

let result_callback = |upgrade_result: Result<Principal, (Principal, String)>| {
Expand Down Expand Up @@ -89,14 +89,14 @@ 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) -> Result<Principal, (Principal, String)> {
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))?;
}

upgrade_user_canister(&user_principal_id, &user_canister_id, version_number, &configuration).await.map_err(|s| (user_principal_id, s))?;
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)
}
Expand Down Expand Up @@ -134,6 +134,7 @@ async fn upgrade_user_canister(
canister_id: &Principal,
version_number: u64,
configuration: &Configuration,
version: String
) -> Result<(), String> {
canister_management::upgrade_individual_user_canister(
*canister_id,
Expand All @@ -145,6 +146,7 @@ async fn upgrade_user_canister(
url_to_send_canister_metrics_to: Some(
configuration.url_to_send_canister_metrics_to.clone(),
),
version
},
false
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ async fn upgrade_specific_individual_user_canister_with_latest_wasm(
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
)
Expand Down
Loading

0 comments on commit 8d0b2ed

Please sign in to comment.