Keeping compatibility with 2.51 on type level
Tõivo Leedjärv <[email protected]> Tue, 20 Jul 2021 21:04:30 +0200
| Newsgroups | gmane.network.unison.devel |
|---|---|
| Message-ID | <CAALvpZTe-BvPTWoQboMZ9mLo+BzKFihwgvsszA=OXiKXGut-Ag@mail.gmail.com> |
I have added two more commits to PR https://github.com/bcpierce00/unison/pull/507 Since the PR is now fully compatible with 2.51, there is yet another piece of the puzzle that must be solved if we want to keep that compatibility in the future. Due to 2.51 using OCaml's Marshal module for on-the-wire encoding then in addition to requiring mostly matching OCaml versions, also the types on both ends must match exactly. And this is precisely what these two additional commits are about. The code is there for review, this mail is just to clarify some of the assumptions and design decisions I made. As a background for why this matters and why it's needed: with this foundation I can make for example the ACL and xattr patches non-breaking. - The assumption is that the only way to remain compatible with 2.51 is to keep unchanged the types that are exchanged between client and server. - To that end, the types that are changed (due to new features, bug fixes, you name it) must be duplicated: one type for the actual code to function and the other type that is an exact copy of how it existed in 2.51 <= 2.51.4. - That copy of a type is never used in the then-current code, it is there only to provide on-the-wire compatibility with 2.51. As such, the data will be converted between the types at the moment of marshaling and unmarshaling with the help of the `Marshal` module. - Each RPC call takes type-specific conversion functions (optional, supplied only if the types have changed). - While easily extendable to future version changes, I have foreseen this mechanism to be used only for compatibility with 2.51. Managing type changes between future versions (those using Stéphane's Umarshal, for example) will have basically the same mechanism built-in (by making dynamic/conditional the definition of "schema" for marshaling and unmarshaling a certain type (it will be static for most types, since they don't change between versions)). - In the code, I decided to keep the copies of the so-called compatibility types in the same module, next to the "current" types. Likewise with any functions that must be duplicated to work with the compatibility types (besides the conversion functions, these would be very rare). I did it mainly for simplicity and code locality (compatibility code is right next to the code it provides compatibility for). Perhaps a cleaner solution would be to add a V0 sub-module, but my OCaml skills don't see how to make it work in a simple way. In the commits you can see an example with `Update.archive` and `Props.t` preserved in their 2.51 state. Note that in addition to plain data conversions, the `checkArchive` function must be preserved as well as it's result on both ends must match and is directly dependent on the entire data structure. I have verified that this works and retains full compatibility with 2.51 even if the current `Props.t` is changed. And to be complete, it has to be mentioned that this approach only works as long as the new code does not break with the data conversions (which by definition are lossy). _______________________________________________ Unison-hackers mailing list [email protected] https://LISTS.SEAS.UPENN.EDU/mailman/listinfo/unison-hackers