We'd like to be able to reuse saved Flow server state between our CI machines (linux) and our developer machines (macOS). Currently, trying to do so raises Saved-state file failed version check. Expected version "8b41cfe4420429b\000" but got "2ca8752fb8ca764\000" when we try to launch the Flow server.
We'd like to create a post-merge CI job that launches the Flow server, saves state, and then uploads that state to a shared internal location. Then, for development branches, our Flow script could pull the appropriate saved state based on merge-base, create .flow.saved_state_file_changes as appropriate, and then launch the server with --saved-state-fetcher=local --lazy. This should achieve a massive decrease in local Flow startup time.
It seems that we won't be able to do that without running the macOS Flow binary in our CI environment. Is interoperable saved state something that is feasible or should we be looking to find a way to generate state in the same environment we want to use it? I'm also open to hearing other strategies for how teams are using save-state to speed up development.
Thanks!
this should be doable. the saved state file format is portable, but not stable. it's just serialized ocaml data structures, so it changes often between versions. the version mismatch you're running into is trying to ensure it's invalidated whenever the binary changes.
these versions are computed by hashing the binary, and obviously the Mac and Linux binaries are different. but since they come from the same commit, compatibility shouldn't be an issue. I think we could fix this by using the commit hash or version number for release builds, and continuing to use the binary's hash for dev builds.
cc @nmote
our Flow script could pull the appropriate saved state based on merge-base, create .flow.saved_state_file_changes as appropriate, and then launch the server with --saved-state-fetcher=local --lazy.
we should perhaps discuss this in a separate issue, but internally we use a custom build with an additional saved-state fetcher, so we do --saved-state-fetcher=fb (rather, saved_state.fetcher=fb in flowconfig). it gets the mergebase from mercurial, queries a DB to find the most recent saved state from CI (it's generated on a schedule, doing it on every merge is too expensive), downloads it, then asks mercurial for all the files changed since the saved state's commit. you'd replace this: https://github.com/facebook/flow/blob/1a8a22eaf2541febe77856a88f6ad69cde1367a1/src/stubs/saved_state_fb_fetcher.ml
Yes, I think this is a good idea. Like @mroch said, the saved state is made up of just serialized OCaml data structures, which should be the same across platforms. The build hash check is overly strict with this in mind. I'm not sure exactly what would be required to use a different identifier on release builds. @mroch, do you have any suggestions?
It's also worth noting that we'll need to solve this problem as we continue to roll out saved-state internally to repositories that people develop on across platforms.
I also think it would be okay to introduce a flag that tells Flow to skip this check. There are several times while testing that I would have liked such a flag, and you could use it carefully here as a short-term solution. However, the check is there for a reason: Flow can segfault if it attempts to load a saved state with a different structure than it's expecting (this is a consequence of how OCaml serializes and deserializes data).
Lastly, I'm taking a month off of work starting on Friday. I won't have time to do anything about this until I get back in early August.
Most helpful comment
this should be doable. the saved state file format is portable, but not stable. it's just serialized ocaml data structures, so it changes often between versions. the version mismatch you're running into is trying to ensure it's invalidated whenever the binary changes.
these versions are computed by hashing the binary, and obviously the Mac and Linux binaries are different. but since they come from the same commit, compatibility shouldn't be an issue. I think we could fix this by using the commit hash or version number for release builds, and continuing to use the binary's hash for dev builds.
cc @nmote