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

Java: validate initial hosts, configuration and nodes loaded from API #45

Merged
merged 1 commit into from
Nov 19, 2024

Conversation

dkropachev
Copy link
Collaborator

Changes:

  1. Store nodes and URI, not as string
  2. Do validation on initial nodes list and on nodes list it reads from API
  3. Don't do AlternatorLiveNodes.start when it is created
  4. Implement AlternatorLiveNodes.validate to check if it is configured properly

@dkropachev dkropachev force-pushed the dk/java-validate-hosts branch 2 times, most recently from 3159dc9 to 2a542a6 Compare November 15, 2024 03:06
@dkropachev dkropachev changed the title Java: prevalidate hosts on constructor and when nodes are loaded from API Java: validate initial hosts, configuration and nodes loaded from API Nov 15, 2024
@dkropachev dkropachev force-pushed the dk/java-validate-hosts branch from 2a542a6 to a0f4b6d Compare November 15, 2024 03:09
@dkropachev dkropachev requested review from nyh and Bouncheck November 15, 2024 03:38
@dkropachev dkropachev force-pushed the dk/java-validate-hosts branch 2 times, most recently from 59aacea to 23dfc62 Compare November 18, 2024 02:07
@dkropachev
Copy link
Collaborator Author

@nyh, @Bouncheck , could you please take a look at it.

Copy link

@Bouncheck Bouncheck left a comment

Choose a reason for hiding this comment

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

I think comments and loggers definitely should be updated.
Other stuff is suggestions.

Comment on lines 54 to 55
// A private constructor. Use the create() functions below instead, as
// they also start the thread after creating the object.

Choose a reason for hiding this comment

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

Seems no longer up to date. There should be comments about the usage of the new API.
Also should we be removing the old API? I don't know how many people use this and how big of a deal would that be.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Removed, it is not a library, user jsut copy paste it, so no problem there.

@@ -26,16 +27,21 @@ public class AlternatorLiveNodes extends Thread {
private final String alternatorScheme;
private final int alternatorPort;

private final AtomicReference<List<String>> liveNodes;
private final AtomicReference<List<URI>> liveNodes;
private final List<String> initialNodes;
private final AtomicInteger nextLiveNodeIndex;

private static Logger logger = Logger.getLogger(AlternatorLiveNodes.class.getName());

@Override
public void run() {
logger.log(Level.INFO, "AlternatorLiveNodes thread starting");

Choose a reason for hiding this comment

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

With start() overridden I think this log line should be there instead. It's slightly misleading.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Changed log message and added end message.

return create(uri.getScheme(), Arrays.asList(uri.getHost()), uri.getPort());

@Override
public void start() {

Choose a reason for hiding this comment

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

While I don't see any errors I'm not sure if it's a common practice to override start. May be confusing to read in the future, but I don't really know what's the general consensus about that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What would you recommend ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Can we leave it as it is ?

Choose a reason for hiding this comment

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

I'd keep most of the initialization in constructor and run() and here I'd just log that the thread is starting.

Choose a reason for hiding this comment

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

Can we leave it as it is ?

If it works then it's probably fine. I would not want to block further work

liveNodes = AlternatorLiveNodes.create(seedURI);
liveNodes = new AlternatorLiveNodes(seedURI);
try {
liveNodes.validate();

Choose a reason for hiding this comment

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

I think it would be nicer if user could not use AlternatorLiveNodes without passing validation. Someone working on this repo later may not notice that he should call .validate() after creation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Make sense, but AlternatorLiveNodes is auxiliary code, not supposed used by user directly.
I would not want to constructor or start to throw an exceptions, keep everything separate, so that it would be easier to test it later.

@dkropachev dkropachev force-pushed the dk/java-validate-hosts branch from 23dfc62 to cd255cc Compare November 19, 2024 16:32
Copy link

@Bouncheck Bouncheck left a comment

Choose a reason for hiding this comment

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

I don't spot anything breaking. It's probably ok if the functionality remains the same.

return create(uri.getScheme(), Arrays.asList(uri.getHost()), uri.getPort());

@Override
public void start() {

Choose a reason for hiding this comment

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

I'd keep most of the initialization in constructor and run() and here I'd just log that the thread is starting.

return create(uri.getScheme(), Arrays.asList(uri.getHost()), uri.getPort());

@Override
public void start() {

Choose a reason for hiding this comment

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

Can we leave it as it is ?

If it works then it's probably fine. I would not want to block further work

@dkropachev dkropachev merged commit a2fbd8f into scylladb:master Nov 19, 2024
1 check passed
@@ -26,69 +27,115 @@ public class AlternatorLiveNodes extends Thread {
private final String alternatorScheme;
private final int alternatorPort;

private final AtomicReference<List<String>> liveNodes;
private final AtomicReference<List<URI>> liveNodes;
private final List<String> initialNodes;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm late to review this PR, but I don't understand some of the changes here. Here in particular - why would we want to save initialNodes forever? We only use the initial list in the constructor, and that's it. Saving initialNodes forever - potentially a week after initialization - suggestion we have some logic that goes back to initialNodes (e.g., in case we lost all the nodes in the cluster, or something)... But - do we have such logic? We don't, as far as I know.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We would want to postpone validation, since initial live nodes are strings and liveNodes are URIs.
In next PR we going to switch all of them to URIs, but we still need this validation, because we would want to make sure that URI to URL conversion works flawlessly, while URI is relax regarding scheme definition URL is more strict, so we would want to be sure that error is not happening at runtime, only on configuration stage.

Copy link
Contributor

Choose a reason for hiding this comment

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

But why "postpone validation"? Why shouldn't the constructor validate its options? It is perfectly normal for a Java constructor to validate its parameters and throw an exception if they are invalid.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I would say both cases normal, but having it separately allows you more flexibility, smaller bricks makes it easier to build what you want.
Say customer whants to reuse it in their repo, and they build a classes first and only then validate their configuration.
Now, if your class does validation when classes is being built, there is no good way to do that.
While if you have it separate, you can do it whenever you want.

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.

3 participants