Skip to content

Commit

Permalink
Handle installing large wasms onto new subnets
Browse files Browse the repository at this point in the history
  • Loading branch information
hpeebles committed Dec 18, 2024
1 parent 78085b3 commit f8b6018
Show file tree
Hide file tree
Showing 16 changed files with 74 additions and 54 deletions.
1 change: 0 additions & 1 deletion backend/canisters/community/api/src/lifecycle/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ pub struct Args {
pub primary_language: String,
pub created_by_principal: Principal,
pub created_by_user_id: UserId,
#[serde(default)]
pub created_by_user_type: UserType,
pub mark_active_duration: Milliseconds,
pub user_index_canister_id: CanisterId,
Expand Down
1 change: 0 additions & 1 deletion backend/canisters/group/api/src/lifecycle/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ pub struct Args {
pub permissions_v2: Option<GroupPermissions>,
pub created_by_principal: Principal,
pub created_by_user_id: UserId,
#[serde(default)]
pub created_by_user_type: UserType,
pub events_ttl: Option<Milliseconds>,
pub mark_active_duration: Milliseconds,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use crate::guards::caller_is_registry_canister;
use crate::updates::upgrade_community_canister_wasm::upgrade_community_wasm_in_local_group_index;
use crate::updates::upgrade_group_canister_wasm::upgrade_group_wasm_in_local_group_index;
use crate::{mutate_state, read_state, RuntimeState};
use canister_api_macros::update;
use canister_tracing_macros::trace;
use group_index_canister::add_local_group_index_canister::{Response::*, *};
use group_index_canister::ChildCanisterType;
use tracing::info;
use types::{BuildVersion, CanisterId, CanisterWasm};
use types::{BuildVersion, CanisterId, CanisterWasm, Hash};
use utils::canister::{install_basic, set_controllers};

#[update(guard = "caller_is_registry_canister", msgpack = true)]
Expand All @@ -19,6 +21,24 @@ async fn add_local_group_index_canister(args: Args) -> Response {
InternalError(format!("Failed to set controller: {error:?}"))
} else if let Err(error) = install_basic(args.canister_id, result.canister_wasm, result.init_args).await {
InternalError(format!("Failed to install canister: {error:?}"))
} else if let Err(error) = upgrade_group_wasm_in_local_group_index(
args.canister_id,
&result.group_canister_wasm,
result.group_canister_wasm_hash,
None,
)
.await
{
InternalError(format!("Failed to install group canister wasm: {error:?}"))
} else if let Err(error) = upgrade_community_wasm_in_local_group_index(
args.canister_id,
&result.community_canister_wasm,
result.community_canister_wasm_hash,
None,
)
.await
{
InternalError(format!("Failed to install community canister wasm: {error:?}"))
} else {
let response = mutate_state(|state| commit(args.canister_id, wasm_version, state));
info!(canister_id = %args.canister_id, "local group index canister added");
Expand All @@ -32,6 +52,10 @@ async fn add_local_group_index_canister(args: Args) -> Response {
struct PrepareResult {
this_canister_id: CanisterId,
canister_wasm: CanisterWasm,
group_canister_wasm: CanisterWasm,
group_canister_wasm_hash: Hash,
community_canister_wasm: CanisterWasm,
community_canister_wasm_hash: Hash,
init_args: local_group_index_canister::init::Args,
}

Expand All @@ -45,12 +69,17 @@ fn prepare(args: &Args, state: &RuntimeState) -> Result<PrepareResult, Response>
.clone();
let wasm_version = canister_wasm.version;

let group_canister_wasm = state.data.child_canister_wasms.get(ChildCanisterType::Group);
let community_canister_wasm = state.data.child_canister_wasms.get(ChildCanisterType::Community);

Ok(PrepareResult {
this_canister_id: state.env.canister_id(),
canister_wasm,
group_canister_wasm: group_canister_wasm.wasm.clone(),
group_canister_wasm_hash: group_canister_wasm.wasm_hash,
community_canister_wasm: community_canister_wasm.wasm.clone(),
community_canister_wasm_hash: community_canister_wasm.wasm_hash,
init_args: local_group_index_canister::init::Args {
group_canister_wasm: state.data.child_canister_wasms.get(ChildCanisterType::Group).wasm.clone(),
community_canister_wasm: state.data.child_canister_wasms.get(ChildCanisterType::Community).wasm.clone(),
wasm_version,
user_index_canister_id: state.data.user_index_canister_id,
local_user_index_canister_id: args.local_user_index_canister_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ async fn upgrade_community_canister_wasm(args: Args) -> Response {

let futures: Vec<_> = local_group_index_canisters
.into_iter()
.map(|(canister_id, filter)| process_local_group_index(canister_id, &wasm, wasm_hash, Some(filter)))
.map(|(canister_id, filter)| upgrade_community_wasm_in_local_group_index(canister_id, &wasm, wasm_hash, Some(filter)))
.collect();

if let Err(error) = futures::future::try_join_all(futures).await {
Expand Down Expand Up @@ -71,7 +71,7 @@ fn prepare(args: Args, state: &RuntimeState) -> Result<PrepareResult, Response>
})
}

async fn process_local_group_index(
pub(crate) async fn upgrade_community_wasm_in_local_group_index(
canister_id: CanisterId,
canister_wasm: &CanisterWasm,
wasm_hash: Hash,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ async fn upgrade_group_canister_wasm(args: Args) -> Response {

let futures: Vec<_> = local_group_index_canisters
.into_iter()
.map(|(canister_id, filter)| process_local_group_index(canister_id, &wasm, wasm_hash, Some(filter)))
.map(|(canister_id, filter)| upgrade_group_wasm_in_local_group_index(canister_id, &wasm, wasm_hash, Some(filter)))
.collect();

if let Err(error) = futures::future::try_join_all(futures).await {
Expand Down Expand Up @@ -71,7 +71,7 @@ fn prepare(args: Args, state: &RuntimeState) -> Result<PrepareResult, Response>
})
}

async fn process_local_group_index(
pub(crate) async fn upgrade_group_wasm_in_local_group_index(
canister_id: CanisterId,
canister_wasm: &CanisterWasm,
wasm_hash: Hash,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
use candid::{CandidType, Principal};
use serde::{Deserialize, Serialize};
use types::{BuildVersion, CanisterId, CanisterWasm, UserId};
use types::{BuildVersion, CanisterId, UserId};

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub struct Args {
// The wasm module for creating group canisters
pub group_canister_wasm: CanisterWasm,

// The wasm module for creating community canisters
pub community_canister_wasm: CanisterWasm,

// The wasm version running on this canister
pub wasm_version: BuildVersion,

pub user_index_canister_id: CanisterId,
pub local_user_index_canister_id: CanisterId,
pub group_index_canister_id: CanisterId,
Expand Down
11 changes: 2 additions & 9 deletions backend/canisters/local_group_index/impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ use serde::{Deserialize, Serialize};
use std::cell::RefCell;
use std::collections::{BTreeMap, VecDeque};
use std::time::Duration;
use types::{
BuildVersion, CanisterId, CanisterWasm, ChildCanisterWasms, Cycles, Milliseconds, TimestampMillis, Timestamped, UserId,
};
use types::{BuildVersion, CanisterId, ChildCanisterWasms, Cycles, Milliseconds, TimestampMillis, Timestamped, UserId};
use utils::canister;
use utils::canister::{CanistersRequiringUpgrade, FailedUpgradeCount};
use utils::env::Environment;
Expand Down Expand Up @@ -164,8 +162,6 @@ struct Data {
impl Data {
#[allow(clippy::too_many_arguments)]
pub fn new(
group_canister_wasm: CanisterWasm,
community_canister_wasm: CanisterWasm,
user_index_canister_id: CanisterId,
local_user_index_canister_id: CanisterId,
group_index_canister_id: CanisterId,
Expand All @@ -183,10 +179,7 @@ impl Data {
Data {
local_groups: LocalGroupMap::default(),
local_communities: LocalCommunityMap::default(),
child_canister_wasms: ChildCanisterWasms::new(vec![
(ChildCanisterType::Group, group_canister_wasm),
(ChildCanisterType::Community, community_canister_wasm),
]),
child_canister_wasms: ChildCanisterWasms::default(),
user_index_canister_id,
local_user_index_canister_id,
group_index_canister_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ fn init(args: Args) {
let canister_pool_target_size = if args.test_mode { 3_u16 } else { CANISTER_POOL_TARGET_SIZE };

let data = Data::new(
args.group_canister_wasm,
args.community_canister_wasm,
args.user_index_canister_id,
args.local_user_index_canister_id,
args.group_index_canister_id,
Expand Down
6 changes: 1 addition & 5 deletions backend/canisters/local_user_index/api/src/lifecycle/init.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
use candid::{CandidType, Principal};
use serde::{Deserialize, Serialize};
use types::{BuildVersion, CanisterId, CanisterWasm};
use types::{BuildVersion, CanisterId};

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub struct Args {
// The wasm module for creating user canisters
pub user_canister_wasm: CanisterWasm,

// The wasm version running on this canister
pub wasm_version: BuildVersion,

pub user_index_canister_id: CanisterId,
pub group_index_canister_id: CanisterId,
pub identity_canister_id: CanisterId,
Expand Down
9 changes: 4 additions & 5 deletions backend/canisters/local_user_index/impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ use std::collections::{BTreeMap, HashMap, VecDeque};
use std::time::Duration;
use timer_job_queues::GroupedTimerJobQueue;
use types::{
BuildVersion, CanisterId, CanisterWasm, ChannelLatestMessageIndex, ChatId, ChildCanisterWasms,
CommunityCanisterChannelSummary, CommunityCanisterCommunitySummary, CommunityId, Cycles, DiamondMembershipDetails,
MessageContent, ReferralType, TimestampMillis, Timestamped, User, UserId, VerifiedCredentialGateArgs,
BuildVersion, CanisterId, ChannelLatestMessageIndex, ChatId, ChildCanisterWasms, CommunityCanisterChannelSummary,
CommunityCanisterCommunitySummary, CommunityId, Cycles, DiamondMembershipDetails, MessageContent, ReferralType,
TimestampMillis, Timestamped, User, UserId, VerifiedCredentialGateArgs,
};
use user_canister::LocalUserIndexEvent as UserEvent;
use user_index_canister::LocalUserIndexEvent as UserIndexEvent;
Expand Down Expand Up @@ -338,7 +338,6 @@ pub struct UserToDelete {
impl Data {
#[allow(clippy::too_many_arguments)]
pub fn new(
user_canister_wasm: CanisterWasm,
user_index_canister_id: CanisterId,
group_index_canister_id: CanisterId,
identity_canister_id: CanisterId,
Expand All @@ -358,7 +357,7 @@ impl Data {
Data {
local_users: LocalUserMap::default(),
global_users: GlobalUserMap::default(),
child_canister_wasms: ChildCanisterWasms::new(vec![(ChildCanisterType::User, user_canister_wasm)]),
child_canister_wasms: ChildCanisterWasms::default(),
user_index_canister_id,
group_index_canister_id,
identity_canister_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ fn init(args: Args) {
let canister_pool_target_size = if args.test_mode { 3_u16 } else { CANISTER_POOL_TARGET_SIZE };

let data = Data::new(
args.user_canister_wasm,
args.user_index_canister_id,
args.group_index_canister_id,
args.identity_canister_id,
Expand Down
14 changes: 7 additions & 7 deletions backend/canisters/registry/impl/src/timer_job_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ const MEMO_CREATE_CANISTER: Memo = Memo(0x41455243); // == 'CREA'

#[derive(Serialize, Deserialize, Clone)]
pub enum TimerJob {
ExpandOntoNewSubnet(ExpandOntoNewSubnetJob),
ExpandOntoSubnet(ExpandOntoSubnetJob),
}

#[derive(Serialize, Deserialize, Clone)]
pub struct ExpandOntoNewSubnetJob {
pub struct ExpandOntoSubnetJob {
pub subnet_id: Principal,
pub this_canister_id: CanisterId,
pub user_index: CanisterId,
Expand All @@ -34,12 +34,12 @@ pub struct ExpandOntoNewSubnetJob {
impl Job for TimerJob {
fn execute(self) {
match self {
TimerJob::ExpandOntoNewSubnet(job) => job.execute(),
TimerJob::ExpandOntoSubnet(job) => job.execute(),
}
}
}

impl Job for ExpandOntoNewSubnetJob {
impl Job for ExpandOntoSubnetJob {
fn execute(self) {
if let Some((next_step, now)) =
read_state(|state| state.data.subnets.in_progress().map(|s| (s.next_step(), state.env.now())))
Expand All @@ -49,12 +49,12 @@ impl Job for ExpandOntoNewSubnetJob {
}
}

impl ExpandOntoNewSubnetJob {
impl ExpandOntoSubnetJob {
async fn process_step(self, next_step: ExpandOntoSubnetStep, now: TimestampMillis) {
let delay = match self.process_step_inner(next_step, now).await {
Ok(Some(false)) => 0,
Err(error) => {
ic_cdk::println!("ExpandOntoNewSubnet processing failed: {:?}", error);
ic_cdk::println!("ExpandOntoSubnet processing failed: {:?}", error);
MINUTE_IN_MS
}
Ok(Some(true)) | Ok(None) => return,
Expand All @@ -65,7 +65,7 @@ impl ExpandOntoNewSubnetJob {
state
.data
.timer_jobs
.enqueue_job(TimerJob::ExpandOntoNewSubnet(self), now + delay, now);
.enqueue_job(TimerJob::ExpandOntoSubnet(self), now + delay, now);
})
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::guards::caller_is_governance_principal;
use crate::timer_job_types::ExpandOntoNewSubnetJob;
use crate::timer_job_types::ExpandOntoSubnetJob;
use crate::{mutate_state, RuntimeState};
use canister_api_macros::proposal;
use canister_timer_jobs::Job;
Expand All @@ -18,15 +18,15 @@ fn expand_onto_subnet(args: Args) -> Response {
}
}

fn expand_onto_subnet_impl(args: Args, state: &mut RuntimeState) -> Result<ExpandOntoNewSubnetJob, Response> {
fn expand_onto_subnet_impl(args: Args, state: &mut RuntimeState) -> Result<ExpandOntoSubnetJob, Response> {
if state.data.subnets.subnets().iter().any(|s| s.subnet_id == args.subnet_id) {
Err(AlreadyOnSubnet)
} else if state.data.subnets.in_progress().is_some() {
Err(AlreadyInProgress)
} else {
state.data.subnets.start_new(args.subnet_id, state.env.now());

Ok(ExpandOntoNewSubnetJob {
Ok(ExpandOntoSubnetJob {
subnet_id: args.subnet_id,
this_canister_id: state.env.canister_id(),
user_index: state.data.user_index_canister_id,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::guards::caller_is_registry_canister;
use crate::updates::upgrade_user_canister_wasm::upgrade_user_wasm_in_local_user_index;
use crate::{mutate_state, read_state, RuntimeState};
use canister_api_macros::update;
use canister_tracing_macros::trace;
use local_user_index_canister::{UserIndexEvent, UserRegistered};
use tracing::info;
use types::{BuildVersion, CanisterId, CanisterWasm};
use types::{BuildVersion, CanisterId, CanisterWasm, Hash};
use user_index_canister::add_local_user_index_canister::{Response::*, *};
use user_index_canister::ChildCanisterType;
use utils::canister::{install_basic, set_controllers};
Expand All @@ -20,6 +21,15 @@ async fn add_local_user_index_canister(args: Args) -> Response {
InternalError(format!("Failed to set controller: {error:?}"))
} else if let Err(error) = install_basic(args.canister_id, result.canister_wasm, result.init_args).await {
InternalError(format!("Failed to install canister: {error:?}"))
} else if let Err(error) = upgrade_user_wasm_in_local_user_index(
args.canister_id,
&result.user_canister_wasm,
result.user_canister_wasm_hash,
None,
)
.await
{
InternalError(format!("Failed to install user canister wasm: {error:?}"))
} else {
let response = mutate_state(|state| commit(args.canister_id, wasm_version, state));
info!(canister_id = %args.canister_id, "local user index canister added");
Expand All @@ -33,6 +43,8 @@ async fn add_local_user_index_canister(args: Args) -> Response {
struct PrepareResult {
this_canister_id: CanisterId,
canister_wasm: CanisterWasm,
user_canister_wasm: CanisterWasm,
user_canister_wasm_hash: Hash,
init_args: local_user_index_canister::init::Args,
}

Expand All @@ -46,11 +58,14 @@ fn prepare(args: &Args, state: &RuntimeState) -> Result<PrepareResult, Response>
.clone();
let wasm_version = canister_wasm.version;

let user_canister_wasm = state.data.child_canister_wasms.get(ChildCanisterType::User);

Ok(PrepareResult {
this_canister_id: state.env.canister_id(),
canister_wasm,
user_canister_wasm: user_canister_wasm.wasm.clone(),
user_canister_wasm_hash: user_canister_wasm.wasm_hash,
init_args: local_user_index_canister::init::Args {
user_canister_wasm: state.data.child_canister_wasms.get(ChildCanisterType::User).wasm.clone(),
wasm_version,
user_index_canister_id: state.env.canister_id(),
group_index_canister_id: state.data.group_index_canister_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ async fn upgrade_user_canister_wasm(args: Args) -> Response {

let futures: Vec<_> = local_user_index_canisters
.into_iter()
.map(|(canister_id, filter)| process_local_user_index(canister_id, &wasm, wasm_hash, Some(filter)))
.map(|(canister_id, filter)| upgrade_user_wasm_in_local_user_index(canister_id, &wasm, wasm_hash, Some(filter)))
.collect();

if let Err(error) = futures::future::try_join_all(futures).await {
Expand Down Expand Up @@ -71,7 +71,7 @@ fn prepare(args: Args, state: &RuntimeState) -> Result<PrepareResult, Response>
})
}

async fn process_local_user_index(
pub(crate) async fn upgrade_user_wasm_in_local_user_index(
canister_id: CanisterId,
canister_wasm: &CanisterWasm,
wasm_hash: Hash,
Expand Down
2 changes: 1 addition & 1 deletion backend/libraries/types/src/canister_wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ pub struct ChunkedCanisterWasm {
impl From<CanisterWasm> for ChunkedCanisterWasm {
fn from(value: CanisterWasm) -> Self {
ChunkedCanisterWasm {
wasm_hash: value.module.hash(),
wasm: value,
chunks: Vec::new(),
wasm_hash: [0; 32],
}
}
}
Expand Down

0 comments on commit f8b6018

Please sign in to comment.