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

async-nats 1.0.0 release planning #896

Open
13 of 16 tasks
Jarema opened this issue Mar 23, 2023 · 7 comments
Open
13 of 16 tasks

async-nats 1.0.0 release planning #896

Jarema opened this issue Mar 23, 2023 · 7 comments

Comments

@Jarema
Copy link
Member

Jarema commented Mar 23, 2023

This issue gathers all work needed for 1.0.0 release and encourages discussions.

Current list of pending work

Release 0.30.0 should bring most of the work and hopefully all breaking changes.

@Jarema Jarema pinned this issue Mar 23, 2023
@Jarema
Copy link
Member Author

Jarema commented Nov 8, 2023

We decided to not touch current builders, and instead add new ones whenver there is a need for them.

@ekalosak
Copy link

ekalosak commented Mar 2, 2024

Any updates on the 1.0 release plan? Looks like all the work is done, from that checklist?

@Jarema
Copy link
Member Author

Jarema commented Mar 4, 2024

@ekalosak After some consideration, we settled at:

  1. Do not release actual 1.0.0
  2. Provide guarantees and standards that library will be held to, which means:
  • being very explicit whenever any breaking change is introduced
  • avoid doing breaking changes when not well justified or forced by upstream dependencies.

Despite library being in stable, production ready state, making it 1.0.0 brings a hefty set of problems
Let's list some of them:

  1. Any change to a public struct is technically a breaking change and CAN break people. And we are expanding many public structs with each release of nats-server when new features are added to streams, consumers etc.
  2. Any change to error enums is a breaking change. While we don't do that often, sometimes its forced, when server adds new errors. We could mitigate it by making all the error enums non exhaustive, but that impacts ergonomics quite a bit.
  3. Some of our critical dependencies are < 1.0.0, like rustls. This library is mature, well written, well maintained, but it also decided to stay < 1.0.0. We do expose some of its structs to not block users from niche, yet important use cases and setups.
  4. While async ecosystem is maturing, a lot of new important features are still not there. We just got async traits, while we still wait for async closures and more, that we would love to incorporate instead of hacky closures returning async blocks etc.

All of above means that we would either really often iterate on major version of the library, or, trying to avoid any breaking changes, keep the library "in the past" and not benefit from the good changes in maturing ecosystem.

@Kinrany
Copy link

Kinrany commented Apr 16, 2024

  1. Any change to a public struct is technically a breaking change and CAN break people. And we are expanding many public structs with each release of nats-server when new features are added to streams, consumers etc.
  2. Any change to error enums is a breaking change. While we don't do that often, sometimes its forced, when server adds new errors. We could mitigate it by making all the error enums non exhaustive, but that impacts ergonomics quite a bit.

If the server can add new errors in the future, shouldn't the client's enum be non-exhaustive anyway?

Are there breaking changes that happen to structs that aren't also covered by the ability to mark structs as non-exhaustive?

@Jarema
Copy link
Member Author

Jarema commented Apr 16, 2024

@Kinrany we did consider non-exhaustive errors, but the ergonomics of such are really bad.
We decided on leaving them exhaustive. Especially that rarely we expose those new errors directly. Usualy they are abstracted away into user-actionable items. It can happen though. Every single time its clearly telegraphed in release notes.

The actual server errors are represented in client as

pub struct ErrorCode(u64);

impl ErrorCode {

and are reachable via checking source of errors.

Regarding the non-exhaustive structs: those could not be used with ..Default::default() so not sure how that could help here?

@Kinrany
Copy link

Kinrany commented Apr 17, 2024

Regarding the non-exhaustive structs: those could not be used with ..Default::default() so not sure how that could help here?

..Default::default() is used purely for ergonomics, right? Wouldn't it be better for ergonomics to provide a builder for every type anyway? 🤔

Foo::new().option(value).build() fits on a single line when Foo { option: value, ..Foo::default() } always takes four 😄

@Jarema
Copy link
Member Author

Jarema commented Apr 17, 2024

Default::default() is used when you want to specify some fields for Configs, but you are happy with others being default values.

Many users prefer to use config structs rather than builders. Especially in NATS context, where its sometimes easier to look at whole config rather than a code (as this is how you often see those in cli when caling nats stream info nats consumer info etc.

That's why we went with struct variant.
However, it's of course fine to add builders as an extension in the future.
However I would like to avoid high maintenance cost of those, so probably not manual, but generated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants