Chapter 42. Automating Workflow Using Job Scheduling

 

Just because you don’t know a technology, doesn’t mean you won’t be called upon to work with it.

 
 --Mike Bongiovanni

Job scheduling has become an increasingly important role of computers. They are most effective at automatically carrying out the scheduled routines of an organization. Some analysts believe that the level of job scheduling and process automation is altering the way workflow and business is done today. In actuality, the level of automation used within software products or workflow pipelines is a result of the growing needs of the industry. The industry is largely responsible for the increased reliance on enhanced process automation, not the technology itself.

Some common applications for job scheduling include report generation, batch conversion or compression of game assets, nightly system backups of source code and game assets, and moving concept art from the “completed” folder on one artist’s machine into the “to be modeled” folder on another artist’s machine. The possibilities for this technology and how it relates to workflow enhancement are nearly limitless.

There are a variety of job scheduling systems on the market that all support an exhausting number of features, but essentially there are two fundamental components: job and scheduler.

A job can be defined as a unit of work orchestrated by a computer to perform a task in an automated fashion. Multiple jobs can be composed together to form a larger workflow process, or they can operate independently of each other. Jobs can be run at a specific date and time or on a reoccurring basis specified by a time span interval.

The job scheduler is typically responsible for the continuous monitoring and notification of processes and event-driven jobs, scheduling of operational reports, and the monitoring of performance. Jobs are registered with the scheduler, and it is the duty of the scheduler to provide the mechanism that ensures the orderly and timely processing of the jobs at the time or interval specified.

Most of the leading scheduling systems provide a graphical user interface that offers a single point of control for a distributed environment of processes. This chapter addresses the development of a reusable core framework that offers a flexible mechanism for generic job scheduling.

Benefits

Most companies have a multitude of processes and workflows that define how their business operates. There are some significant benefits that result from the integration of all the disparate processes into a cohesive and automated workflow.

It is a commonly known fact that an automated process will be more reliable and less prone to error than a human operator. The less time required from human effort to perform a particular task will free that human effort for assignment to more thought-intensive problems, resulting in a considerable cost savings.

Another benefit is the increase in productivity. Almost every software company, especially within the gaming industry, is faced with the dilemma that product development must be crunched into a seemingly impossible time span. Batch processing and workflow automation allow for an increase in the amount of work performed in a shorter period of time.

Aside from the financial and increased resource gains, there are a number of operational and quality assurance benefits that result from automation. Human effort is prone to errors, whereas a properly configured computerized job will execute in the same manner every time it is run, reducing the probability of error.

Solution Goals

It may seem silly, but the key goal of the solution is to support the automation of processes. The user should be able to define a job, register the job within the scheduler, and feel confident that the process will be executed at the appropriate time.

Earlier, workflow management was discussed as a common application for job scheduling, but this chapter is meant to focus on the technology behind the scheduling itself, not business process or workflow. Near the end of the chapter, some goals are discussed that would be applicable to a scheduling system that managed workflow.

The solution must also ensure that data is efficiently processed in a generic manner. Each job performs a different role, but the core functionality remains the same. The framework must provide a mechanism to pass arbitrary data through a job efficiently.

Two job scheduling modes are available: exact and time span. The exact mode specifies a specific date and time that a job will be executed. The job will fire once and then be promptly removed from the scheduler. The time span mode specifies an interval at which a job will be executed on a recurring basis.

Implementation

The namespaces used in the implementation are very simple, shown with the following code. Be sure to reference System.Timers so that you have access to the .NET Timer object.

using System;
using System.Timers;

As outlined in the solution goals, the core framework will support two different scheduling modes. The following enumeration will be used within the job and scheduler components to distinguish between the two modes.

public enum ScheduleMode
{
    Exact,
    Span
}

The following class implements the event arguments that are passed in the event handler when a job is executed.

public class JobTriggeredEventArgs : EventArgs
{
    private ScheduleMode _mode;
    private Object _userData;
    public ScheduleMode Mode
    {
        get { return _mode; }
    }

    public Object UserData
    {
        get { return _userData; }
    }

    public JobTriggeredEventArgs(ScheduleMode mode, Object userData)
    {
        _mode = mode;
        _userData = userData;
    }
}

The following class implements the functionality behind a job and the timing mechanism that controls it.

