Introduction to Amazon Code Pipeline with Java part 16: the WorkResult object

Introduction

In the previous post we looked at the job processor interface of the Code Pipeline third party action job agent. The job processor is responsible for processing a new job item returned by polling a Code Pipeline endpoint. The interface has a single method called process which accepts a WorkItem object and returns a WorkResult object. We discussed the WorkItem object in detail. In this post we’ll go through the WorkItem object.

The WorkResult object ingredients

The WorkResult object represents the result of processing a work item. A work result can be a success or a failure. There are currently no other modes available in CP. A job either succeeds or fails, there are no intermediate results such as “warning”.

Before we go through the work result object code let’s look at a couple of constituent objects that are used in WorkResult.

First off we have a simple Validator class that checks for null values:

package com.apica.awscodepipelinebuildrunner;

public final class Validator
{
    public final static void notNull(final Object obj)
    {
        if (obj == null)
        {
            throw new IllegalArgumentException("Object is null");
        }
    }
}

The work item statuses are represented by the WorkResultStatus enumeration:

package com.apica.awscodepipelinebuildrunner.model;

public enum WorkResultStatus
{    
    Success,    
    Failure
}

The ExecutionDetails object holds a couple of values describing the result of the work item:

package com.apica.awscodepipelinebuildrunner.model;

public class ExecutionDetails
{

    private final String summary;
    private final String externalExecutionId;
    private final int percentComplete;

    public ExecutionDetails(final String summary, final String externalExecutionId, final int percentComplete)
    {
        this.summary = summary;
        this.externalExecutionId = externalExecutionId;
        this.percentComplete = percentComplete;
    }

    public String getSummary()
    {
        return summary;
    }

    public String getExternalExecutionId()
    {
        return externalExecutionId;
    }

    public int getPercentComplete()
    {
        return percentComplete;
    }
}

We can provide a summary that describes the job result using the summary parameter. We have to return the job id, denoted by the externalExecutionId parameter, so that CP can find the job. Finally we can indicate the progress on a scale of 0% to 100% where 100 means that a job is complete and CP should consider the job as done. Anything below means that the job is still in progress and CP should keep sending signals with the continuation token.

The CurrentRevision object allows us to describe a revision and a change identifier for the work result:

package com.apica.awscodepipelinebuildrunner.model;
import com.apica.awscodepipelinebuildrunner.Validator;
public class CurrentRevision
{

    private final String revision;
    private final String changeIdentifier;

    public CurrentRevision(final String revision, final String changeIdentifier)
    {
        Validator.notNull(revision);
        Validator.notNull(changeIdentifier);
        this.revision = revision;
        this.changeIdentifier = changeIdentifier;
    }

    public String getRevision()
    {
        return revision;
    }

    public String getChangeIdentifier()
    {
        return changeIdentifier;
    }
}

Finally we have a FailureDetails object where we can provide some details around a failure:

package com.apica.awscodepipelinebuildrunner.model;

import com.apica.awscodepipelinebuildrunner.Validator;

public class FailureDetails
{
    private final FailureType type;
    private final String message;

    public FailureDetails(final FailureType type)
    {
        Validator.notNull(type);
        this.type = type;
        this.message = null;
    }

    public FailureDetails(final FailureType type, final String message)
    {
        Validator.notNull(type);
        this.type = type;
        this.message = message;
    }

    public FailureType getType()
    {
        return type;
    }

    public String getMessage()
    {
        return message;
    }
}

…where FailureType is an enumeration for the various failure types:

package com.apica.awscodepipelinebuildrunner.model;

public enum FailureType
{
    /**
     * Generic job failed error.
     */
    JobFailed,
    /**
     * Configuration error,
     * e.g. wrong action configuration.
     */
    ConfigurationError,
    /**
     * Permissions error,
     * e.g. caller has no access to the given resource.
     */
    PermissionError,
    /**
     * Revision has changed and is not the expected one.
     */
    RevisionOutOfSync,
    /**
     * No revision has been provided.
     */
    RevisionUnavailable,
    /**
     * System is temporarily not available.
     */
    SystemUnavailable
}

The WorkResult object

Now that we’ve seen the ingredients we can finally look at the final product. The WorkResult object is really nothing more than a container for the above objects and a number of static methods that help build a WorkResult object such as various success and failure results:

package com.apica.awscodepipelinebuildrunner.model;

import com.apica.awscodepipelinebuildrunner.Validator;

public class WorkResult
{

    private final String jobId;
    private final WorkResultStatus status;
    private final ExecutionDetails executionDetails;
    private final CurrentRevision currentRevision;
    private final String continuationToken;
    private final FailureDetails failureDetails;

    private WorkResult(final String jobId,
            final ExecutionDetails executionDetails,
            final CurrentRevision currentRevision,
            final String continuationToken)
    {
        Validator.notNull(jobId);
        this.jobId = jobId;
        this.status = WorkResultStatus.Success;
        this.executionDetails = executionDetails;
        this.currentRevision = currentRevision;
        this.continuationToken = continuationToken;
        this.failureDetails = null;
    }

    private WorkResult(final String jobId, final FailureDetails failureDetails)
    {
        Validator.notNull(jobId);
        Validator.notNull(failureDetails);
        this.jobId = jobId;
        this.status = WorkResultStatus.Failure;
        this.executionDetails = null;
        this.currentRevision = null;
        this.continuationToken = null;
        this.failureDetails = failureDetails;
    }

    public String getJobId()
    {
        return jobId;
    }

    public WorkResultStatus getStatus()
    {
        return status;
    }

    public ExecutionDetails getExecutionDetails()
    {
        return executionDetails;
    }

    public CurrentRevision getCurrentRevision()
    {
        return currentRevision;
    }

    public String getContinuationToken()
    {
        return continuationToken;
    }

    public FailureDetails getFailureDetails()
    {
        return failureDetails;
    }

    public static WorkResult success(final String jobId)
    {
        return new WorkResult(jobId, null, null, null);
    }

    public static WorkResult success(final String jobId,
            final ExecutionDetails executionDetails)
    {
        return new WorkResult(jobId, executionDetails, null, null);
    }

    public static WorkResult success(final String jobId,
            final ExecutionDetails executionDetails,
            final CurrentRevision currentRevision)
    {
        return new WorkResult(jobId, executionDetails, currentRevision, null);
    }
   
    public static WorkResult success(final String jobId,
            final ExecutionDetails executionDetails,
            final CurrentRevision currentRevision,
            final String continuationToken)
    {
        return new WorkResult(jobId, executionDetails, currentRevision, continuationToken);
    }

    public static WorkResult failure(final String jobId, final FailureDetails failureDetails)
    {
        return new WorkResult(jobId, failureDetails);
    }
}

In the next post we’ll look at an implementation of the JobProcessor interface.

View all posts related to Amazon Web Services and Big Data here.

Advertisement

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: