Closed paulyoung closed 1 year ago
let note_id = NEXT_NOTE.with(|counter_ref| {
let mut writer = counter_ref.borrow_mut();
*writer += 1;
*writer
});
On the question of Cell
vs RefCell
, maybe I made an incorrect assumption there’s nothing about the types themselves that implicitly make them stable or flexible.
Either way, I think that would be good to clarify.
The leads me to other questions about the upgrade process. I’ll try to report back with my findings here.
Some further questions:
pre_upgrade
and post_upgrade
?For 2, I misunderstood. I thought that https://github.com/dfinity/cdk-rs/pull/215 completely removed the storage API, but it didn't.
It looks like storage::stable_save
and storage::stable_restore
are still available: https://github.com/dfinity/cdk-rs/pull/215/files#diff-3c2aeeb74a082f6b1d004977688e887a7496565e415611a73dc487e2d95e002dR49-R57
Hi @paulyoung!
Thanks a lot for your feedback!
Here, an example is given that uses Cell for NEXT_USER_ID But later it is explained that variables using Cell “flexible” and are discarded on upgrades. Would it make more sense to use RefCell in the original example?
The difference between Cell
and RefCell
is not that one is always flexible and the other is stable, the difference lies in the kind of values we keep inside. It makes sense to use Cell
for immutable values like integers and RefCell
— for mutable values like collections (HashMaps, Vectors, etc.).
But there isn’t an example of how one might properly manage the creation of new user IDs (assuming they are incremental, like in NEXT_USER_ID)
Surprisingly, I hear this question very often, I'll add a piece of advice on the topic. Basically, a simple counter should work in 90% of cases, just like database ID sequences. Many people opt for UUID, which is often an unnecessary complication.
Internet Identity also has a sequential user number: However, it uses stable memory which is much more involved than using a stable variable. Could you explain why that is?
Internet Identity was designed to store large amounts of data (currently, it uses ~4GiB of storage).
Serializing the whole state on upgrades is impractical for large datasets, so the II canister uses stable memory as the main storage, which makes upgrades safe and blazingly fast.
However, this design implies that II needs to control the stable memory layout precisely, and invoking stable_save
can (and will) corrupt all the stable data structures.
Hi @roman-kashitsyn!
I was re-reading Effective Rust Canisters and I wanted to say thank you for writing it. It’s a great resource.
I had some questions/suggestions, particularly around generating sequential user numbers that I hoped you could help me with.
Thank you in advance!
Here, an example is given that uses
Cell
forNEXT_USER_ID
https://github.com/roman-kashitsyn/mmapped.blog/blob/7eaa01608b73cde2331a84f0ce645da020b05876/posts/01-effective-rust-canisters.html.pm#L44
But later it is explained that variables using
Cell
“flexible” and are discarded on upgrades.https://github.com/roman-kashitsyn/mmapped.blog/blob/7eaa01608b73cde2331a84f0ce645da020b05876/posts/01-effective-rust-canisters.html.pm#L159
https://github.com/roman-kashitsyn/mmapped.blog/blob/7eaa01608b73cde2331a84f0ce645da020b05876/posts/01-effective-rust-canisters.html.pm#L170
Would it make more sense to use
RefCell
in the original example?There are some examples of functions that take
UserId
:https://github.com/roman-kashitsyn/mmapped.blog/blob/7eaa01608b73cde2331a84f0ce645da020b05876/posts/01-effective-rust-canisters.html.pm#L217
https://github.com/roman-kashitsyn/mmapped.blog/blob/7eaa01608b73cde2331a84f0ce645da020b05876/posts/01-effective-rust-canisters.html.pm#L250
But there isn’t an example of how one might properly manage the creation of new user IDs (assuming they are incremental, like in
NEXT_USER_ID
)Could you provide an example of that?
Are there any pitfalls with something like the following?
What do you recommend?
There’s a link to Internet Identity:
https://github.com/roman-kashitsyn/mmapped.blog/blob/7eaa01608b73cde2331a84f0ce645da020b05876/posts/01-effective-rust-canisters.html.pm#L688
Internet Identity also has a sequential user number:
https://github.com/dfinity/internet-identity/blob/b434acea3831e4317cf20c26488f1d31570dd35b/src/internet_identity/src/storage.rs#L128-L140
However, it uses stable memory which is much more involved than using a stable variable. Could you explain why that is?