-
Notifications
You must be signed in to change notification settings - Fork 210
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
Expanded plugin constructor capabilities #481
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.amazon.dataprepper.model.annotations; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* Add to a plugin class to indicate which constructor should be used by Data Prepper. | ||
* <p> | ||
* The current behavior for choosing a constructor is: | ||
* <ol> | ||
* <li>Choose the constructor annotated with {@link DataPrepperPluginConstructor}</li> | ||
* <li>Choose a constructor which takes in a single parameter matching | ||
* the {@link DataPrepperPlugin#pluginConfigurationType()} for the plugin</li> | ||
* <li>Use the default (ie. empty) constructor</li> | ||
* </ol> | ||
*/ | ||
@Documented | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target({ElementType.CONSTRUCTOR}) | ||
public @interface DataPrepperPluginConstructor { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package com.amazon.dataprepper.plugin; | ||
|
||
import com.amazon.dataprepper.metrics.PluginMetrics; | ||
import com.amazon.dataprepper.model.configuration.PluginSetting; | ||
import com.amazon.dataprepper.model.plugin.InvalidPluginDefinitionException; | ||
|
||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
import java.util.function.Supplier; | ||
|
||
/** | ||
* An internal class which represents all the data which can be provided | ||
* when constructing a new plugin. | ||
*/ | ||
class PluginArgumentsContext { | ||
private final Map<Class<?>, Supplier<Object>> typedArgumentsSuppliers; | ||
|
||
private PluginArgumentsContext(final Builder builder) { | ||
Objects.requireNonNull(builder.pluginSetting, | ||
"PluginArgumentsContext received a null Builder object. This is likely an error in the plugin framework."); | ||
|
||
typedArgumentsSuppliers = new HashMap<>(); | ||
|
||
typedArgumentsSuppliers.put(builder.pluginSetting.getClass(), () -> builder.pluginSetting); | ||
|
||
if(builder.pluginConfiguration != null) { | ||
typedArgumentsSuppliers.put(builder.pluginConfiguration.getClass(), () -> builder.pluginConfiguration); | ||
} | ||
|
||
typedArgumentsSuppliers.put(PluginMetrics.class, () -> PluginMetrics.fromPluginSetting(builder.pluginSetting)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this only be added if the pluginMetrics value is non null? Also, are we supporting an annotated constructor like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To answer your second question, yes, we are support that type of constructor. But, only if it is annotated with I'm not quite sure what your first question is asking. At this point of the code we are only adding a |
||
} | ||
|
||
Object[] createArguments(final Class<?>[] parameterTypes) { | ||
return Arrays.stream(parameterTypes) | ||
.map(this::getRequiredArgumentSupplier) | ||
.map(Supplier::get) | ||
.toArray(); | ||
} | ||
|
||
private Supplier<Object> getRequiredArgumentSupplier(final Class<?> parameterType) { | ||
if(typedArgumentsSuppliers.containsKey(parameterType)) { | ||
return typedArgumentsSuppliers.get(parameterType); | ||
} | ||
|
||
throw new InvalidPluginDefinitionException("Unable to create an argument for required plugin parameter type: " + parameterType); | ||
} | ||
|
||
static class Builder { | ||
private Object pluginConfiguration; | ||
private PluginSetting pluginSetting; | ||
|
||
Builder withPluginConfiguration(final Object pluginConfiguration) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is a pluginConfiguration? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is the custom configuration supplied which is the type directed by this field: https://github.com/opensearch-project/data-prepper/blob/main/data-prepper-api/src/main/java/com/amazon/dataprepper/model/annotations/DataPrepperPlugin.java#L80 |
||
this.pluginConfiguration = pluginConfiguration; | ||
return this; | ||
} | ||
|
||
Builder withPluginSetting(final PluginSetting pluginSetting) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is some nuance to how the parameters impact how the plugins are loaded. I really wish we had plugin documentation. I am worried we are going to build out the plugin documentation at the very end and miss some details. Is there any way we can start building out documentation of this framework now? It doesn't have to be perfect or finalized. Just a README in this package would be nice. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I can add this next. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have added the documentation and linked it from the Development guide. As plugin support is extended, I would like to reconsidering the linking, but I believe this is sufficient for now. |
||
this.pluginSetting = pluginSetting; | ||
return this; | ||
} | ||
|
||
PluginArgumentsContext build() { | ||
return new PluginArgumentsContext(this); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's align on align on a single name either
ConstructionContext
orPluginArguementsContext
. Changing names is difficult to follow along and implies they are somehow different.