setInterval() 및 32비트 문제.

뒷이야기



저는 Hacktoberfest에 대한 4개의 풀 리퀘스트를 완료하기 위해 10월 초에 처음 출발했습니다. 나의 초기 연구는 터미널 출력을 색칠하기 위한 CLI 도구인 "Colorette"라는 도구로 이끌었습니다. 나는 정말로 이 저장소에서 작업하고 싶었지만 내가 제안한 문제 수정을 구현하기 전에 누군가 급습하여 내 자리에 PR을 병합했습니다.

나중에 kibertoad이라는 프로젝트의 멋진 기여자가 이 일을 보고 자신의 scheduling tool 작업을 하고 싶은지 물었습니다. 나는 확실히 말했다, 그리고 우리는 갔다. 도구가 잘 테스트되었기 때문에 리포지토리에는 문제가 거의 없었습니다.

그러나 one key issue remained . setInterval().

setInterval()? 뭐가 문제 야?



"setInterval()? 100만 번이나 사용해도 문제 없습니다."라고 생각할 수 있습니다. 그리고 당신이 옳을 것입니다. 프로젝트를 통해 알게 된 setInterval()의 문제는 JavaScript 언어 자체의 문제입니다.

setInterval의 값은 32비트 부호 있는 정수로 유지됩니다. 대부분의 경우 setInterval()은 주로 작업을 더 가깝게 실행하는 데 사용되기 때문에 최대값을 초과하지 않습니다. 그러나 우리의 경우 일정 도구를 만들고 있기 때문에 실제로 누군가가 작업을 30일 동안 예약하려고 할 수 있으며 한도는 24.855일입니다.

생성자 고정



처음에 30일 일정으로 작업 및 작업을 생성할 때 도구가 제한에 대한 NodeJS 오류와 함께 충돌합니다. 이를 수정하기 위해 생성자에서 많은 확인, 지연 및 시간 추적을 구현해야 했습니다.


먼저 현재 시간 + 사용자가 예약한 시간을 사용하여 작업을 실행할 미래 시간을 설정합니다. 그런 다음 SimpleIntervalJob 자체 내에 작업을 만듭니다. 이것의 목적은 작업이 실행될 때(깨어나면) 원래 작업을 실행할 시간인지 또는 여전히 제한을 초과하는지 확인하는 것입니다. 그렇다면 timeEating 태스크를 계속 실행하십시오. 그렇지 않은 경우 사용자가 계획한 작업을 실행합니다.

이렇게 하면 setInterval()이 더 이상 오류를 발생시키지 않을 때까지 "시간을 잡아먹습니다". 전반적으로, 이 생성자 수정의 가장 어려운 부분은 timeEating 태스크가 자신을 호출하고 시간이 경과했는지 내부에서 확인하는 것이었습니다.

테스트



이제 애플리케이션 코드를 보았을 때 작성자가 Jest 테스트 프레임워크를 사용하고 있음을 알았습니다. 그 전에는 자동화된 테스트를 작성한 경험이 없었지만 수정 사항을 구현하려면 테스트해야 하므로 지금이 적기입니다.

대부분의 경우 테스트는 카운터 변수와 실행할 작업/작업으로 구성되었습니다. 내 생성자가 작동하는지 테스트하기 위해 작업을 초기화하여 25일(제한 초과)에 실행하는 테스트를 작성했습니다. 타이머를 25일 미만으로 앞당긴 다음 작업이 제대로 실행되는지 확인하기 위해 25일로 바로 밀었습니다.

    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()
    })


창조주



이 도구의 원래 작성자는 Igor 'kibertoad' Savin이며 저는 그를 알게 되고 이 문제에 대해 그의 생각을 고르는 데 정말 즐거운 시간을 보냈습니다. 전반적으로 해결하기 매우 어려운 문제였기 때문에 내 4th Pull Request에 대해 선택했지만 32비트 정수가 크지 않은 것과 같이 기본 수준에서 해결할 수 없는 문제를 해결하는 방법에 대해 많이 배웠습니다. 충분한. 정수의 크기를 변경할 수는 없지만 내 코드에서 이러한 문제를 처리하는 방법은 변경할 수 있습니다.

좋은 웹페이지 즐겨찾기