Introduction to Amazon Code Pipeline with Java part 18: the job worker thread

Introduction

In the previous post we looked at an implementation stub for the JobProcessor interface. The implementation reflects our real life Code Pipeline third party action job process. The business specific logic has been omitted of course as that is not crucial for understanding the code. Probably the most important bit was checking whether the continuation token was present in the incoming Code Pipeline job. That was the basis for distinguishing new load tests from ongoing ones. We also saw how to indicate to CP that a job is ongoing or whether it has finished with success or failure.

In this post we’ll start looking into how to start the job checking thread.

The job worker daemon thread

If you are not familiar with daemon threads then in short they are most often used for long-running background tasks. They are started by the main thread and are then executed on their own threads which won’t block the main code execution. Imagine that all your real life actions are executed on a certain thread, like eating breakfast, watching TV, etc. They are usually performed one after the other, just like code blocks are executed one after the other in code. However, there are tasks that you only initiate, e.g. turning the heating on. You probably press a button and adjust the temperature but the heating itself will be executed by the heater and you won’t care about it as long it performs what it’s supposed to. The heating task is then executed on a daemon thread and you can go on with your other tasks without being blocked by it. You can read more about daemon threads here and here.

We are coming back to our entry point code in ServletInitiator.java we saw before. I’ve removed the stuff we’ve looked at already:

package com.apica.awscodepipelinebuildrunner;

import org.apache.commons.daemon.Daemon;
import org.apache.commons.daemon.DaemonContext;
import org.apache.commons.daemon.DaemonInitException;

public class ServletInitiator implements ServletContextListener
{   
    public void contextInitialized(ServletContextEvent sce)
    {
        final class ConsumerRunner implements Runnable
        {

            @Override
            public void run()
            {
                
                if (//properties file successfully processed)
                {
                    //code ignored
                    Daemon jobAgentDaemon = new JobWorkerDaemon(Executors.newScheduledThreadPool(1),
                            properties, new CentralLogger(properties), 
                            new LtpApiClientTokenProvider(codePipelineService), jobProcessor);
                    DaemonContext jobAgentDaemonContext = new DaemonLoader.Context();

                    try
                    {
                        jobAgentDaemon.init(jobAgentDaemonContext);
                        jobAgentDaemon.start();
                    } catch (Exception ex)
                    {
                        //exception handling and logging
                    }
                } else
                {
                    //exception handling and logging
                }
            }
        }
        try
        {
            Thread t = new Thread(new ConsumerRunner());
            t.start();
        } catch (Exception ex)
        {
             //exception handling and logging
        }
    }
}

The Daemon interface comes from the org.apache.commons.daemon package and represents a daemon thread. It has 4 methods related to thread handling: init, start, stop and destroy that are all called at the corresponding stages in the thread lifetime.

Our implementation of Daemon, i.e. JobWorkerDaemon has a number of dependencies:

  • An executor service of type ScheduledExecutorService. It is used to execute tasks periodically which comes very handy when checking for new jobs at CP. You can read more about this executor service type here.
  • The properties extracted before reaching this point in the code
  • The logging service which is not relevant for our main discussion
  • The client token provider which will read the client token from the back end store based on the client ID
  • A job processor which we saw in the previous post

We then construct an empty daemon context object which is used in the init method of Daemon. Finally we start the daemon thread in the overridden run method of the ConsumerRunner class. The last action in the contextInitialized method of ServletContextListener is to start the consumer runner thread.

We have covered a lot of ground in this series so far but there’s still quite a bit to go before we have the full picture. In the next post we’ll look at the JobWorkerDaemon class which in turn will lead to a lot of other components as well.

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 )

Twitter picture

You are commenting using your Twitter 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: