ZhenyaUsenko / motoko-hash-map

Stable hash maps for Motoko
MIT License
41 stars 12 forks source link

How to update the structure in a safe way #12

Open samlinux opened 7 months ago

samlinux commented 7 months ago

I have structure like this:

type License = { license : Text; active : Bool; }; stable let map = Map.new<Nat, License>();

After some time I would like to add a further property to the License type: e.g. status:

type License = { license : Text; active : Bool; status:Bool; };

During the update process I receive a warning, what is fine.

Stable interface compatibility check failed for canister 'backend'. Upgrade will either FAIL or LOSE some stable variable data.

But, If I install the update, my data is lost and the query call failed.

Error: Failed query call. Caused by: Failed query call. The replica returned a replica error: reject code CanisterError, reject message IC0503: Canister bkyz2-fmaaa-aaaaa-qaaaq-cai trapped explicitly: unreachable, error code Some("IC0503")

So how can I handle this situation ?

ZhenyaUsenko commented 7 months ago

One way is to add new properties as optional

type License = {
  license: Text;
  active: Bool;
  status: ?Bool; // optional
};

This can be suboptimal as it will make you handle optional types explicitly every time you try to access licence.status

That's why I've designed a migration pattern some time ago (similar to what you could use while working with SQL databases)

Here is a sample project structure that can help you implement this migration pattern in your project

https://github.com/ZhenyaUsenko/motoko-migrations

samlinux commented 7 months ago

Thank you I will study it.

samlinux commented 4 months ago

Hey 👋 , the migration strategy works in my example, thanks for putting it together.