Pre-RFC: Decouple services using structured typing

more eyes could help, yeah.

feel free to already share a repro of the outstanding challenge here if you’d like.

1 Like

Alright, it’s done! I created the RFC at [RFC 0189] Contracts by ibizaman · Pull Request #189 · NixOS/rfcs · GitHub It has a link to the draft PR in it. The issue can be found in the “unresolved” section.

12 Likes

This idea looks fantastic!

I have 2 questions:

What about “contract evolution”?
And by that, I mean versioning and breaking changes.
Modifying a contract by adding a field with a default value, it’s a backwards compatible change, but renaming a field would be a backwards incompatible change. Something like a “backup” contract might be a solved problem, but I bet there will be contracts that are too green and will need to evolve over time.

In Kubernetes, resources have like: apiVersion: gateway.networking.k8s.io/v1. In avro, there’s the concept of “schema evolution”, where you can say “this schema accepts only backwards compatible changes”.

What about features support within a contract?
Where do you draw the line in what’s supported and what it’s not, let’s say on a reverse_proxy? Could it be composed of a subset of contracts?
Let’s say tomorrow there’s a new ACME Challenge, or a reverse proxy adds support for HTTP/4, and you want to enable that feature? How does a Reverse Proxy implementation says “I support this but not that”?

1 Like

Those are good questions indeed!

For contract evolution, I think we can resort to using the same mechanism as we do now for module options. That is using mkRemovedOptionModule and mkRenamedOptionModule. With those we can nicely deprecate options as need be and evolve the contract. I would stay far away from versions. They have their use in APIs where those using the API do not decide when they upgrade. But in nixpkgs, one updates their nixpkgs version at their own leisure so using the pattern above should be enough.

For features support, we’ll see in practice but I don’t mind having multiple contracts with only slightly different list of options. Having one contract with optional options will be confusing and producing a useful error message will be hard. (I could be wrong for the error message, I haven’t tried). For example, I’m currently adding a datasetBackup contract on top of the fileBackup and databaseBackup ones. Indeed, for ZFS datasets, it makes no sense to talk about sourceDirectories to be backed up. Instead, we need the name of the dataset to be backed up. After trying one unified backup contract, I realized it doesn’t work great.

The reverse proxy contract will be a hard nut to crack. I need more experience configuring those to be able to give a meaningful answer here. That being said, I think the solution will be to split the reverse proxy in its primordial constituents like you suggested. I’m leaving this vague intentionally, to be filled later :sweat_smile:

2 Likes

going by #506343:

contract evolution

  • lib/tests/modules/contracts-rename-warning.nix
  • lib/tests/modules/contracts-contract-rename.nix

Could it be composed of a subset of contracts?

  • nixos/tests/contracts/chaining.nix

What about features support within a contract?

i’ve had a poc on this, but tryna find earlier discussion we had on this still, bit on the fence on how i feel about it

2 Likes

I think this is the best shot so far for a self-contained, no fluff PR for introducing contracts using the file backup contract Contracts for file backups by ibizaman · Pull Request #522054 · NixOS/nixpkgs · GitHub. Check the PR description for all the info needed.

9 Likes

to try and revive the above one:

1 Like