Skip to content
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

Give nix daemon and nix-store --serve protocols separate serializers with version info #6223

Merged
merged 5 commits into from
Oct 23, 2023

Conversation

Ericson2314
Copy link
Member

@Ericson2314 Ericson2314 commented Mar 9, 2022

This allows that the versioning parts for it to actually be correct.

Version agnostic serializers are deduped in common-protocol.hh/ namespace nix::common_proto, while version-specific ones written separately in {worker,serve-proto.hh/namespace nix::{worker,serve}_proto.

Motivation

For me, these are main motivations for this:

  1. No more perverse incentives. fe1f34f did some awkward things because the serializers did not store the version. I don't want anyone making changes to be pushed towards keeping the serialization logic with the core data types because it's easier.

  2. I am confident with the incremental approach I tried out in Factoring out parts of the serve protocol for Hydra to share #6134, we can get Hydra using ssh-ng:// (and the Store abstraction) pretty quickly. After that, I hope we can deprecate ssh:// for a few releases and then remove it. I don't want to worry about accidentally changing it / breaking it during that time, and having separated codes ensures it stays out of the way!

  3. In general, for anyone else implementing the daemon protocol, the more we factor out logic from daemon.cc, remote-store.cc, etc., the easier things will be to understand. There are a number of projects looking to reimplement the daemon protocol, and this helps them.

The last two commits are especially notable, because they use the serialization refactoring to dedup and factor out / improves factored out seralizers for:

  • BuildResult
  • PathInfo

This demonstrates the sort of cleanup that this is supposed t enable

Context

The history in this PR has been delicately preserved to allow reviewing commit-by-commit. Please do so!

If a certain prefix of commits seems good, we can always merge them first too.

depends on #8360
depends on #9197

Checklist for maintainers

Maintainers: tick if completed or explain if not relevant

  • agreed on idea
  • agreed on implementation strategy
  • tests, as appropriate
    • functional tests - tests/**.sh
    • unit tests - src/*/tests
    • integration tests - tests/nixos/*
  • documentation in the manual
  • code and comments are self-explanatory
  • commit message explains why the change was made
  • new feature or incompatible change: updated release notes

@Ericson2314
Copy link
Member Author

Rebased this on top!

@thufschmitt
Copy link
Member

I’m quite scared by these raw #include-d files that have a different semantic depending on where they are included.

A nicer way to do that might be to

  1. Replace the worker_proto and serve_proto namespaces by classes
  2. Add these classes as argument to all the templates defined here (or maybe use plain subclassing?) so that they can be reused “normally”

@Ericson2314 Ericson2314 force-pushed the worker-proto-with-version branch from 13b17d1 to 38a26a1 Compare March 25, 2022 08:18
@Ericson2314
Copy link
Member Author

@thufschmitt Those files are gone! Also, less boilerplate to handle versions now.

Combined with #6312 and likewise for valid path info, this will be much nicer.

@Ericson2314 Ericson2314 changed the title Give the server protocol its own serializers Give the nix-store ---serve protocol its own serializers Mar 28, 2022
@thufschmitt
Copy link
Member

I do like the overall idea, but I find this really complex, and I don’t see what justifies all this this complexity. Do we really need all that cpp and namespace mangling? I’d much rather use plain inheritance or templating, even it it comes with more boilerplate

@Ericson2314
Copy link
Member Author

@thufschmitt What CPP mangling is there now?

I agree the namespace tricks are unfortunate --- if we have just had Rust's Traits this would all be so much easier --- but I thought quite long about alternatives and I can't think of much different unless it become unextendable (e.g. fit set of method on some serializer, lots of virtual), which doesn't sit right with me but also is just feels like far more churn.

The namespace tricks are roughly how nlohmann json works, too, fwiw.

I would like to do this more more less as-is, and just hope we can get rid of the nix-store --serve protocol soon, after which things are simpler again.

@thufschmitt
Copy link
Member

What CPP mangling is there now?

No CPP mangling, just namespace mangling ;).
But the WRAP_META_PROTO, MAKE_PROTO and friends intuitively feel like something that would better be replaced by a class holding both the read and write methods.

I can't think of much different unless it become unextendable (e.g. fit set of method on some serializer, lots of virtual)

Is it that bad? After all we’re in control of everything, so it’s fine to have one master-class declaring all the methods (beside it’s easier to have a view of everything that’s implemented)

(Just to be clear: I’m not saying that this approach is wrong. There’s a lot of nasty complexity here and I’m all ready to believe that we don’t have a choice. But in that case it deserves a clear justification)

@Ericson2314
Copy link
Member Author

Is it that bad? After all we’re in control of everything, so it’s fine to have one master-class declaring all the methods (beside it’s easier to have a view of everything that’s implemented)

You are right its not a problem in practice. Just the non-modularity of it sits very uncomfortably with me. If we ever want to make a greenfield new protocol that is e.g. Protobuf or JSON, and easier for other tools I understand, to those tools usually take the open world approach so I feel like it's good to match it too.

The tricky parts here are trying to share code between daemon protocol / serve protocol / hooks / import/export / whatever else. As soon as we stop/don't need to do that, it gets easier again.

@thufschmitt
Copy link
Member

If we ever want to make a greenfield new protocol that is e.g. Protobuf or JSON, and easier for other tools I understand, to those tools usually take the open world approach so I feel like it's good to match it too.

Well, these new protocols wouldn’t share anything with the current one, would they?

The tricky parts here are trying to share code between daemon protocol / serve protocol / hooks / import/export / whatever else. As soon as we stop/don't need to do that, it gets easier again.

Unfortunately that will probably have to stay for at least a couple years, so we’d better not treat this as too temporary

@Ericson2314
Copy link
Member Author

Well, these new protocols wouldn’t share anything with the current one, would they?

Yes they wouldn't, and thus the downsides of the current approach would hopefully be avoided

Unfortunately that will probably have to stay for at least a couple years, so we’d better not treat this as too temporary

Perhaps I just need to overcome the "ick" reflex and just duplicate the code. Then the status quo will also be simpler and modular.

I think once Hydra can use ssh-ng://, we can freeze and deprecate ssh://. Then, it is perfectly OK for the code to drift out of sync, so that might be a good time to get over the "ick" and do the duplicate + simplify.

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/a-proposal-for-replacing-the-nix-worker-protocol/20926/12

@Ericson2314 Ericson2314 marked this pull request as draft February 22, 2023 15:44
@Ericson2314 Ericson2314 force-pushed the worker-proto-with-version branch from 38a26a1 to aac2270 Compare February 24, 2023 20:50
@Ericson2314 Ericson2314 marked this pull request as ready for review February 24, 2023 20:50
@Ericson2314 Ericson2314 changed the title Give the nix-store ---serve protocol its own serializers Give the nix-store ---serve protocol its own serializers Feb 24, 2023
@fricklerhandwerk fricklerhandwerk added the store Issues and pull requests concerning the Nix store label Mar 3, 2023
@Ericson2314 Ericson2314 changed the title Give the nix-store ---serve protocol its own serializers Give the nix-store --serve protocol its own serializers Mar 15, 2023
Ericson2314 added a commit to obsidiansystems/nix that referenced this pull request Apr 15, 2023
In many cases we are dealing with a collection of realisations, they are
all outputs of the same derivation. In that case, we don't need
"derivation hashes modulos" to be part of our map key, because the
output names alone will be unique. Those hashes are still part of the
realisation proper, so we aren't loosing any information, we're just
"normalizing our schema" by narrowing the "primary key".

Besides making our data model a bit "tighter" this allows us to avoid a
double `for` loop in `DerivationGoal::waiteeDone`. The inner `for` loop
was previously just to select the output we cared about without knowing
its hash. Now we can just select the output by name directly.

Note that neither protocol is changed as part of this: we are still
transferring `DrvOutputs` over the wire for `BuildResult`s. I would only
consider revising this once NixOS#6223 is merged, and we can mention protocol
versions inside factored-out serialization logic. Until then it is
better not change anything because it would come a the cost of code
reuse.
@Ericson2314 Ericson2314 changed the title Give the nix-store --serve protocol its own serializers nix daemon and nix-store --serve protocols have separate serializers with version info Apr 15, 2023
@github-actions github-actions bot added the new-cli Relating to the "nix" command label Apr 15, 2023
@Ericson2314 Ericson2314 force-pushed the worker-proto-with-version branch from aac2270 to 8f29241 Compare April 15, 2023 19:44
@Ericson2314 Ericson2314 force-pushed the worker-proto-with-version branch from d5028d4 to df9cff2 Compare July 24, 2023 14:43
@Ericson2314 Ericson2314 force-pushed the worker-proto-with-version branch 2 times, most recently from 2a6b1f8 to 98c5476 Compare August 30, 2023 23:25
@Ericson2314 Ericson2314 force-pushed the worker-proto-with-version branch from 98c5476 to 0cb0060 Compare October 4, 2023 22:07
@github-actions github-actions bot added the with-tests Issues related to testing. PRs with tests have some priority label Oct 4, 2023
@Ericson2314 Ericson2314 force-pushed the worker-proto-with-version branch from 0cb0060 to ade5b21 Compare October 10, 2023 14:58
@github-actions github-actions bot removed the with-tests Issues related to testing. PRs with tests have some priority label Oct 10, 2023
@Ericson2314 Ericson2314 force-pushed the worker-proto-with-version branch from ade5b21 to 061a09d Compare October 10, 2023 15:36
@github-actions github-actions bot added the with-tests Issues related to testing. PRs with tests have some priority label Oct 10, 2023
@Ericson2314 Ericson2314 force-pushed the worker-proto-with-version branch 2 times, most recently from e4661d6 to e058ce5 Compare October 16, 2023 06:04
@Ericson2314 Ericson2314 changed the base branch from master to backport-9008-to-2.18-maintenance October 20, 2023 13:37
@Ericson2314 Ericson2314 changed the base branch from backport-9008-to-2.18-maintenance to master October 20, 2023 13:37
@Ericson2314 Ericson2314 force-pushed the worker-proto-with-version branch 2 times, most recently from 8d07f2a to ac860fd Compare October 20, 2023 16:44
@dpulls
Copy link

dpulls bot commented Oct 20, 2023

🎉 All dependencies have been resolved !

@Ericson2314 Ericson2314 changed the base branch from master to 0.6-maintenance October 20, 2023 17:57
@Ericson2314 Ericson2314 changed the base branch from 0.6-maintenance to master October 20, 2023 17:57
It was some ad-hoc functions to account for versions, while the already
factored-out serializer just supported the latest version.

Now, we can fold that version-specific logic into the factored out one,
and so we do.
Worker Protocol:

Note that the worker protocol already had a serialization for
`BuildResult`; this was added in
a4604f1. It didn't have any versioning
support because at that time reusable seralizers were not away for the protocol
version. It could thus only be used for new messages also introduced in
that commit.

Now that we do support versioning in reusable serializers, we can expand
it to support all known versions and use it in many more places.

The exist test data becomes the version 1.29 tests: note that those
files' contents are unchanged. 1.28 and 1.27 tests are added to cover
the older code-paths.

The keyered build result test only has 1.29 because the keying was also
added in a4604f1; the older
serializations are always used unkeyed.

Serve Protocol:

Conversely, no attempt was made to factor out such a serializer for the
serve protocol, so our work there in this commit for that protocol
proceeds from scratch.
It does not belong with the data type itself.

This also materializes the fact that `copyPath` does not do any version
negotiation just just hard-codes "16".

The non-standard interface of these serializers makes it harder to test,
but this is fixed in the next commit which then adds those tests.
This makes the path info serialisers ideomatic again, which allows me to
test them.
@Ericson2314 Ericson2314 force-pushed the worker-proto-with-version branch from ac860fd to 70f8b96 Compare October 20, 2023 19:21
@Ericson2314 Ericson2314 merged commit 8b68bbb into NixOS:master Oct 23, 2023
8 checks passed
@Ericson2314 Ericson2314 deleted the worker-proto-with-version branch October 23, 2023 13:16
tebowy pushed a commit to tebowy/nix that referenced this pull request Jul 11, 2024
…version

Give `nix daemon` and `nix-store --serve` protocols separate serializers with version info

(cherry picked from commit 8b68bbb)
Change-Id: Ia3d3b9fbaf9f0ae62ab225020b7d14790e793655
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
protocol Things involving the daemon protocol & compatibility issues store Issues and pull requests concerning the Nix store with-tests Issues related to testing. PRs with tests have some priority
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

7 participants