-
Notifications
You must be signed in to change notification settings - Fork 4
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
feat(plugins): filled in scaffolding #11
base: master
Are you sure you want to change the base?
Conversation
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.
I probably know all of this, deep in my brain, but I was initially confused by what's happening in this PR so let me describe what I'm seeing and you can either confirm or deny. It seems like we're deviating from what the API is today and defining a new API for building stages in a plugin. I just want to make sure I'm on the same page.
Users who build a plugin stage will implement the Stage
interface, which has an execute
method. At runtime, every one of these stages will be registered with the StageResolver
after being turned into an ApiStageDefinitionBuilder
.
The ApiStageDefinitionBuilder
will build a taskGraph
with a single ApiTask
which introspects the type required by the execute
method, converts the context to the appropriate type and calls the execute
method, passing in the desired type.
Am I correct in assuming that we're moving away from stages being composed of multiple task classes and opting for a single API execute
which does everything? It seems that moving in this direction will cause us to lose the benefits of having multiple tasks like being able to use RetryableTask
to retry a subset of operations within a stage or inject tasks depending the presence or absense of context values. From a UX perspective this is definitely simpler, so that's a plus!
StageInput stageInput = | ||
new StageInput( | ||
objectMapper.convertValue( | ||
stage.getContext(), GenericTypeResolver.resolveType(type, typeVariableMap))); |
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.
So, the idea here is that I can have a StageInput
class which looks like
public class MyPluginStageInput extends StageInput {
public String foo;
}
and use it as my stage input like so
public execute(MyPluginStageInput input) {}
Is this correct?
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.
One would create a new class like:
public class MyPluginStageInput {
}
and then in their new stage do:
public class MyStage implements Stage<MyPluginStageInput> {
@Override
public <MyPluginStageInput> StageOutput execute(StageInput<MyPluginStageInput> stageInput) {
Class[] cArg = new Class[1]; | ||
cArg[0] = StageInput.class; | ||
Method method = apiStage.getClass().getMethod("execute", cArg); | ||
Type type = ResolvableType.forMethodParameter(method, 0).getGeneric().getType(); |
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.
Small nit: imight be a bit more descriptive to use inputType
instead of type
for this variable name.
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.
👍
status = ExecutionStatus.TERMINAL; | ||
} | ||
|
||
return TaskResult.ofStatus(status); |
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.
Don't we want to throw the outputs of the stage back into the context here? This would allow us to use any outputs from the stage in downstream stages.
TaskResult.builder(status).context(outputs.getOutputs()).outputs(outputs.getOutputs()).build();
ExecutionStatus status; | ||
try { | ||
Class[] cArg = new Class[1]; | ||
cArg[0] = StageInput.class; |
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.
You can do Arrays.asList
to clean this up.
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.
supa smooth! 🚢
@@ -0,0 +1,61 @@ | |||
/* | |||
* Copyright 2019 Netflix, Inc. |
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.
s/Netflix/Armory/
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.
woops! nice catch
|
||
then: | ||
results.getStatus() == ExecutionStatus.SUCCEEDED | ||
results.getContext()["hello"] == "world" |
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.
The tiniest of nits - you just do results.context.hello
since this is Groovy.
import com.google.common.annotations.Beta; | ||
|
||
@Beta | ||
public interface Stage<T> { |
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.
I'm not a fan of duplicated class name. It hurts readability and increases complexity by having to determine which type of Stage object you're working with.
No description provided.