canic-core 0.111.0

Canic — a canister orchestration and management toolkit for the Internet Computer
Documentation
use crate::{
    cdk::{
        candid::Principal,
        structures::{
            DefaultMemoryImpl, btreemap::BTreeMap as StableBtreeMap, memory::RuntimeMemory,
        },
        types::BoundedString64,
    },
    impl_storable_bounded,
};
use canic_contracts::ids::CanisterRole;
use serde::{Deserialize, Serialize};
use std::cell::RefCell;

std::thread_local! {
    static SCALING_REGISTRY: RefCell<
        StableBtreeMap<Principal, WorkerEntryRecord, RuntimeMemory<DefaultMemoryImpl>>
    > = RefCell::new(
        StableBtreeMap::init(crate::ic_memory_key!(authority = CANIC_CORE_MEMORY_AUTHORITY, key = "canic.core.placement.scaling_registry.v1")),
    );
}

///
/// ScalingRegistryEntryRecord
///
/// One logical scaling-registry snapshot row.
///

#[derive(Clone, Debug)]
pub struct ScalingRegistryEntryRecord {
    pub pid: Principal,
    pub entry: WorkerEntryRecord,
}

impl ScalingRegistryEntryRecord {
    pub const STATE_CONTRACT_NAME: &'static str = "ScalingRegistryEntryRecord";
}

///
/// ScalingRegistryData
///
/// Canonical scaling-registry export snapshot.
///

#[derive(Clone, Debug)]
pub struct ScalingRegistryData {
    pub entries: Vec<ScalingRegistryEntryRecord>,
}

impl ScalingRegistryData {
    pub const STATE_CONTRACT_NAME: &'static str = "ScalingRegistryData";
}

///
/// ScalingRegistry
/// Registry of active scaling workers
///

pub struct ScalingRegistry;

impl ScalingRegistry {
    /// Insert or update a worker entry
    pub(crate) fn upsert(pid: Principal, entry: WorkerEntryRecord) {
        SCALING_REGISTRY.with_borrow_mut(|map| {
            map.insert(pid, entry);
        });
    }

    /// Export full registry
    #[must_use]
    pub(crate) fn export() -> ScalingRegistryData {
        ScalingRegistryData {
            entries: SCALING_REGISTRY.with_borrow(|map| {
                map.iter()
                    .map(|entry| ScalingRegistryEntryRecord {
                        pid: *entry.key(),
                        entry: entry.value(),
                    })
                    .collect()
            }),
        }
    }
}

///
/// WorkerEntryRecord
///

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct WorkerEntryRecord {
    pub pool: BoundedString64,       // which scale pool this belongs to
    pub canister_role: CanisterRole, // canister role
    pub allocation_operation_id: [u8; 32],
    pub created_at_secs: u64, // timestamp
}

impl WorkerEntryRecord {
    pub const STORABLE_MAX_SIZE: u32 = 256;
}

impl_storable_bounded!(
    WorkerEntryRecord,
    WorkerEntryRecord::STORABLE_MAX_SIZE,
    false
);