DEV Community 👩‍💻👨‍💻

Cover image for setInterval() and the 32 bit debacle.
Andre Willomitzer
Andre Willomitzer

Posted on

setInterval() and the 32 bit debacle.

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 saw this happen and asked if I wanted to come work on his scheduling tool. 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. 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

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()
    })
Enter fullscreen mode Exit fullscreen mode

The Creator

The original creator of the tool is Igor 'kibertoad' Savin 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 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.

Top comments (2)

Collapse
 
fitsum profile image
fitsum

I really enjoyed this

Collapse
 
andrewillomitzer profile image
Andre Willomitzer Author

Hey! Glad you liked it. It was one of the toughest issues I've ever encountered. It took a lot of time to wrap my head around how to do it and a lot of errors/failing tests lol

Thanks for reading, all the best!

Andre

Need a better mental model for async/await?

Check out this classic DEV post on the subject.

⭐️🎀 JavaScript Visualized: Promises & Async/Await

async await