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

feat(plugins): filled in scaffolding #11

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open

Conversation

bpowell
Copy link

@bpowell bpowell commented Aug 9, 2019

No description provided.

@bpowell bpowell changed the base branch from plugins-scaffolding to master August 12, 2019 23:53
Copy link

@ethanfrogers ethanfrogers left a 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)));

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?

Copy link
Author

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();

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.

Copy link
Author

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);

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;

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.

Copy link

@ethanfrogers ethanfrogers left a 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.

Choose a reason for hiding this comment

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

s/Netflix/Armory/

Copy link
Author

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"

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> {
Copy link
Member

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.

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