DEV Community

Yeqing (Marvin) Zhang
Yeqing (Marvin) Zhang

Posted on

Go Project Source Code Analysis: Schedule Job Library "cron"

Introduction

There are many excellent open-source projects on GitHub, where the code is transparent and available to everyone. As software developer, we can learn a lot from them including software engineering, unit testing, coding style standardization, etc. We can even find issues by looking into their code, and submit pull requests to contribute to tech communities. Today we are going to dig into the source code of a popular Golang open-source project on GitHub, robfig/cron, which is small and with clear annotations, and is very suitable for new developers to learn how to read and analyze source code.

Environment Preparation

First, we are going to fork the project into our personal repo. We can do so by clicking the Fork button and enter the project name. After it's forked, we can either download to our local, or click Create codespace on master to create a Codespace on the GitHub repo's home page. Codespace is a Azure-based GitHub service that allows developers to develop remotely, and it is now available to individuals. Let's give it a try!

Create Codespace

After clicking, a new page will be opened in the browser, where there is a web interface of VS Code, displaying the directory, code and terminal of the project. See the figure below.

Codespace

As our objective is to analyze source code, we will use it to display code for reading, instead of executing it.

Now, we can start reading and analyzing.

Entry File

A good way of analyzing source code is find the entry file, which is like a book's introduction, where the overall project structure will show up.

Code Structure

We can find in README.md file that the usage of this library is something like cron.New(cron.WithSeconds()), or the method cron.New. Therefore, we reckon that this method is in the file cron.go. Let's open it and take a look.

A quick go-through can allow us to locate the New method at Line 113, as below.

Method New

If we take a close look, it is basically a pointer to the instance of the Cron struct. The parameters opts ...Option is called Functional Option. The actual implementation is to build an instance pointer c of the struct Cron, applied by functional options, and return it.

With above analysis, we can conclude that the main logic is inside the Cron struct.

Regardless to say, we can be sure that the entry file is cron.go. What we can do next is analyze the core modules of this file to fully understand the source code.

Core Struct/Class

Now let's take a look at the structure of the core struct Core to find some enlightenment.

We can locate the struct Cron at Line 13.

Cron Struct

There are quite many fields in the struct Cron, including the lower-case private attributes entries, chain, parser, but we can hardly know their actual meanings and functionalities. According to the comments at Line 10-12, we can deduct that it is used for tracking entries and executing functions defined by schedule. However, we are still not quite sure about what it does exactly, so only through reading the source code further, we can understand more details.

We can also find 3 interfaces just under beneath with their descriptions:

  • ScheduleParser: parser of the schedule, which parses specs and returns Schedule instance.
  • Job: submitted scheduled jobs.
  • Schedule: used for describing running cycles of jobs.

In fact, these 3 interfaces are very important, given their locations in the source code.

Entry Method

Before we explore further, let's recall the usage of the library apart from cron.New: it takes effect after calling c.Start(). Therefore, we need to dig into the Start method in Cron, which is actually the entry method of the core struct.

We can locate the Start method at Line 215 in cron.go as below.

Cron Start

An experienced Go developer could notice this is an atomic operation. c.runningMu is an instance of sync.Mutex, which can lock at the beginning, and unlock after the function execution finishes. This technique avoids data racing in the repeated calls of this method. if c.running { return } denotes that the method won't go further and return immediately if it's already started. c.running is set as true. The last line is an essential statement, go c.run(), meaning it starts a goroutine to asynchronously execute c.run. Now we have found the real core method, and the rest of the work is to analyze it through.

Is it similar to we playing RPG games and unlocking all the milestones and entering the next episode?

Conclusion

Wait! Is it over?

The reason why we stopped here is that I want to keep the article short. Reading and analyzing source code a tedious and boring process, which might prevent readers from going further. As a result, the objective of this article is to introduce the right and basic techniques of analyzing source code to readers, allowing you guys to do the analysis by yourselves. This way can make you learn faster and with more interest.

Now let's summarize the techniques for analyzing source code:

  1. Find the entry file
  2. Locate the core struct/class
  3. Analyze the entry method

Top comments (0)