public abstract class JobBase
{
    private ScheduleMode   _mode;
    private Timer          _jobTimer;
    private Object         _userData;
    private Scheduler      _schedule;

    protected JobBase(Scheduler schedule, ScheduleMode mode)
    {
        _schedule = schedule;
        _mode = mode;
    }

    public Timer JobTimer
    {
         get { return _jobTimer; }
         set { _jobTimer = value; }
    }

    public ScheduleMode Mode
    {
        get { return _mode; }
    }
    public object UserData
    {
        get { return _userData; }
        set { _userData = value; }
    }

    internal void ElapsedInterval(object sender, ElapsedEventArgs e)
    {
        if (Triggered != null)
            Triggered(sender, new JobTriggeredEventArgs(_mode, _userData));

        _schedule.Trigger(_mode, _userData);

        if (_mode.Equals(ScheduleMode.Exact))
        {
            _schedule.Remove(_userData);
        }
     }

     public event EventHandler<JobTriggeredEventArgs> Triggered;
}

The following class describes a job that occurs at a specific date and time.

public class JobExact : JobBase
{
    public JobExact(Scheduler schedule,
                    DateTime startTime,
                    DateTime finishTime)
        : base(schedule, ScheduleMode.Exact)
    {
        TimeSpan period = finishTime - startTime;

        base.JobTimer = new Timer(period.TotalMilliseconds);
        base.JobTimer.Elapsed += new ElapsedEventHandler(ElapsedInterval);
        base.JobTimer.AutoReset = false;
    }
}

The following class describes a job that occurs at a recurring interval.

public class JobSpan : JobBase
{
    public JobSpan(Scheduler schedule, TimeSpan interval)
        : base(schedule, ScheduleMode.Span)
    {
        base.JobTimer = new Timer(interval.TotalMilliseconds);
        base.JobTimer.Elapsed += new ElapsedEventHandler(ElapsedInterval);
        base.JobTimer.AutoReset = true;
    }
}

The final step in implementing a job scheduler is to develop the scheduling component itself. At this point, we have two different flavors of jobs that can be registered: jobs that execute at a particular date and time and jobs that can execute at a given interval on a recurring basis. Basically, each JobBase object has an internal timer that is configured for the job, and it is the responsibility of the scheduler to manage the timers and track all registered jobs. While relatively simple, the scheduler is an important part of an automation system. The following code describes the implementation of the scheduler in its entirety.

using System;
using System.Collections.Generic;

public class Scheduler : IDisposable
{
    private SortedList<Object, JobBase> _jobList;

    public SortedList<Object, JobBase> JobList
    {
        get { return _jobList; }
    }

    public Scheduler()
    {
        _jobList = new SortedList<Object, JobBase>();
    }
    public void Add(object key, JobBase job)
    {
        try
        {
           _jobList.Add(key, job);
           job.UserData = key;
           job.JobTimer.Start();
       }
        catch (Exception exception)
        {
             System.Diagnostics.Debug.WriteLine(exception.Message);
             throw;
        }
    }
    public void Remove(object key)
    {
        _jobList[key].JobTimer.Dispose();
        _jobList.Remove(key);
    }
    public JobBase this[object key]
    {
        get { return _jobList[key]; }
        set { _jobList[key] = value; }
    }
    public void Trigger(ScheduleMode mode, Object userData)
    {
        if (Triggered != null)
        {
            Triggered(this, new JobTriggeredEventArgs(mode, userData));
        }
    }
    public void IDisposable.Dispose()
    {
        foreach (JobBase job in _jobList.Values)
        {
            job.JobTimer.Dispose();
        }
    }
    public event EventHandler<JobTriggeredEventArgs> Triggered;
}

Conclusion

In this chapter, I discussed the need for job scheduling, some common uses for it, and how to implement a framework that provides enough of a mechanism to create jobs and register them within a scheduler for execution. At the beginning of this chapter, it was stated that all scheduling systems have jobs and a scheduler, no matter what other enhancements or “cool features” are included. Some systems support a transaction layer that can recover from a job failure and, in some cases, can even restart the job!

You may also be wondering what type of harness is needed to control the job system, and typically a Windows service would do the job nicely. Building a Windows service is beyond the scope of this chapter, but it would be ideal to place the code for your job manager within such a service.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.131.10