Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(station): store monitoring data in ExternalCanister #430

Merged
merged 9 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ const submit = async (input: CanisterMonitorModel) => {
canister_id: assertAndReturn(input.canisterId, 'canisterId'),
kind: {
Start: {
strategy: assertAndReturn(input.strategy, 'strategy'),
funding_strategy: assertAndReturn(input.strategy, 'strategy'),
cycle_obtain_strategy: [],
},
},
});
Expand Down
8 changes: 6 additions & 2 deletions apps/wallet/src/generated/station/station.did
Original file line number Diff line number Diff line change
Expand Up @@ -796,8 +796,10 @@ type MonitorExternalCanisterStrategyInput = variant {

// The input type for specifying the strategy for monitoring an external canister.
type MonitorExternalCanisterStartInput = record {
// The amount of cycles to send to the canister.
strategy : MonitorExternalCanisterStrategyInput;
// The strategy for funding the canister.
funding_strategy : MonitorExternalCanisterStrategyInput;
// The strategy for obtaining cycles for the funding operation.
cycle_obtain_strategy: opt CycleObtainStrategyInput;
};

// The operation kind for monitoring an external canister in the station.
Expand Down Expand Up @@ -2595,6 +2597,8 @@ type ExternalCanister = record {
created_at : TimestampRFC3339;
// The time at which the canister was last modified, if available.
modified_at : opt TimestampRFC3339;
// Monitoring configuration for the canister.
monitoring : opt MonitorExternalCanisterStartInput;
};

// The state of the external canister.
Expand Down
4 changes: 3 additions & 1 deletion apps/wallet/src/generated/station/station.did.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ export interface ExternalCanister {
'created_at' : TimestampRFC3339,
'request_policies' : ExternalCanisterRequestPolicies,
'state' : ExternalCanisterState,
'monitoring' : [] | [MonitorExternalCanisterStartInput],
}
export interface ExternalCanisterCallPermission {
'execution_method' : string,
Expand Down Expand Up @@ -840,7 +841,8 @@ export type MonitorExternalCanisterOperationKind = {
} |
{ 'Stop' : null };
export interface MonitorExternalCanisterStartInput {
'strategy' : MonitorExternalCanisterStrategyInput,
'cycle_obtain_strategy' : [] | [CycleObtainStrategyInput],
'funding_strategy' : MonitorExternalCanisterStrategyInput,
}
export type MonitorExternalCanisterStrategyInput = { 'Always' : bigint } |
{ 'BelowThreshold' : MonitoringExternalCanisterCyclesThresholdInput } |
Expand Down
12 changes: 7 additions & 5 deletions apps/wallet/src/generated/station/station.did.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,10 @@ export const idlFactory = ({ IDL }) => {
'module_checksum' : Sha256Hash,
'arg_checksum' : IDL.Opt(Sha256Hash),
});
const CycleObtainStrategyInput = IDL.Variant({
'Disabled' : IDL.Null,
'MintFromNativeToken' : IDL.Record({ 'account_id' : UUID }),
});
const MonitoringExternalCanisterCyclesThresholdInput = IDL.Record({
'fund_cycles' : IDL.Nat,
'min_cycles' : IDL.Nat,
Expand All @@ -328,7 +332,8 @@ export const idlFactory = ({ IDL }) => {
'BelowEstimatedRuntime' : MonitoringExternalCanisterEstimatedRuntimeInput,
});
const MonitorExternalCanisterStartInput = IDL.Record({
'strategy' : MonitorExternalCanisterStrategyInput,
'cycle_obtain_strategy' : IDL.Opt(CycleObtainStrategyInput),
'funding_strategy' : MonitorExternalCanisterStrategyInput,
});
const MonitorExternalCanisterOperationKind = IDL.Variant({
'Start' : MonitorExternalCanisterStartInput,
Expand Down Expand Up @@ -504,10 +509,6 @@ export const idlFactory = ({ IDL }) => {
'identities' : IDL.Opt(IDL.Vec(IDL.Principal)),
});
const EditUserOperation = IDL.Record({ 'input' : EditUserOperationInput });
const CycleObtainStrategyInput = IDL.Variant({
'Disabled' : IDL.Null,
'MintFromNativeToken' : IDL.Record({ 'account_id' : UUID }),
});
const ManageSystemInfoOperationInput = IDL.Record({
'name' : IDL.Opt(IDL.Text),
'cycle_obtain_strategy' : IDL.Opt(CycleObtainStrategyInput),
Expand Down Expand Up @@ -933,6 +934,7 @@ export const idlFactory = ({ IDL }) => {
'created_at' : TimestampRFC3339,
'request_policies' : ExternalCanisterRequestPolicies,
'state' : ExternalCanisterState,
'monitoring' : IDL.Opt(MonitorExternalCanisterStartInput),
});
const GetExternalCanisterResult = IDL.Variant({
'Ok' : IDL.Record({
Expand Down
8 changes: 6 additions & 2 deletions core/station/api/spec.did
Original file line number Diff line number Diff line change
Expand Up @@ -796,8 +796,10 @@ type MonitorExternalCanisterStrategyInput = variant {

// The input type for specifying the strategy for monitoring an external canister.
type MonitorExternalCanisterStartInput = record {
// The amount of cycles to send to the canister.
strategy : MonitorExternalCanisterStrategyInput;
// The strategy for funding the canister.
funding_strategy : MonitorExternalCanisterStrategyInput;
// The strategy for obtaining cycles for the funding operation.
cycle_obtain_strategy: opt CycleObtainStrategyInput;
};

// The operation kind for monitoring an external canister in the station.
Expand Down Expand Up @@ -2595,6 +2597,8 @@ type ExternalCanister = record {
created_at : TimestampRFC3339;
// The time at which the canister was last modified, if available.
modified_at : opt TimestampRFC3339;
// Monitoring configuration for the canister.
monitoring : opt MonitorExternalCanisterStartInput;
};

// The state of the external canister.
Expand Down
10 changes: 6 additions & 4 deletions core/station/api/src/external_canister.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
AllowDTO, CanisterInstallMode, ChangeMetadataDTO, MetadataDTO, PaginationInput,
RequestPolicyRuleDTO, Sha256HashDTO, SortDirection, TimestampRfc3339, UuidDTO,
AllowDTO, CanisterInstallMode, ChangeMetadataDTO, CycleObtainStrategyInput, MetadataDTO,
PaginationInput, RequestPolicyRuleDTO, Sha256HashDTO, SortDirection, TimestampRfc3339, UuidDTO,
ValidationMethodResourceTargetDTO,
};
use candid::{CandidType, Deserialize, Nat, Principal};
Expand Down Expand Up @@ -285,6 +285,7 @@ pub struct ExternalCanisterDTO {
pub request_policies: ExternalCanisterRequestPoliciesDTO,
pub created_at: TimestampRfc3339,
pub modified_at: Option<TimestampRfc3339>,
pub monitoring: Option<MonitorExternalCanisterStartInput>,
}

#[derive(CandidType, serde::Serialize, Deserialize, Debug, Clone)]
Expand Down Expand Up @@ -398,15 +399,16 @@ pub struct MonitoringExternalCanisterCyclesThresholdInput {
}

#[derive(CandidType, serde::Serialize, Deserialize, Debug, Clone)]
pub enum MonitorExternalCanisterStartStrategyDTO {
pub enum MonitorExternalCanisterStrategyDTO {
Always(u128),
BelowThreshold(MonitoringExternalCanisterCyclesThresholdInput),
BelowEstimatedRuntime(MonitoringExternalCanisterEstimatedRuntimeInput),
}

#[derive(CandidType, serde::Serialize, Deserialize, Debug, Clone)]
pub struct MonitorExternalCanisterStartInput {
pub strategy: MonitorExternalCanisterStartStrategyDTO,
pub funding_strategy: MonitorExternalCanisterStrategyDTO,
pub cycle_obtain_strategy: Option<CycleObtainStrategyInput>,
}

#[derive(CandidType, serde::Serialize, Deserialize, Debug, Clone)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ impl Execute for MonitorExternalCanisterRequestExecute<'_, '_> {
match &self.operation.kind {
MonitorExternalCanisterOperationKind::Start(input) => {
self.external_canister_service
.canister_monitor_start(self.operation.canister_id, input.strategy.clone())
.canister_monitor_start(
self.operation.canister_id,
input.funding_strategy.clone(),
)
.map_err(|e| RequestExecuteError::Failed {
reason: format!("Failed to monitor canister: {}", e),
})?;
Expand Down
60 changes: 29 additions & 31 deletions core/station/impl/src/mappers/external_canister.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
FundExternalCanisterOperationInput, FundExternalCanisterOperationKind,
FundExternalCanisterSendCyclesInput, LogVisibility, MonitorExternalCanisterOperationInput,
MonitorExternalCanisterOperationKind, MonitorExternalCanisterStartInput,
MonitorExternalCanisterStartStrategy, MonitoringExternalCanisterCyclesThresholdInput,
MonitorExternalCanisterStrategy, MonitoringExternalCanisterCyclesThresholdInput,
MonitoringExternalCanisterEstimatedRuntimeInput,
},
repositories::ExternalCanisterWhereClauseSort,
Expand Down Expand Up @@ -40,6 +40,7 @@ impl ExternalCanisterMapper {
state: ExternalCanisterState::Active,
created_at: next_time(),
modified_at: None,
monitoring: None,
}
}
}
Expand All @@ -62,6 +63,7 @@ impl ExternalCanister {
request_policies: policies.into(),
created_at: timestamp_to_rfc3339(&self.created_at),
modified_at: self.modified_at.map(|ts| timestamp_to_rfc3339(&ts)),
monitoring: self.monitoring.map(Into::into),
}
}
}
Expand Down Expand Up @@ -376,52 +378,48 @@ impl From<MonitorExternalCanisterOperationKind>
impl From<station_api::MonitorExternalCanisterStartInput> for MonitorExternalCanisterStartInput {
fn from(input: station_api::MonitorExternalCanisterStartInput) -> Self {
MonitorExternalCanisterStartInput {
strategy: input.strategy.into(),
funding_strategy: input.funding_strategy.into(),
cycle_obtain_strategy: input.cycle_obtain_strategy.map(Into::into),
}
}
}

impl From<MonitorExternalCanisterStartInput> for station_api::MonitorExternalCanisterStartInput {
fn from(input: MonitorExternalCanisterStartInput) -> Self {
station_api::MonitorExternalCanisterStartInput {
strategy: input.strategy.into(),
funding_strategy: input.funding_strategy.into(),
cycle_obtain_strategy: input.cycle_obtain_strategy.map(Into::into),
}
}
}

impl From<station_api::MonitorExternalCanisterStartStrategyDTO>
for MonitorExternalCanisterStartStrategy
{
fn from(strategy: station_api::MonitorExternalCanisterStartStrategyDTO) -> Self {
impl From<station_api::MonitorExternalCanisterStrategyDTO> for MonitorExternalCanisterStrategy {
fn from(strategy: station_api::MonitorExternalCanisterStrategyDTO) -> Self {
match strategy {
station_api::MonitorExternalCanisterStartStrategyDTO::Always(cycles) => {
MonitorExternalCanisterStartStrategy::Always(cycles)
station_api::MonitorExternalCanisterStrategyDTO::Always(cycles) => {
MonitorExternalCanisterStrategy::Always(cycles)
}
station_api::MonitorExternalCanisterStrategyDTO::BelowThreshold(threshold) => {
MonitorExternalCanisterStrategy::BelowThreshold(threshold.into())
}
station_api::MonitorExternalCanisterStartStrategyDTO::BelowThreshold(threshold) => {
MonitorExternalCanisterStartStrategy::BelowThreshold(threshold.into())
station_api::MonitorExternalCanisterStrategyDTO::BelowEstimatedRuntime(runtime) => {
MonitorExternalCanisterStrategy::BelowEstimatedRuntime(runtime.into())
}
station_api::MonitorExternalCanisterStartStrategyDTO::BelowEstimatedRuntime(
runtime,
) => MonitorExternalCanisterStartStrategy::BelowEstimatedRuntime(runtime.into()),
}
}
}

impl From<MonitorExternalCanisterStartStrategy>
for station_api::MonitorExternalCanisterStartStrategyDTO
{
fn from(strategy: MonitorExternalCanisterStartStrategy) -> Self {
impl From<MonitorExternalCanisterStrategy> for station_api::MonitorExternalCanisterStrategyDTO {
fn from(strategy: MonitorExternalCanisterStrategy) -> Self {
match strategy {
MonitorExternalCanisterStartStrategy::Always(cycles) => {
station_api::MonitorExternalCanisterStartStrategyDTO::Always(cycles)
MonitorExternalCanisterStrategy::Always(cycles) => {
station_api::MonitorExternalCanisterStrategyDTO::Always(cycles)
}
MonitorExternalCanisterStartStrategy::BelowThreshold(threshold) => {
station_api::MonitorExternalCanisterStartStrategyDTO::BelowThreshold(
threshold.into(),
)
MonitorExternalCanisterStrategy::BelowThreshold(threshold) => {
station_api::MonitorExternalCanisterStrategyDTO::BelowThreshold(threshold.into())
}
MonitorExternalCanisterStartStrategy::BelowEstimatedRuntime(runtime) => {
station_api::MonitorExternalCanisterStartStrategyDTO::BelowEstimatedRuntime(
MonitorExternalCanisterStrategy::BelowEstimatedRuntime(runtime) => {
station_api::MonitorExternalCanisterStrategyDTO::BelowEstimatedRuntime(
runtime.into(),
)
}
Expand Down Expand Up @@ -479,16 +477,16 @@ impl From<MonitoringExternalCanisterEstimatedRuntimeInput>
}
}

impl From<MonitorExternalCanisterStartStrategy> for canfund::manager::options::FundStrategy {
fn from(strategy: MonitorExternalCanisterStartStrategy) -> Self {
impl From<MonitorExternalCanisterStrategy> for canfund::manager::options::FundStrategy {
fn from(strategy: MonitorExternalCanisterStrategy) -> Self {
match strategy {
MonitorExternalCanisterStartStrategy::Always(cycles) => {
MonitorExternalCanisterStrategy::Always(cycles) => {
canfund::manager::options::FundStrategy::Always(cycles)
}
MonitorExternalCanisterStartStrategy::BelowThreshold(threshold) => {
MonitorExternalCanisterStrategy::BelowThreshold(threshold) => {
canfund::manager::options::FundStrategy::BelowThreshold(threshold.into())
}
MonitorExternalCanisterStartStrategy::BelowEstimatedRuntime(runtime) => {
MonitorExternalCanisterStrategy::BelowEstimatedRuntime(runtime) => {
canfund::manager::options::FundStrategy::BelowEstimatedRuntime(runtime.into())
}
}
Expand Down
8 changes: 7 additions & 1 deletion core/station/impl/src/models/external_canister.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use super::{
CanisterMethod, ConfigureExternalCanisterSettingsInput, CreateExternalCanisterOperationInput,
CreateExternalCanisterOperationKind, ExternalCanisterChangeCallRequestPoliciesInput,
ExternalCanisterRequestPoliciesCreateInput, ExternalCanisterRequestPoliciesUpdateInput,
Metadata, RequestPolicy, RequestPolicyRule,
Metadata, MonitorExternalCanisterStartInput, RequestPolicy, RequestPolicyRule,
};
use crate::errors::{ExternalCanisterError, ExternalCanisterValidationError};
use crate::repositories::REQUEST_POLICY_REPOSITORY;
Expand Down Expand Up @@ -57,6 +57,8 @@ pub struct ExternalCanister {
pub created_at: Timestamp,
/// The last time the record was updated.
pub modified_at: Option<Timestamp>,
/// Is the canister monitored by the station.
pub monitoring: Option<ExternalCanisterMonitoring>,
}

#[storable]
Expand Down Expand Up @@ -129,6 +131,8 @@ pub struct ExternalCanisterCallerPrivileges {

pub type ExternalCanisterAvailableFilters = GetExternalCanisterFiltersResponse;

pub type ExternalCanisterMonitoring = MonitorExternalCanisterStartInput;

impl ExternalCanister {
pub const MAX_NAME_LENGTH: usize = 100;
pub const MAX_LABEL_LENGTH: usize = 50;
Expand Down Expand Up @@ -448,6 +452,7 @@ pub mod external_canister_test_utils {
state: ExternalCanisterState::Active,
created_at: next_time(),
modified_at: None,
monitoring: None,
}
}
}
Expand Down Expand Up @@ -483,6 +488,7 @@ mod tests {
assert_eq!(model.state, deserialized_model.state);
assert_eq!(model.created_at, deserialized_model.created_at);
assert_eq!(model.modified_at, deserialized_model.modified_at);
assert_eq!(model.monitoring, deserialized_model.monitoring);
}

#[test]
Expand Down
11 changes: 6 additions & 5 deletions core/station/impl/src/models/request_operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ pub struct MonitoringExternalCanisterCyclesThresholdInput {

#[storable]
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum MonitorExternalCanisterStartStrategy {
pub enum MonitorExternalCanisterStrategy {
Always(u128),
BelowThreshold(MonitoringExternalCanisterCyclesThresholdInput),
BelowEstimatedRuntime(MonitoringExternalCanisterEstimatedRuntimeInput),
Expand All @@ -555,24 +555,25 @@ pub enum MonitorExternalCanisterStartStrategy {
#[storable]
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MonitorExternalCanisterStartInput {
pub strategy: MonitorExternalCanisterStartStrategy,
pub funding_strategy: MonitorExternalCanisterStrategy,
pub cycle_obtain_strategy: Option<CycleObtainStrategy>,
}

#[storable]
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum MonitorExternalCanisterOperationKind {
Start(crate::models::MonitorExternalCanisterStartInput),
Start(MonitorExternalCanisterStartInput),
Stop,
}

#[storable]
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MonitorExternalCanisterOperationInput {
pub canister_id: Principal,
pub kind: crate::models::MonitorExternalCanisterOperationKind,
pub kind: MonitorExternalCanisterOperationKind,
}

pub type MonitorExternalCanisterOperation = crate::models::MonitorExternalCanisterOperationInput;
pub type MonitorExternalCanisterOperation = MonitorExternalCanisterOperationInput;

#[storable]
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
Expand Down
2 changes: 1 addition & 1 deletion core/station/impl/src/services/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ impl AccountService {
write_system_info(system_info);

#[cfg(target_arch = "wasm32")]
crate::services::cycle_manager::CYCLE_MANAGER.set_global_obtain_cycles_strategy(
crate::services::cycle_manager::CYCLE_MANAGER.set_global_cycle_obtain_strategy(
&CycleObtainStrategy::MintFromNativeToken {
account_id: new_account.id,
},
Expand Down
2 changes: 1 addition & 1 deletion core/station/impl/src/services/cycle_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl CycleManager {
ic_cdk::print("Cycle manager: monitoring started.");
}

pub fn set_global_obtain_cycles_strategy(&self, strategy: &CycleObtainStrategy) {
pub fn set_global_cycle_obtain_strategy(&self, strategy: &CycleObtainStrategy) {
FUND_MANAGER.with(|manager| {
let mut fund_manager = manager.borrow_mut();
let options = fund_manager.get_options();
Expand Down
Loading
Loading