#[cfg(test)]
use crate::storage::stable::state::subnet::ControlPlaneSubnetStateData;
use crate::{
dto::{state::SubnetStateResponse, template::WasmStorePublicationStateResponse},
ids::{WasmStoreBinding, WasmStoreGcMode},
ops::storage::state::mapper::SubnetStateMapper,
storage::stable::state::subnet::{
SubnetState, WasmStoreInventoryConflict, WasmStoreUpsertOutcome,
},
view::state::{PublicationStoreStateView, WasmStoreView},
};
use canic_core::{
cdk::types::Principal,
control_plane_support::error::{InternalError, InternalErrorOrigin},
};
pub struct SubnetStateOps;
impl SubnetStateOps {
#[must_use]
pub fn snapshot_response() -> SubnetStateResponse {
SubnetStateMapper::data_to_response(SubnetState::export())
}
#[must_use]
pub fn publication_store_binding() -> Option<WasmStoreBinding> {
SubnetState::publication_store_binding()
}
#[must_use]
pub fn publication_store_state() -> PublicationStoreStateView {
SubnetStateMapper::publication_store_record_to_view(SubnetState::publication_store_state())
}
#[must_use]
pub fn wasm_stores() -> Vec<WasmStoreView> {
SubnetState::wasm_stores()
.into_iter()
.map(SubnetStateMapper::wasm_store_record_to_view)
.collect()
}
#[must_use]
pub fn wasm_store_pid(binding: &WasmStoreBinding) -> Option<Principal> {
SubnetState::wasm_store_pid(binding)
}
#[must_use]
pub fn wasm_store_binding_for_pid(pid: Principal) -> Option<WasmStoreBinding> {
SubnetState::wasm_store_binding_for_pid(pid)
}
pub fn upsert_wasm_store(
binding: WasmStoreBinding,
pid: Principal,
created_at: u64,
) -> Result<(), InternalError> {
match SubnetState::upsert_wasm_store(binding, pid, created_at) {
WasmStoreUpsertOutcome::Inserted | WasmStoreUpsertOutcome::Existing => Ok(()),
WasmStoreUpsertOutcome::Conflict(conflict) => {
Err(Self::wasm_store_inventory_conflict_error(conflict))
}
}
}
fn wasm_store_inventory_conflict_error(conflict: WasmStoreInventoryConflict) -> InternalError {
InternalError::workflow(
InternalErrorOrigin::Workflow,
format!(
"wasm store inventory conflict: existing binding '{}' / pid {}; requested binding '{}' / pid {}",
conflict.existing_binding,
conflict.existing_pid,
conflict.requested_binding,
conflict.requested_pid,
),
)
}
#[must_use]
pub fn remove_wasm_store(binding: &WasmStoreBinding) -> bool {
SubnetState::remove_wasm_store(binding).is_some()
}
#[must_use]
pub fn transition_wasm_store_gc(
binding: &WasmStoreBinding,
next: WasmStoreGcMode,
changed_at: u64,
) -> bool {
SubnetState::transition_wasm_store_gc(binding, next, changed_at)
}
#[must_use]
pub fn publication_store_state_response() -> WasmStorePublicationStateResponse {
SubnetStateMapper::publication_store_record_to_response(
SubnetState::publication_store_state(),
)
}
#[must_use]
pub fn activate_publication_store_binding(binding: WasmStoreBinding, changed_at: u64) -> bool {
SubnetState::activate_publication_store_binding(binding, changed_at)
}
#[must_use]
pub fn clear_publication_store_binding(changed_at: u64) -> bool {
SubnetState::clear_publication_store_binding(changed_at)
}
#[must_use]
pub fn retire_detached_publication_store_binding(changed_at: u64) -> Option<WasmStoreBinding> {
SubnetState::retire_detached_publication_store_binding(changed_at)
}
#[must_use]
pub fn finalize_retired_publication_store_binding(changed_at: u64) -> Option<WasmStoreBinding> {
SubnetState::finalize_retired_publication_store_binding(changed_at)
}
#[cfg(test)]
pub fn import(data: ControlPlaneSubnetStateData) {
SubnetState::import(data);
}
}