| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.paginate = void 0;
- const content = `--[[
- Paginate a set or hash
- Input:
- KEYS[1] key pointing to the set or hash to be paginated.
- ARGV[1] page start offset
- ARGV[2] page end offset (-1 for all the elements)
- ARGV[3] cursor
- ARGV[4] offset
- ARGV[5] max iterations
- ARGV[6] fetch jobs?
- Output:
- [cursor, offset, items, numItems]
- ]]
- local rcall = redis.call
- -- Includes
- --[[
- Function to achieve pagination for a set or hash.
- This function simulates pagination in the most efficient way possible
- for a set using sscan or hscan.
- The main limitation is that sets are not order preserving, so the
- pagination is not stable. This means that if the set is modified
- between pages, the same element may appear in different pages.
- ]] -- Maximum number of elements to be returned by sscan per iteration.
- local maxCount = 100
- -- Finds the cursor, and returns the first elements available for the requested page.
- local function findPage(key, command, pageStart, pageSize, cursor, offset,
- maxIterations, fetchJobs)
- local items = {}
- local jobs = {}
- local iterations = 0
- repeat
- -- Iterate over the set using sscan/hscan.
- local result = rcall(command, key, cursor, "COUNT", maxCount)
- cursor = result[1]
- local members = result[2]
- local step = 1
- if command == "HSCAN" then
- step = 2
- end
- if #members == 0 then
- -- If the result is empty, we can return the result.
- return cursor, offset, items, jobs
- end
- local chunkStart = offset
- local chunkEnd = offset + #members / step
- local pageEnd = pageStart + pageSize
- if chunkEnd < pageStart then
- -- If the chunk is before the page, we can skip it.
- offset = chunkEnd
- elseif chunkStart > pageEnd then
- -- If the chunk is after the page, we can return the result.
- return cursor, offset, items, jobs
- else
- -- If the chunk is overlapping the page, we need to add the elements to the result.
- for i = 1, #members, step do
- if offset >= pageEnd then
- return cursor, offset, items, jobs
- end
- if offset >= pageStart then
- local index = #items + 1
- if fetchJobs ~= nil then
- jobs[#jobs+1] = rcall("HGETALL", members[i])
- end
- if step == 2 then
- items[index] = {members[i], members[i + 1]}
- else
- items[index] = members[i]
- end
- end
- offset = offset + 1
- end
- end
- iterations = iterations + 1
- until cursor == "0" or iterations >= maxIterations
- return cursor, offset, items, jobs
- end
- local key = KEYS[1]
- local scanCommand = "SSCAN"
- local countCommand = "SCARD"
- local type = rcall("TYPE", key)["ok"]
- if type == "none" then
- return {0, 0, {}, 0}
- elseif type == "hash" then
- scanCommand = "HSCAN"
- countCommand = "HLEN"
- elseif type ~= "set" then
- return
- redis.error_reply("Pagination is only supported for sets and hashes.")
- end
- local numItems = rcall(countCommand, key)
- local startOffset = tonumber(ARGV[1])
- local endOffset = tonumber(ARGV[2])
- if endOffset == -1 then
- endOffset = numItems
- end
- local pageSize = (endOffset - startOffset) + 1
- local cursor, offset, items, jobs = findPage(key, scanCommand, startOffset,
- pageSize, ARGV[3], tonumber(ARGV[4]),
- tonumber(ARGV[5]), ARGV[6])
- return {cursor, offset, items, numItems, jobs}
- `;
- exports.paginate = {
- name: 'paginate',
- content,
- keys: 1,
- };
- //# sourceMappingURL=paginate-1.js.map
|