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

wip crdt spec #316

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft

wip crdt spec #316

wants to merge 10 commits into from

Conversation

ripienaar
Copy link
Contributor

No description provided.

adr/ADR-48.md Outdated Show resolved Hide resolved
@derekcollison
Copy link
Member

I think integers only unless you feel we should support floats..

@ripienaar
Copy link
Contributor Author

I think integers only unless you feel we should support floats..

Seemed like no extra effort to do float so went with it.

But, pulling in some comments from the email thread here, we need to limit it to 2^53 if we are doing JSON and guard against overflow

@derekcollison
Copy link
Member

Actually a decent amount of effort actually to determine to use atoi or atof (essentially)..

@derekcollison
Copy link
Member

I am not liking the 2^53 but if we keep total as a string can be higher yes?

@aricart
Copy link
Member

aricart commented Jan 9, 2025

if you do the string yes, the 2^53 is the size from the JSON spec... as a string, libs have a chance to parse as big num or whatever they require.

@ripienaar
Copy link
Contributor Author

I am not liking the 2^53 but if we keep total as a string can be higher yes?

so what should we make the top ceiling for protection against overlflow assuming ints - int64 would be easiest else parsing becomes very annoying

@derekcollison
Copy link
Member

We could say int64 for now and learn more as we go..

@derekcollison
Copy link
Member

Or uint64 if all positive?

@ripienaar
Copy link
Contributor Author

Or uint64 if all positive?

sounds complex :) but we can move in that direction if needed, so int64 is a good start

@aricart
Copy link
Member

aricart commented Jan 9, 2025

uint64 is going to be parsed incorrectly by some JSON parser...

@derekcollison
Copy link
Member

We could chose to have the value as a string and the client lib parses it however they want. So JS/TS still has a limit but not languages with true 74bit or 128bit numbers. Doesn't JS have a big int thing now too?

@ripienaar
Copy link
Contributor Author

ripienaar commented Jan 9, 2025

Yeah JS does now have BigInt, it seems to me starting with int64 and then moving to exotic weird things later is a best option. But from the get-go value as string.

Updated ADR for that

Signed-off-by: R.I.Pienaar <[email protected]>
@aricart
Copy link
Member

aricart commented Jan 9, 2025

Otherwise it requires a custom JSON parser, to convert the numeric value to a string, and then change it. As a string, the flow can be outside of the JSON parsing which imho is better

adr/ADR-48.md Outdated

* The header holds values like `+1`, `-1` and `-10`, in other words any valid `int64`, if the value fails to parse
the message is rejected with an error. A value of `0` is valid.
* When publishing a message to the subject the last value is loaded, the body is parsed, incremented and written
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel like we need to strongly define what "the last value" is, i.e. it must be from the leader only, cannot be direct-get'd from a replica.

Also do we have to think about interactions with Nats-Expected-Last-Sequence, Nats-Expected-Subject-Last-Sequence etc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous message for the subject - this is done on the server where the message is received so would be the leader right?

We might for now reject those headers just to avoid weird things?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have marked those all as rejected and made a small clarification

adr/ADR-48.md Show resolved Hide resolved

It's important that counters can be reset to zero, in a simple standalone counter this is easily done with a subject purge. In a topology where multiple regions contribute to a total a regional reset might require a negative value to be published equal to the current total.

The preferred method for Reset should be a negative value being published followed by a purge up to the message holding the negative value, with subject purge being used only for entire counter deletes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can split the responsibilities here:

  1. Publishing negative values - a way to reset the counter.
  2. Purging - a way to clear old values.

Does solve the problem of resetting in more advanced topologies at least.

* When a message with the header is published to a Stream without the option set the message is rejected with an error
* When a message with the header is received over a Mirror the message is stored verbatim
* When a message without the header is received and the previous message is a counter this will be rejected since
the subject is then treated as being a counter only. This could be very expensive on Streams with many
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can say that Stream with Counters enabled is always counter only to substantialy reduce the cost of those checks?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, may be worth starting there, we can always relax later

@Jarema
Copy link
Member

Jarema commented Jan 13, 2025

I think this should be the first feature developed for the 2.12, and relased early for preview so we can gather feedback allowing us to improve before the API is released and cannot have breaking changes anymore.

Otherwise, we might land in a place where great feature with good design is crippled with small mistakes that could be easily avoided, making it a missed opportunity for a great user experience.

@ripienaar
Copy link
Contributor Author

I think this should be the first feature developed for the 2.12, and relased early for preview so we can gather feedback allowing us to improve before the API is released and cannot have breaking changes anymore.

Otherwise, we might land in a place where great feature with good design is crippled with small mistakes that could be easily avoided, making it a missed opportunity for a great user experience.

Very strongly agree with this

@derekcollison
Copy link
Member

So we are now saying do not try to squeeze this as alpha/beta into 2.11? Or are we agreeing put it into 2.11 as beta and 2.12 is when it becomes real?

@ripienaar
Copy link
Contributor Author

From writing the ADR I think this is not the trivial easy win we were thinking it is, especially considering sources (the place where this will really shine) we should use the 2.12 cycle - hopefully a 6 months one - to get this right and focus the remaining of our 2.11 time to get Msg TTL right. Both are very big ticket items that we must be sure to get right.

So for me, I think we need to pick this up as early / first delivery for 2.12 cycle

@Jarema
Copy link
Member

Jarema commented Jan 14, 2025

I agree with @ripienaar

If we have it in early in 2.12 preview release, it will effectively be a preview beta that we can stabilize for the 2.12 release.
No matter how we mark it for 2.11, people will use it and ship to production, making it impossible to make any necessary breaking changes and improvements.

The end result will be the same (released in 2.12), but without a risk of not being able to improve it or having serious bugs.

@derekcollison
Copy link
Member

What part is hard about sourcing?

@ripienaar
Copy link
Contributor Author

What part is hard about sourcing?

read the section here https://github.com/nats-io/nats-architecture-and-design/blob/74e0f2086be6b36031e76ef5b209d051bab3a521/adr/ADR-48.md#source-based-replicated-counters and about adding sources at runtime

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

Successfully merging this pull request may close these issues.

6 participants