laravel / horizon

Dashboard and code-driven configuration for Laravel queues.
https://laravel.com/docs/horizon
MIT License
3.84k stars 645 forks source link

Fix the pagination of recent jobs list #1366

Closed kirba closed 8 months ago

kirba commented 8 months ago

There is an issue with navigating to the next / previous pages in recent jobs pages (pending, completed & silenced).

To summarize, a job at index 50 will be skipped when navigating to the 2nd page and a job at index 0 will be skipped when navigating back to the first page.

https://github.com/laravel/horizon/blob/5.x/src/Repositories/RedisJobRepository.php#L244-L251

This function is responsible for pulling the list of jobs from Redis

 protected function getJobsByType($type, $afterIndex)
  {
      $afterIndex = $afterIndex === null ? -1 : $afterIndex;

      return $this->getJobs($this->connection()->zrange(
          $type, $afterIndex + 1, $afterIndex + 50
      ), $afterIndex + 1);
  }

what this function does is it takes the $afterIndex add 1 to it for the starting index and adds 50 for the ending.

That works for the first page, we will send -1 and it will load jobs between 0 and 49. But when we navigate to the second page, as a starting index we are sending 50 instead of 49 (since in the Vue component we would multiple the current page (1) with the number of records we load per page (50)). And then what happens in the Repo class is that we load jobs starting at index 51 until index 100. By doing this we have skipped one job. Further pages would be fine because they will follow the same principle. (101-150 etc)

And when going back to the first page we multiply current page minus 2 (0) with number of records we load per page and we get 0. Then we are loading jobs from 1 to 50 and we are skipping the very first job at the zero index. In this case the issue will resolve itself in 3 seconds as we are auto refreshing with the starting value of -1 while on the first page.

The fix is very easy, for the starting value we should always send a value decremented by 1 after doing computation that involves multiplying the current page number with number of records. That way we would sent -1, 49, 99, etc as starting values and we would not skip a job.