findPage.lua 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. --[[
  2. Function to achieve pagination for a set or hash.
  3. This function simulates pagination in the most efficient way possible
  4. for a set using sscan or hscan.
  5. The main limitation is that sets are not order preserving, so the
  6. pagination is not stable. This means that if the set is modified
  7. between pages, the same element may appear in different pages.
  8. ]] -- Maximum number of elements to be returned by sscan per iteration.
  9. local maxCount = 100
  10. -- Finds the cursor, and returns the first elements available for the requested page.
  11. local function findPage(key, command, pageStart, pageSize, cursor, offset,
  12. maxIterations, fetchJobs)
  13. local items = {}
  14. local jobs = {}
  15. local iterations = 0
  16. repeat
  17. -- Iterate over the set using sscan/hscan.
  18. local result = rcall(command, key, cursor, "COUNT", maxCount)
  19. cursor = result[1]
  20. local members = result[2]
  21. local step = 1
  22. if command == "HSCAN" then
  23. step = 2
  24. end
  25. if #members == 0 then
  26. -- If the result is empty, we can return the result.
  27. return cursor, offset, items, jobs
  28. end
  29. local chunkStart = offset
  30. local chunkEnd = offset + #members / step
  31. local pageEnd = pageStart + pageSize
  32. if chunkEnd < pageStart then
  33. -- If the chunk is before the page, we can skip it.
  34. offset = chunkEnd
  35. elseif chunkStart > pageEnd then
  36. -- If the chunk is after the page, we can return the result.
  37. return cursor, offset, items, jobs
  38. else
  39. -- If the chunk is overlapping the page, we need to add the elements to the result.
  40. for i = 1, #members, step do
  41. if offset >= pageEnd then
  42. return cursor, offset, items, jobs
  43. end
  44. if offset >= pageStart then
  45. local index = #items + 1
  46. if fetchJobs ~= nil then
  47. jobs[#jobs+1] = rcall("HGETALL", members[i])
  48. end
  49. if step == 2 then
  50. items[index] = {members[i], members[i + 1]}
  51. else
  52. items[index] = members[i]
  53. end
  54. end
  55. offset = offset + 1
  56. end
  57. end
  58. iterations = iterations + 1
  59. until cursor == "0" or iterations >= maxIterations
  60. return cursor, offset, items, jobs
  61. end