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

[Extensions] Create writeable implementations for parser #5838

Closed
wants to merge 77 commits into from

Conversation

mloufra
Copy link
Contributor

@mloufra mloufra commented Jan 11, 2023

Signed-off-by: Frank Lou [email protected]

Description

Create writeable implementations for parser that implement both Function<String, T> and Writeable interfaces for all existing setting implementations that use parsers.

Issues Resolved

Fixes opensearch-project/opensearch-sdk-java#349

Check List

  • New functionality includes testing.
    • All tests pass
  • New functionality has been documented.
    • New functionality has javadoc added
  • Commits are signed per the DCO using --signoff
  • Commit changes are listed out in CHANGELOG.md file (See: Changelog)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

  • RESULT: null ❌
  • URL: null
  • CommitID: 0a285d2
    Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green.
    Is the failure a flaky test unrelated to your change?

Copy link
Member

@dbwiddis dbwiddis left a comment

Choose a reason for hiding this comment

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

Good intuition to pass the min and max values.

Unfortunately we don't save the min and max values anywhere in the Setting object so at the moment this is impossible to do inside WriteableSetting without modifying Setting.

I've left one idea in the comments, there may be other ways to do it as well.

@@ -191,6 +284,8 @@ public void writeTo(StreamOutput out) throws IOException {
out.writeString(setting.getKey());
// Write the default value
writeDefaultValue(out, setting.getDefault(Settings.EMPTY));
// not sure we need to write out the min and max value
// writeMinValue(out, minValue);
Copy link
Member

@dbwiddis dbwiddis Jan 12, 2023

Choose a reason for hiding this comment

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

Anything that you want to read in, you need to write out, so yes you'll somehow need to write the min and max value.

The problem is that when we create a setting we don't save the min and max value so you don't have them, except as stored internally in the private final Function<String, T> parser, which is not writeable.

So you are going to have to go into the Setting class and find where the setting is created, like this for double (similar for other number types):

    public static Setting<Double> doubleSetting(
        String key,
        Setting<Double> fallbackSetting,
        double minValue,
        double maxValue,
        Validator<Double> validator,
        Property... properties
    ) {
        return new Setting<>(
            new SimpleKey(key),
            fallbackSetting,
            fallbackSetting::getRaw,
            (s) -> parseDouble(s, minValue, maxValue, key, isFiltered(properties)),
            validator,
            properties
        );
    }

and replace the function (s) -> parseDouble(s, minValue, maxValue, key, isFiltered(properties)) with something that is writeable.

Here's one idea, you might think of a better one:

public class DoubleParser implements Function<String, T>, Writeable { ... } 

The Function interface will require you implement a method T apply(String s) (the equivalent of the (s) -> ... method that returns T ... syntax) where you would use that parseDouble method. You could instantiate the class with a constructor containing the minValue, maxValue, key, and boolean filtered, and create a new DoubleParser in the above code.

The Writeable interface will require the writeTo() method where you can pass those min/max, key, and filtered values.

Then here, instead of writeMinValue and writeMaxValue you would just write the parser, which would embed the min, max, key, and filtered values.

One great benefit of this approach is it keeps the existing Setting API and gives users ideas/examples of other parsing functions they can include, as long as they are Writeable.

@@ -147,26 +153,113 @@ private Setting<?> createSetting(
? Setting.boolSetting(key, (boolean) defaultValue, propertyArray)
: Setting.boolSetting(key, (Setting<Boolean>) fallback.getSetting(), propertyArray);
case Integer:
if (minValue != null && maxValue != null) {
Copy link
Member

Choose a reason for hiding this comment

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

Since you haven't implemented the write portion, I don't know when or if you'd get null. But I think for most of these numbers there are MIN_VALUE for a default min, and MAX_VALUE for a default max, that you will always have a value for it and not have to handle nulls.

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

import org.opensearch.common.settings.Setting.Property;
import org.opensearch.common.settings.Setting.Validator;

public class DoubleParser<T> implements Function<String, T>, Writeable {
Copy link
Member

Choose a reason for hiding this comment

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

If you make DoubleParser an inner class inside Setting, then:

  • You won't need to include the generic type <T> here
  • You will automatically gain access to the parseDouble() method inside the Setting class so you don't have to recreate it yourself. That will really simplify the rest of your implementation!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree, I will make DoubleParser as an inner class inside Setting


public class DoubleParser<T> implements Function<String, T>, Writeable {
private Setting<Double> setting;
private Double minValue;
Copy link
Member

Choose a reason for hiding this comment

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

The min and max can probably be primitive double

private Setting<Double> setting;
private Double minValue;
private Double maxValue;
private Double fallback;
Copy link
Member

Choose a reason for hiding this comment

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

Fallback is a Setting<T>

private Double maxValue;
private Double fallback;

public DoubleParser(Setting<Double> setting) {
Copy link
Member

Choose a reason for hiding this comment

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

I don't think you need this constructor at all

// Read the max value
this.maxValue = in.readDouble();
// Read the fallback
boolean hasFallback = in.readBoolean();
Copy link
Member

Choose a reason for hiding this comment

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

I think trying to implement this outside the Setting class is overcomplicating things. Don't worry about the fallbacks for now. Just focus on replacing the Function<String, T> parser argument ((s) -> parseDouble(s, minValue, maxValue, key, isFiltered(properties))) with an object.

return new Setting<Double>(
key,
Double.toString(defaultValue),
(s) -> doubleParser(s, minValue, maxValue, key, isFiltered(properties)),
Copy link
Member

Choose a reason for hiding this comment

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

this isn't really improving on the existing implementation, you're putting a non-Writeable object here for the parser. The whole goal of what you are doing is to have new Setting<Double>( ... writeableParser argument ... ). That way when you send WriteableSetting over transport you can just do parser.writeTo(out).

return properties != null && Arrays.asList(properties).contains(Property.Filtered);
}

private static double doubleParser(String s, double minValue, double maxValue, String key, boolean isFiltered) {
Copy link
Member

Choose a reason for hiding this comment

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

Java principle: DRY (Don't Repeat Yourself). Use the existing method in Settings object. If it's private, you can just make DoubleParser an inner class and it will have access to it.

public class Setting<T>  ... {
    public class DoubleParser ... { ... }
}


@Override
public T apply(String s) {
// TODO Auto-generated method stub
Copy link
Member

Choose a reason for hiding this comment

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

This apply() is what implements parseDouble, the right hand side of the (s) -> parseDouble(s, minValue, maxValue, key, isFiltered(properties)). The (s) is the parameter.

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

  • RESULT: UNSTABLE ❕
  • TEST FAILURES:
      1 org.opensearch.snapshots.DedicatedClusterSnapshotRestoreIT.testIndexDeletionDuringSnapshotCreationInQueue
      1 org.opensearch.indices.replication.SegmentReplicationIT.testStartReplicaAfterPrimaryIndexesDocs

@mloufra mloufra changed the title [Extensions] Add min and max value for default value [Extensions] Create writeable implementations for parser Jan 23, 2023
@mloufra mloufra marked this pull request as ready for review January 23, 2023 20:24
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
Signed-off-by: Frank Lou <[email protected]>
@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

  • RESULT: UNSTABLE ❕
  • TEST FAILURES:
      1 org.opensearch.snapshots.DedicatedClusterSnapshotRestoreIT.testIndexDeletionDuringSnapshotCreationInQueue

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

Signed-off-by: Frank Lou <[email protected]>
@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@mloufra mloufra closed this Feb 17, 2023
@mloufra
Copy link
Contributor Author

mloufra commented Feb 17, 2023

Open another PR to keep the PR commit clean. Here is the link.

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.

[FEATURE] Create writeable implementations for parser
5 participants