Hello, I want to discuss whats the best way to save canister’s stable memory, while upgrading its wasm using install_code method of IC management canister ?
To be more clear, I want to upgrade some motoko objects with new fields which were stored in stable memory.
So how to save this stable memory while upgrading canisters.
I’m confused about your question; as far as I know, stable memory is automatically persistent across upgrades.
Ahhh ok ok.
Lets say canisters stable memory data structures are changed (say changes in motoko objects), so when we will upgrade the canisters to new wasm, stable memory will get vanished.
So for this i am asking best way, aFAIK pre/post upgrades is the only way, but I am not sure, weather pre/post upgrades run or not when we upgrade wasm of canister via install_code method.
I updated the question as well. Thanks for letting me know.
No idea of Motoko but when it comes to the Rust stable structure crate, @ielashi has wrote a small short tutorial about this particular subject: https://github.com/dfinity/stable-structures/blob/main/docs/schema-upgrades.md
Does that help?
In rust its clear, But dk if something like this exist in motoko as well.
No idea. I can forward your question though.
That would be helpful for sure
Motoko gets a bit confusing. There are “stable” variables and there is “stable memory”. In hindsight, I wish they had been called “managed” variables. When you do something like:
stable var halt : Bool = false;
Motoko takes responsibility of moving halt into stable memory on pre upgrade and then back into halt after post-upgrade. Therefore you don’t need to ‘manage’ it your self in your pre and post upgrade.
Stable memory is different and uses the stable regions and https://github.com/dfinity/motoko-base/blob/master/src/Region.mo or https://github.com/dfinity/motoko-base/blob/master/src/ExperimentalStableMemory.mo to load data into stable memory out side of motoko management. You can put way more in through the region or esm library because it doesn’t have to be streamed in and out of memory during upgrade(takes a lot of cycles).
In either instance, if you change your structure you’ll likely need to do some magic in pre and post upgrades to move your data from one type to another.
install_code
can be called with a number of modes, but if the mode is upgrade
, then the Motoko stable variables (and the IC stable memory used to store them during upgrade) will be preserved.
The general rule is that any actor fields that are declared stable
will be serialized to stable memory before upgrade, and deserialized from stable memory after upgrade. The type of such a variable must itself be a stable
type which is basically most types with the exception of functions and type containing functions (such as objects with methods).
Because the old value has to be compatible with the new type, the type of a existing field can only evolve to a Motoko supertype: i.e. a Nat
can become an Int
, a record type can lose some fields, a variant type can gain some variants, but not the other way around.
In addition, the replacement actor can declare some new stable variables, whose values will be obtained from the initializers for the variables (and retained in future upgrades).
The recommended way to change the type of an old field to an unrelated type (e.g. adding a field to a record or more generally changing a data structure), is to declare a new stable variable, with a new name, explicitly initialized from the old stable variable, but adding the field/changing the representation. Question on updating data structures of stable variables in Motoko - #11 by chenyan sketches an example.
In addition to this basic mechanism, Motoko also lets you declare specific pre- and post- upgrade system
methods that let you explicitly modify/restore additional state just before and after an upgrade, for example, if you need to transfer some transient state to stable variables before doing the upgrade.
Some relevant Motoko documentation: