5 ms·
Software A version 1 consumes format F1 and produces format G1 data, and software B version 1 consumes format G1 and produces H1. To upgrade format G2 we must
by geocar 9y ago
Software A version 1 consumes format F1 and produces format G1 data, and software B version 1 consumes format G1 and produces H1.
To upgrade format G2 we must change both software A and B.
First, software B version 2 must accept both G1 and G2. To do this we may need to build software A version 2 and try them in a sandbox environment to gain confidence that ∀F1 we produce the correct G2. If F1 is complete, we may be able to do this exhaustively, but if F1 is sufficiently diverse, monte carlo simulation might be used.
Then, if there's a 1:1 relationship between A/B we can upgrade pairs.
If there's a N:M relationship, we need to upgrade all of the instances of software version B1 to B2 (at least within a shard). If you're running in a non-stop environment, this might have it's own challenges. Only then, can we begin the upgrade from A1 to A2.
Now:
Something, somewhere needs to record what and where we are in this journey. It is relatively straightforward how to do this with a monorepo, but it is very unclear how to do it with a distributed repository:
Almost everyone I know punts and uses some other golden record (like a continuous integration server, or a ticketing system, or an admin/staging system), and like it or not: that's your monorepo.
- newfoundglory 9y agoNot by any definition I can think of. How are you defining "monorepo"?
- qquark 9y ago> but it is very unclear how to do it with a distributed repository Versioning through branching and tagging, while having some drawbacks - at least the fact that you have to DO an operation and that this is not automatic - seem to solve this problem, and are not, in my eyes, a form of monorepo. You globally get more flexibility at the cost of a bit more repo management work. If the problem is retrieving the right version automatically, externals or submodules should be able to solve this problem. If A and B have no clear dependency direction, a top level repo might help.
- geocar 9y ago> a top level repo might help. This is the way I generally do it: A repository that represents my system/environment that has submodules for A1, A2, B1, and B2, and scripts for updating the environment.
- pas 9y agoMaybe using a ticketing system [or just call it a project management system] is the right abstraction level. If A and B has nothing to do with each other - other than for some circumstantial reason they consume data from each other, then why would we care if A or B starts to support a new output format? If we want to do a format change for some reason, maybe it'll allow better security/traceability, then sure, make a project and track the tasks (like make A able to produce/consume new format, make B able to produce/consume new format, deploy A2 and B2 to test environment, promote to prod), but I don't see why would you track that on the source code versioning level. A and B has separate tests to ascertain that they can deal with the new format, and then you do the integration testing, that might catch problems, that then should be covered by unit tests in A or B. (Or in a fuzzer for said format.)
- geocar 9y ago> Maybe using a ticketing system [or just call it a project management system] is the right abstraction level. > If A and B has nothing to do with each other - other than for some circumstantial reason they consume data from each other, then why would we care if A or B starts to support a new output format? First, even if the coordination between A and B is recorded in the ticketing system, the coordination between F and G is probably not. > I don't see why would you track that on the source code versioning level. Pretend F and G are tables in a database (or other data storage system) if that makes it easier. Where is the schema stored? Who records the migration path? Many people like to record migrations in a version control system, but it is tricky to link those migrations to the (otherwise) independent A and B. If these are file formats where exists the code to consume and produce them? Or network formats? The problem remains the same -- do we break this up into additional libraries? That there's a very real ordering between release of A and B that isn't properly encoded, we're relying on process diligence (as opposed to tooling) to be correct.
- pas 9y agoIf tables, then if they are in the same DB, they should be in the same project. If they are independent tables, then I don't care, show me the API between the projects. If these are file/network/serialization/wire/in-memory/binary/codec formats, then there are conformance checkers (passive and active, like fuzzers). Those are separate projects, but they can be used like tools during testing and development. Rely on tooling to make sure that the stated goal of the project is reached. (It now supports F or G or X,Y,Z formats. It supports output-format G by processing input-format F. If that's a project requirement, test it in that project.) You can use a top level repo for the integration tests. But it's no need to make it one flat repo.
- Joeri 9y agoYou can also design software A to produce both G1 and G2 side by side, deploy it, and then develop new software B against G2, submitting bug reports to project A when there’s a problem detected in G2. If you’re doing the multirepo strategy it’s best imho to make the projects truly independent, as if they were developed by different companies. That way every project only needs to think about its own dependencies and consumers, and how to do migrations, without needing to have the big picture mapped out.
- geocar 9y ago> You can also design software A to produce both G1 and G2 side by side This can be impractical if G is a database table that is very large. > it’s best imho to make the projects truly independent, as if they were developed by different companies. One of our systems might cost £300k, so completely desynchronising them so that code paths can build both G1 and G2 simultaneously (allowing B to develop separately) means "simply" doubling the costs. That might put our team at a disadvantage against someone who figures out another way.
- Groxx 9y ago> This can be impractical if G is a database table that is very large. If this is true, you have no choice, and must run things side by side while you convert to G2. Or shut everything down to make the migration atomic, which is increasingly not an option.
- geocar 9y ago> you have no choice It depends on your database. If you imagine a simple postgres or mysql server and an "alter table G..." then you're right. If (however) G1⊂G2 then a document store or a column-based database can usually partition the table somehow.
- gwenzek 9y ago> This can be impractical if G is a database table that is very large. Unless if the new format G2 is a super set of the old format G1. Read protobuffers best practice to know more about this.