setInterval() and the 32 bit debacle.
Tags: opensource, javascript, webdev
Published: 2021-10-31 14:02:22

## Backstory
I first set out at the start of October to complete 4 Pull Requests for Hacktoberfest. My initial research led me to a tool called "Colorette" which is a CLI tool for coloring terminal output. I really wanted to work on this repository, but before I could implement my proposed issue fix, someone had swooped in and merged a PR in my place.

Afterwards, a nice contributor to the project named [kibertoad](https://github.com/kibertoad) saw this happen and asked if I wanted to come work on his [scheduling tool](https://github.com/kibertoad/toad-scheduler). I said sure, and off we went. There were very few issues in the repo because the tool had been tested well.

However, [one key issue remained](https://github.com/kibertoad/toad-scheduler/issues/24). ***setInterval()***.

## setInterval()? What's the problem?
You may think: "setInterval()? I've used that 1 million times no problem." and you would be right. The issue with setInterval() as we learned through the project is a problem with the JavaScript language itself. 

The value for setInterval is held in a 32 bit signed integer. Most times, the maximum is never exceeded because setInterval() is mainly used for executing tasks closer together. In our case however, it was discovered that because we are making a scheduling tool, someone may actually want to schedule a task for ***30 days***, when the limit is ***24.855 days.***

## Constructor Fixing
Initially when creating a job and task with a schedule of 30 days, the tool would crash with a NodeJS error about the limit. In order to fix this, a lot of checking, delaying, and time-tracking had to be implemented in the constructor.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s48fz1mgywuzcj5mkzc6.png)

First, we set the future time to execute the task using the current time + the time the user schedules. Then, we create a task inside the SimpleIntervalJob itself. The purpose of this is so that when the task executes(wakes up) it will check if it's time to execute the original task, or if we're still over the limit. If we are, keep running the timeEating task. If we're not, then execute the task the user planned.

By doing this, we "eat time" until setInterval() won't throw an error anymore. Overall, the most difficult part of this constructor fix was having to wrap my head around the ***timeEating task calling itself*** and checking ***inside itself*** whether were over time.

## Testing
Having seen the application code now, I noticed the creator was using ***Jest*** testing framework. Before this, I had no experience writing automated tests but if you're going to implement a fix you need to test so now was the time.

For the most part, the tests consisted of a counter variable, and a job/task to be executed. In order to test if my constructor worked, I wrote a test that initialized a job to execute in 25 days (which is over the limit). I advanced the timer by just under 25 days, and then pushed it right to 25 days to check if the task executed properly.
```
    it('correctly handles very large intervals', () => {
      let counter = 0
      const daysInMs = 25 * 24 * 60 * 60 * 1000 //25 days in ms
      const scheduler = new ToadScheduler()
      const task = new Task('simple task', () => {
        counter++
      })
      const job = new SimpleIntervalJob(
        {
          milliseconds: daysInMs,
        },
        task
      )
      scheduler.addSimpleIntervalJob(job)

      expect(counter).toBe(0)
      jest.advanceTimersByTime(daysInMs - 1000)
      expect(counter).toBe(0)
      jest.advanceTimersByTime(1000)
      expect(counter).toBe(1)
      scheduler.stop()
    })
```
## The Creator
The original creator of the tool is [Igor 'kibertoad' Savin](https://github.com/kibertoad) and I had a really great time getting to know him and picking his brain about this issue. Overall it was a very difficult issue to solve which is why I chose it for my [4th Pull Request](https://github.com/kibertoad/toad-scheduler/pull/53) but I learned a lot about how to work around issues that you CAN'T fix at a base level such as the ***32 bit integer not being big enough***. I might not be able to change the size of the integer but I can change how my code handles these issues.