Executing infinite and repeating jobs using a worker pool in Go

Ovadiah Myrgorod
3 min readMay 8, 2019

Before I started writing this blog post, I had been trying to find a good example for my task using these search queries: “infinite queue in Golang”, “endless generator in Go”, “Go job scheduler” but nothing useful came up, so I decided to develop my own approach.

Problem

In my task I need to schedule N jobs to be executed repeatedly in the background with some specific requirements:

  • N jobs are added to the job queue upon the Go program start.
  • Jobs should be executed in parallel pool of M workers.
  • A distinct job can only be executed once at a time.
  • As soon as a job is done it should be pushed to the end of the job queue.
  • A distinct job execution should be scheduled at intervals no less than T.

Solution

The basic idea behind the solution is to make sure workers add completed jobs back to the queue. There is a complication, however, which makes a worker to check for an interval requirement based upon the last time a job has started. In case if an interval requirement is met, a worker should run a job, otherwise it will be skipped.

Implementation

The following code is well documented, however there are some important details:

  • sync.Map is used to prevent race conditions when checking for interval requirements. It works similarly to the regular hash map, but it implements mutex feature when reading or writing.
  • In case if job is declined because of the interval requirement, I am running time.Sleep function for a tenths of interval time to prevent extensive usage of channels. Otherwise job ids will be pop out and in to the queue without any payload.

The logic of the code can be improved a bit in case if worker func is split into worker and scheduler, however it can significantly increase the code size.

Results and interpretation

Given there are five jobs, first job takes 1 second to run, second job takes 2 seconds to run, third takes 3 seconds, etc… Also there are three workers and the minimal interval is equal to 6 seconds. Jobs will run as depicted on the image below.

If we change the minimal interval to 2 seconds, jobs will be run more often as shown on the following picture.

As we can see, jobs that take small amount of time to run are idling more, while time intensive jobs are eating away pool resources. This could lead to the case when relatively small amount of jobs would block the pool for quite a long time. To fix it, simply increase amount of workers and/or decrease minimal interval.

--

--

Ovadiah Myrgorod

Welcome to the day that makes it a good day everyday!