-
Notifications
You must be signed in to change notification settings - Fork 101
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
experiment: attach optional migration expression to actor (class) as actor [exp]? #4812
base: master
Are you sure you want to change the base?
Conversation
Did you consider |
Not yet, but I also don't want Maybe
Or
But I expect parsing hell from the last one. Are parentheticals only meant to attach to expressions? |
Not specifically. Any AST node can be it. |
src/mo_frontend/typing.ml
Outdated
display_typ_expand typ; | ||
tfs | ||
| _ -> | ||
local_error env exp.at "M0093" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why a different error code from above? Cut'n'paste error?
* refactoring (buggy) * fix bug * renaming * use blockE to avoid nested letE
…ion produced fields
Support the specification of an optional migration function on the definition of an actor or actor class.
The function must consume and produce records of stable types.
Roughly:
This determines the pre stable signature of the actor.
Dynamically, on upgrade, the (implicit or explicit) post signature of the old actor must be compatible with the pre-signature of the new actor. This is either checked offline, statically in the classical compiler (and by Candid deserialization), and dynamically in the EOP compiler, using a pre signature type descriptor. All stable variables in the domain of the migration function must be non-null in the deserialized or transferred stable record. The migration function is applied to the subset of these fields to produce the codomain record. A new stable record is constructed using the values from the codomain and the values that were not overridden by the domain. Values in the domain are set to null (and will be initialized if present in the post signature).
(It would also be possible to transfer values from the domain, if not in the codomain, but required and compatible with the post-signature, but this design choice is not implemented)
A fresh install ignores the migration code; an upgrade applies it before entering the constructor.
All variables in the codomain must be present for the migration to succeed (since there is no way to provide an initial value).
You will need to remove the migration code to do a self-upgrade.
Follow on PRs implement support for EOP (#4829) and syntactic stable signatures (#4833) (both merged here but might simplify reviewing)
Extended stable signatures
A stable signature (stored in metadata) is now either a single interface of stable fields (as before) or (the new bit) a dual interface recording the pre and post upgrade interface when performing migration.
The pre and post fields are implicitly identical for a singleton interface and provide for backwards compatibility and ordinary upgrades (sans explicit migration).
Stability compatibility now checks the post-signature of the old actor is compatible with the pre-signature of the new actor.
Done this way, there should be no need to modify dfx, which defers to moc for the compatibility check anyway.
Example: adding record fields
To upgrade from:
to incompatible stable type interface:
After we have successfully upgraded to this new version, we can also upgrade once more to a version that drops the migration code.
TODOs
Some, but not all migrations might be reject as type-incompatible, but others may not be:
* Maybe an implicit isMigrated field is enough, or a check that the post-signature of the new "not equals" the post-signature of the old canister?