Go Project Source Code Analysis: Schedule Job Library "cron"
Yeqing (Marvin) Zhang
Posted on November 12, 2022
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!
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.
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.
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.
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.
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 returnsSchedule
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.
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:
- Find the entry file
- Locate the core struct/class
- Analyze the entry method
Posted on November 12, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.