glide-mq 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +190 -0
- package/dist/connection.d.ts +36 -0
- package/dist/connection.d.ts.map +1 -0
- package/dist/connection.js +100 -0
- package/dist/connection.js.map +1 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +25 -0
- package/dist/errors.js.map +1 -0
- package/dist/flow-producer.d.ts +36 -0
- package/dist/flow-producer.d.ts.map +1 -0
- package/dist/flow-producer.js +185 -0
- package/dist/flow-producer.js.map +1 -0
- package/dist/functions/index.d.ts +136 -0
- package/dist/functions/index.d.ts.map +1 -0
- package/dist/functions/index.js +1062 -0
- package/dist/functions/index.js.map +1 -0
- package/dist/graceful-shutdown.d.ts +17 -0
- package/dist/graceful-shutdown.d.ts.map +1 -0
- package/dist/graceful-shutdown.js +27 -0
- package/dist/graceful-shutdown.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/job.d.ts +106 -0
- package/dist/job.d.ts.map +1 -0
- package/dist/job.js +252 -0
- package/dist/job.js.map +1 -0
- package/dist/queue-events.d.ts +33 -0
- package/dist/queue-events.d.ts.map +1 -0
- package/dist/queue-events.js +138 -0
- package/dist/queue-events.js.map +1 -0
- package/dist/queue.d.ts +140 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +483 -0
- package/dist/queue.js.map +1 -0
- package/dist/scheduler.d.ts +48 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +140 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/telemetry.d.ts +29 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +90 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/types.d.ts +125 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +65 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +217 -0
- package/dist/utils.js.map +1 -0
- package/dist/worker.d.ts +138 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +574 -0
- package/dist/worker.js.map +1 -0
- package/dist/workflows.d.ts +34 -0
- package/dist/workflows.d.ts.map +1 -0
- package/dist/workflows.js +117 -0
- package/dist/workflows.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { Client } from '../types';
|
|
2
|
+
import type { GlideReturnType } from '@glidemq/speedkey';
|
|
3
|
+
export declare const LIBRARY_NAME = "glidemq";
|
|
4
|
+
export declare const LIBRARY_VERSION = "5";
|
|
5
|
+
export declare const CONSUMER_GROUP = "workers";
|
|
6
|
+
export declare const LIBRARY_SOURCE = "#!lua name=glidemq\n\nlocal PRIORITY_SHIFT = 4398046511104\n\nlocal function emitEvent(eventsKey, eventType, jobId, extraFields)\n local fields = {'event', eventType, 'jobId', tostring(jobId)}\n if extraFields then\n for i = 1, #extraFields, 2 do\n fields[#fields + 1] = extraFields[i]\n fields[#fields + 1] = extraFields[i + 1]\n end\n end\n redis.call('XADD', eventsKey, 'MAXLEN', '~', '1000', '*', unpack(fields))\nend\n\nredis.register_function('glidemq_version', function(keys, args)\n return '5'\nend)\n\nredis.register_function('glidemq_addJob', function(keys, args)\n local idKey = keys[1]\n local streamKey = keys[2]\n local scheduledKey = keys[3]\n local eventsKey = keys[4]\n local jobName = args[1]\n local jobData = args[2]\n local jobOpts = args[3]\n local timestamp = tonumber(args[4])\n local delay = tonumber(args[5]) or 0\n local priority = tonumber(args[6]) or 0\n local parentId = args[7] or ''\n local maxAttempts = tonumber(args[8]) or 0\n local jobId = redis.call('INCR', idKey)\n local jobIdStr = tostring(jobId)\n local prefix = string.sub(idKey, 1, #idKey - 2)\n local jobKey = prefix .. 'job:' .. jobIdStr\n local hashFields = {\n 'id', jobIdStr,\n 'name', jobName,\n 'data', jobData,\n 'opts', jobOpts,\n 'timestamp', tostring(timestamp),\n 'attemptsMade', '0',\n 'delay', tostring(delay),\n 'priority', tostring(priority),\n 'maxAttempts', tostring(maxAttempts)\n }\n if parentId ~= '' then\n hashFields[#hashFields + 1] = 'parentId'\n hashFields[#hashFields + 1] = parentId\n end\n if delay > 0 or priority > 0 then\n hashFields[#hashFields + 1] = 'state'\n hashFields[#hashFields + 1] = delay > 0 and 'delayed' or 'prioritized'\n else\n hashFields[#hashFields + 1] = 'state'\n hashFields[#hashFields + 1] = 'waiting'\n end\n redis.call('HSET', jobKey, unpack(hashFields))\n if delay > 0 then\n local score = priority * PRIORITY_SHIFT + (timestamp + delay)\n redis.call('ZADD', scheduledKey, score, jobIdStr)\n elseif priority > 0 then\n local score = priority * PRIORITY_SHIFT\n redis.call('ZADD', scheduledKey, score, jobIdStr)\n else\n redis.call('XADD', streamKey, '*', 'jobId', jobIdStr)\n end\n emitEvent(eventsKey, 'added', jobIdStr, {'name', jobName})\n return jobIdStr\nend)\n\nredis.register_function('glidemq_promote', function(keys, args)\n local scheduledKey = keys[1]\n local streamKey = keys[2]\n local eventsKey = keys[3]\n local now = tonumber(args[1])\n local members = redis.call('ZRANGEBYSCORE', scheduledKey, '0', tostring(now))\n local count = 0\n for i = 1, #members do\n local jobId = members[i]\n redis.call('XADD', streamKey, '*', 'jobId', jobId)\n redis.call('ZREM', scheduledKey, jobId)\n local prefix = string.sub(scheduledKey, 1, #scheduledKey - 9)\n local jobKey = prefix .. 'job:' .. jobId\n redis.call('HSET', jobKey, 'state', 'waiting')\n emitEvent(eventsKey, 'promoted', jobId, nil)\n count = count + 1\n end\n return count\nend)\n\nredis.register_function('glidemq_complete', function(keys, args)\n local streamKey = keys[1]\n local completedKey = keys[2]\n local eventsKey = keys[3]\n local jobKey = keys[4]\n local jobId = args[1]\n local entryId = args[2]\n local returnvalue = args[3]\n local timestamp = tonumber(args[4])\n local group = args[5]\n local removeMode = args[6] or '0'\n local removeCount = tonumber(args[7]) or 0\n local removeAge = tonumber(args[8]) or 0\n local depsMember = args[9] or ''\n local parentId = args[10] or ''\n redis.call('XACK', streamKey, group, entryId)\n redis.call('XDEL', streamKey, entryId)\n redis.call('ZADD', completedKey, timestamp, jobId)\n redis.call('HSET', jobKey,\n 'state', 'completed',\n 'returnvalue', returnvalue,\n 'finishedOn', tostring(timestamp)\n )\n emitEvent(eventsKey, 'completed', jobId, {'returnvalue', returnvalue})\n local prefix = string.sub(jobKey, 1, #jobKey - #('job:' .. jobId))\n if removeMode == 'true' then\n redis.call('ZREM', completedKey, jobId)\n redis.call('DEL', jobKey)\n elseif removeMode == 'count' and removeCount > 0 then\n local total = redis.call('ZCARD', completedKey)\n if total > removeCount then\n local excess = redis.call('ZRANGE', completedKey, 0, total - removeCount - 1)\n for i = 1, #excess do\n local oldId = excess[i]\n redis.call('DEL', prefix .. 'job:' .. oldId)\n redis.call('ZREM', completedKey, oldId)\n end\n end\n elseif removeMode == 'age_count' then\n if removeAge > 0 then\n local cutoff = timestamp - (removeAge * 1000)\n local old = redis.call('ZRANGEBYSCORE', completedKey, '0', tostring(cutoff))\n for i = 1, #old do\n local oldId = old[i]\n redis.call('DEL', prefix .. 'job:' .. oldId)\n redis.call('ZREM', completedKey, oldId)\n end\n end\n if removeCount > 0 then\n local total = redis.call('ZCARD', completedKey)\n if total > removeCount then\n local excess = redis.call('ZRANGE', completedKey, 0, total - removeCount - 1)\n for i = 1, #excess do\n local oldId = excess[i]\n redis.call('DEL', prefix .. 'job:' .. oldId)\n redis.call('ZREM', completedKey, oldId)\n end\n end\n end\n end\n if depsMember ~= '' and parentId ~= '' and #keys >= 8 then\n local parentDepsKey = keys[5]\n local parentJobKey = keys[6]\n local parentStreamKey = keys[7]\n local parentEventsKey = keys[8]\n local doneCount = redis.call('HINCRBY', parentJobKey, 'depsCompleted', 1)\n local totalDeps = redis.call('SCARD', parentDepsKey)\n local remaining = totalDeps - doneCount\n if remaining <= 0 then\n redis.call('HSET', parentJobKey, 'state', 'waiting')\n redis.call('XADD', parentStreamKey, '*', 'jobId', parentId)\n emitEvent(parentEventsKey, 'active', parentId, nil)\n end\n end\n return 1\nend)\n\nredis.register_function('glidemq_completeAndFetchNext', function(keys, args)\n local streamKey = keys[1]\n local completedKey = keys[2]\n local eventsKey = keys[3]\n local jobKey = keys[4]\n local jobId = args[1]\n local entryId = args[2]\n local returnvalue = args[3]\n local timestamp = tonumber(args[4])\n local group = args[5]\n local consumer = args[6]\n local removeMode = args[7] or '0'\n local removeCount = tonumber(args[8]) or 0\n local removeAge = tonumber(args[9]) or 0\n local depsMember = args[10] or ''\n local parentId = args[11] or ''\n\n -- Phase 1: Complete current job (same as glidemq_complete)\n redis.call('XACK', streamKey, group, entryId)\n redis.call('XDEL', streamKey, entryId)\n redis.call('ZADD', completedKey, timestamp, jobId)\n redis.call('HSET', jobKey,\n 'state', 'completed',\n 'returnvalue', returnvalue,\n 'finishedOn', tostring(timestamp)\n )\n emitEvent(eventsKey, 'completed', jobId, {'returnvalue', returnvalue})\n local prefix = string.sub(jobKey, 1, #jobKey - #('job:' .. jobId))\n\n -- Retention cleanup\n if removeMode == 'true' then\n redis.call('ZREM', completedKey, jobId)\n redis.call('DEL', jobKey)\n elseif removeMode == 'count' and removeCount > 0 then\n local total = redis.call('ZCARD', completedKey)\n if total > removeCount then\n local excess = redis.call('ZRANGE', completedKey, 0, total - removeCount - 1)\n for i = 1, #excess do\n redis.call('DEL', prefix .. 'job:' .. excess[i])\n redis.call('ZREM', completedKey, excess[i])\n end\n end\n end\n\n -- Parent deps\n if depsMember ~= '' and parentId ~= '' and #keys >= 8 then\n local parentDepsKey = keys[5]\n local parentJobKey = keys[6]\n local parentStreamKey = keys[7]\n local parentEventsKey = keys[8]\n local doneCount = redis.call('HINCRBY', parentJobKey, 'depsCompleted', 1)\n local totalDeps = redis.call('SCARD', parentDepsKey)\n if totalDeps - doneCount <= 0 then\n redis.call('HSET', parentJobKey, 'state', 'waiting')\n redis.call('XADD', parentStreamKey, '*', 'jobId', parentId)\n emitEvent(parentEventsKey, 'active', parentId, nil)\n end\n end\n\n -- Phase 2: Fetch next job (non-blocking XREADGROUP)\n local nextEntries = redis.call('XREADGROUP', 'GROUP', group, consumer, 'COUNT', 1, 'STREAMS', streamKey, '>')\n if not nextEntries or #nextEntries == 0 then\n return cjson.encode({completed = jobId, next = false})\n end\n local streamData = nextEntries[1]\n local entries = streamData[2]\n if not entries or #entries == 0 then\n return cjson.encode({completed = jobId, next = false})\n end\n local nextEntry = entries[1]\n local nextEntryId = nextEntry[1]\n local nextFields = nextEntry[2]\n local nextJobId = nil\n for i = 1, #nextFields, 2 do\n if nextFields[i] == 'jobId' then\n nextJobId = nextFields[i + 1]\n break\n end\n end\n if not nextJobId then\n return cjson.encode({completed = jobId, next = false})\n end\n\n -- Phase 3: Activate next job (same as moveToActive)\n local nextJobKey = prefix .. 'job:' .. nextJobId\n local nextExists = redis.call('EXISTS', nextJobKey)\n if nextExists == 0 then\n return cjson.encode({completed = jobId, next = false, nextEntryId = nextEntryId})\n end\n local revoked = redis.call('HGET', nextJobKey, 'revoked')\n if revoked == '1' then\n return cjson.encode({completed = jobId, next = 'REVOKED', nextJobId = nextJobId, nextEntryId = nextEntryId})\n end\n redis.call('HSET', nextJobKey, 'state', 'active', 'processedOn', tostring(timestamp), 'lastActive', tostring(timestamp))\n local nextHash = redis.call('HGETALL', nextJobKey)\n return cjson.encode({completed = jobId, next = nextHash, nextJobId = nextJobId, nextEntryId = nextEntryId})\nend)\n\nredis.register_function('glidemq_fail', function(keys, args)\n local streamKey = keys[1]\n local failedKey = keys[2]\n local scheduledKey = keys[3]\n local eventsKey = keys[4]\n local jobKey = keys[5]\n local jobId = args[1]\n local entryId = args[2]\n local failedReason = args[3]\n local timestamp = tonumber(args[4])\n local maxAttempts = tonumber(args[5]) or 0\n local backoffDelay = tonumber(args[6]) or 0\n local group = args[7]\n local removeMode = args[8] or '0'\n local removeCount = tonumber(args[9]) or 0\n local removeAge = tonumber(args[10]) or 0\n redis.call('XACK', streamKey, group, entryId)\n redis.call('XDEL', streamKey, entryId)\n local attemptsMade = redis.call('HINCRBY', jobKey, 'attemptsMade', 1)\n if maxAttempts > 0 and attemptsMade < maxAttempts then\n local retryAt = timestamp + backoffDelay\n local priority = tonumber(redis.call('HGET', jobKey, 'priority')) or 0\n local score = priority * PRIORITY_SHIFT + retryAt\n redis.call('ZADD', scheduledKey, score, jobId)\n redis.call('HSET', jobKey,\n 'state', 'delayed',\n 'failedReason', failedReason,\n 'processedOn', tostring(timestamp)\n )\n emitEvent(eventsKey, 'retrying', jobId, {\n 'failedReason', failedReason,\n 'attemptsMade', tostring(attemptsMade),\n 'delay', tostring(backoffDelay)\n })\n return 'retrying'\n else\n redis.call('ZADD', failedKey, timestamp, jobId)\n redis.call('HSET', jobKey,\n 'state', 'failed',\n 'failedReason', failedReason,\n 'finishedOn', tostring(timestamp),\n 'processedOn', tostring(timestamp)\n )\n emitEvent(eventsKey, 'failed', jobId, {'failedReason', failedReason})\n local prefix = string.sub(jobKey, 1, #jobKey - #('job:' .. jobId))\n if removeMode == 'true' then\n redis.call('ZREM', failedKey, jobId)\n redis.call('DEL', jobKey)\n elseif removeMode == 'count' and removeCount > 0 then\n local total = redis.call('ZCARD', failedKey)\n if total > removeCount then\n local excess = redis.call('ZRANGE', failedKey, 0, total - removeCount - 1)\n for i = 1, #excess do\n local oldId = excess[i]\n redis.call('DEL', prefix .. 'job:' .. oldId)\n redis.call('ZREM', failedKey, oldId)\n end\n end\n elseif removeMode == 'age_count' then\n if removeAge > 0 then\n local cutoff = timestamp - (removeAge * 1000)\n local old = redis.call('ZRANGEBYSCORE', failedKey, '0', tostring(cutoff))\n for i = 1, #old do\n local oldId = old[i]\n redis.call('DEL', prefix .. 'job:' .. oldId)\n redis.call('ZREM', failedKey, oldId)\n end\n end\n if removeCount > 0 then\n local total = redis.call('ZCARD', failedKey)\n if total > removeCount then\n local excess = redis.call('ZRANGE', failedKey, 0, total - removeCount - 1)\n for i = 1, #excess do\n local oldId = excess[i]\n redis.call('DEL', prefix .. 'job:' .. oldId)\n redis.call('ZREM', failedKey, oldId)\n end\n end\n end\n end\n return 'failed'\n end\nend)\n\nredis.register_function('glidemq_reclaimStalled', function(keys, args)\n local streamKey = keys[1]\n local eventsKey = keys[2]\n local group = args[1]\n local consumer = args[2]\n local minIdleMs = tonumber(args[3])\n local maxStalledCount = tonumber(args[4]) or 1\n local timestamp = tonumber(args[5])\n local failedKey = args[6]\n local result = redis.call('XAUTOCLAIM', streamKey, group, consumer, minIdleMs, '0-0')\n local entries = result[2]\n if not entries or #entries == 0 then\n return 0\n end\n local prefix = string.sub(streamKey, 1, #streamKey - 6)\n local count = 0\n for i = 1, #entries do\n local entry = entries[i]\n local entryId = entry[1]\n local fields = entry[2]\n local jobId = nil\n if type(fields) == 'table' then\n for j = 1, #fields, 2 do\n if fields[j] == 'jobId' then\n jobId = fields[j + 1]\n break\n end\n end\n end\n if jobId then\n local jobKey = prefix .. 'job:' .. jobId\n local lastActive = tonumber(redis.call('HGET', jobKey, 'lastActive'))\n if lastActive and (timestamp - lastActive) < minIdleMs then\n count = count + 1\n else\n local stalledCount = redis.call('HINCRBY', jobKey, 'stalledCount', 1)\n if stalledCount > maxStalledCount then\n redis.call('XACK', streamKey, group, entryId)\n redis.call('XDEL', streamKey, entryId)\n redis.call('ZADD', failedKey, timestamp, jobId)\n redis.call('HSET', jobKey,\n 'state', 'failed',\n 'failedReason', 'job stalled more than maxStalledCount',\n 'finishedOn', tostring(timestamp)\n )\n emitEvent(eventsKey, 'failed', jobId, {\n 'failedReason', 'job stalled more than maxStalledCount'\n })\n else\n redis.call('HSET', jobKey, 'state', 'active')\n emitEvent(eventsKey, 'stalled', jobId, nil)\n end\n count = count + 1\n end\n end\n end\n return count\nend)\n\nredis.register_function('glidemq_pause', function(keys, args)\n local metaKey = keys[1]\n local eventsKey = keys[2]\n redis.call('HSET', metaKey, 'paused', '1')\n emitEvent(eventsKey, 'paused', '0', nil)\n return 1\nend)\n\nredis.register_function('glidemq_resume', function(keys, args)\n local metaKey = keys[1]\n local eventsKey = keys[2]\n redis.call('HSET', metaKey, 'paused', '0')\n emitEvent(eventsKey, 'resumed', '0', nil)\n return 1\nend)\n\nredis.register_function('glidemq_dedup', function(keys, args)\n local dedupKey = keys[1]\n local idKey = keys[2]\n local streamKey = keys[3]\n local scheduledKey = keys[4]\n local eventsKey = keys[5]\n local dedupId = args[1]\n local ttlMs = tonumber(args[2]) or 0\n local mode = args[3]\n local jobName = args[4]\n local jobData = args[5]\n local jobOpts = args[6]\n local timestamp = tonumber(args[7])\n local delay = tonumber(args[8]) or 0\n local priority = tonumber(args[9]) or 0\n local parentId = args[10] or ''\n local maxAttempts = tonumber(args[11]) or 0\n local prefix = string.sub(idKey, 1, #idKey - 2)\n local existing = redis.call('HGET', dedupKey, dedupId)\n if mode == 'simple' then\n if existing then\n local sep = string.find(existing, ':')\n if sep then\n local existingJobId = string.sub(existing, 1, sep - 1)\n local jobKey = prefix .. 'job:' .. existingJobId\n local state = redis.call('HGET', jobKey, 'state')\n if state and state ~= 'completed' and state ~= 'failed' then\n return 'skipped'\n end\n end\n end\n elseif mode == 'throttle' then\n if existing and ttlMs > 0 then\n local sep = string.find(existing, ':')\n if sep then\n local storedTs = tonumber(string.sub(existing, sep + 1))\n if storedTs and (timestamp - storedTs) < ttlMs then\n return 'skipped'\n end\n end\n end\n elseif mode == 'debounce' then\n if existing then\n local sep = string.find(existing, ':')\n if sep then\n local existingJobId = string.sub(existing, 1, sep - 1)\n local jobKey = prefix .. 'job:' .. existingJobId\n local state = redis.call('HGET', jobKey, 'state')\n if state == 'delayed' or state == 'prioritized' then\n redis.call('ZREM', scheduledKey, existingJobId)\n redis.call('DEL', jobKey)\n emitEvent(eventsKey, 'removed', existingJobId, nil)\n elseif state and state ~= 'completed' and state ~= 'failed' then\n return 'skipped'\n end\n end\n end\n end\n local jobId = redis.call('INCR', idKey)\n local jobIdStr = tostring(jobId)\n local jobKey = prefix .. 'job:' .. jobIdStr\n local hashFields = {\n 'id', jobIdStr,\n 'name', jobName,\n 'data', jobData,\n 'opts', jobOpts,\n 'timestamp', tostring(timestamp),\n 'attemptsMade', '0',\n 'delay', tostring(delay),\n 'priority', tostring(priority),\n 'maxAttempts', tostring(maxAttempts)\n }\n if parentId ~= '' then\n hashFields[#hashFields + 1] = 'parentId'\n hashFields[#hashFields + 1] = parentId\n end\n if delay > 0 or priority > 0 then\n hashFields[#hashFields + 1] = 'state'\n hashFields[#hashFields + 1] = delay > 0 and 'delayed' or 'prioritized'\n else\n hashFields[#hashFields + 1] = 'state'\n hashFields[#hashFields + 1] = 'waiting'\n end\n redis.call('HSET', jobKey, unpack(hashFields))\n if delay > 0 then\n local score = priority * PRIORITY_SHIFT + (timestamp + delay)\n redis.call('ZADD', scheduledKey, score, jobIdStr)\n elseif priority > 0 then\n local score = priority * PRIORITY_SHIFT\n redis.call('ZADD', scheduledKey, score, jobIdStr)\n else\n redis.call('XADD', streamKey, '*', 'jobId', jobIdStr)\n end\n redis.call('HSET', dedupKey, dedupId, jobIdStr .. ':' .. tostring(timestamp))\n emitEvent(eventsKey, 'added', jobIdStr, {'name', jobName})\n return jobIdStr\nend)\n\nredis.register_function('glidemq_rateLimit', function(keys, args)\n local rateKey = keys[1]\n local metaKey = keys[2]\n local maxPerWindow = tonumber(args[1])\n local windowDuration = tonumber(args[2])\n local now = tonumber(args[3])\n local windowStart = tonumber(redis.call('HGET', rateKey, 'windowStart')) or 0\n local count = tonumber(redis.call('HGET', rateKey, 'count')) or 0\n if now - windowStart >= windowDuration then\n redis.call('HSET', rateKey, 'windowStart', tostring(now), 'count', '1')\n return 0\n end\n if count >= maxPerWindow then\n local delayMs = windowDuration - (now - windowStart)\n return delayMs\n end\n redis.call('HSET', rateKey, 'count', tostring(count + 1))\n return 0\nend)\n\nredis.register_function('glidemq_checkConcurrency', function(keys, args)\n local metaKey = keys[1]\n local streamKey = keys[2]\n local group = args[1]\n local gc = tonumber(redis.call('HGET', metaKey, 'globalConcurrency')) or 0\n if gc <= 0 then\n return -1\n end\n local pending = redis.call('XPENDING', streamKey, group)\n local pendingCount = tonumber(pending[1]) or 0\n local remaining = gc - pendingCount\n if remaining <= 0 then\n return 0\n end\n return remaining\nend)\n\nredis.register_function('glidemq_moveToActive', function(keys, args)\n local jobKey = keys[1]\n local timestamp = args[1]\n local exists = redis.call('EXISTS', jobKey)\n if exists == 0 then\n return ''\n end\n local revoked = redis.call('HGET', jobKey, 'revoked')\n if revoked == '1' then\n return 'REVOKED'\n end\n redis.call('HSET', jobKey, 'state', 'active', 'processedOn', timestamp, 'lastActive', timestamp)\n local fields = redis.call('HGETALL', jobKey)\n return cjson.encode(fields)\nend)\n\nredis.register_function('glidemq_addFlow', function(keys, args)\n local parentIdKey = keys[1]\n local parentStreamKey = keys[2]\n local parentScheduledKey = keys[3]\n local parentEventsKey = keys[4]\n local parentName = args[1]\n local parentData = args[2]\n local parentOpts = args[3]\n local timestamp = tonumber(args[4])\n local parentDelay = tonumber(args[5]) or 0\n local parentPriority = tonumber(args[6]) or 0\n local parentMaxAttempts = tonumber(args[7]) or 0\n local numChildren = tonumber(args[8])\n local parentJobId = redis.call('INCR', parentIdKey)\n local parentJobIdStr = tostring(parentJobId)\n local parentPrefix = string.sub(parentIdKey, 1, #parentIdKey - 2)\n local parentJobKey = parentPrefix .. 'job:' .. parentJobIdStr\n local depsKey = parentPrefix .. 'deps:' .. parentJobIdStr\n local parentHash = {\n 'id', parentJobIdStr,\n 'name', parentName,\n 'data', parentData,\n 'opts', parentOpts,\n 'timestamp', tostring(timestamp),\n 'attemptsMade', '0',\n 'delay', tostring(parentDelay),\n 'priority', tostring(parentPriority),\n 'maxAttempts', tostring(parentMaxAttempts),\n 'state', 'waiting-children'\n }\n redis.call('HSET', parentJobKey, unpack(parentHash))\n local childIds = {}\n local childArgOffset = 8\n local childKeyOffset = 4\n for i = 1, numChildren do\n local base = childArgOffset + (i - 1) * 8\n local childName = args[base + 1]\n local childData = args[base + 2]\n local childOpts = args[base + 3]\n local childDelay = tonumber(args[base + 4]) or 0\n local childPriority = tonumber(args[base + 5]) or 0\n local childMaxAttempts = tonumber(args[base + 6]) or 0\n local childQueuePrefix = args[base + 7]\n local childParentQueue = args[base + 8]\n local ckBase = childKeyOffset + (i - 1) * 4\n local childIdKey = keys[ckBase + 1]\n local childStreamKey = keys[ckBase + 2]\n local childScheduledKey = keys[ckBase + 3]\n local childEventsKey = keys[ckBase + 4]\n local childJobId = redis.call('INCR', childIdKey)\n local childJobIdStr = tostring(childJobId)\n local childPrefix = string.sub(childIdKey, 1, #childIdKey - 2)\n local childJobKey = childPrefix .. 'job:' .. childJobIdStr\n local childHash = {\n 'id', childJobIdStr,\n 'name', childName,\n 'data', childData,\n 'opts', childOpts,\n 'timestamp', tostring(timestamp),\n 'attemptsMade', '0',\n 'delay', tostring(childDelay),\n 'priority', tostring(childPriority),\n 'maxAttempts', tostring(childMaxAttempts),\n 'parentId', parentJobIdStr,\n 'parentQueue', childParentQueue\n }\n if childDelay > 0 or childPriority > 0 then\n childHash[#childHash + 1] = 'state'\n childHash[#childHash + 1] = childDelay > 0 and 'delayed' or 'prioritized'\n else\n childHash[#childHash + 1] = 'state'\n childHash[#childHash + 1] = 'waiting'\n end\n redis.call('HSET', childJobKey, unpack(childHash))\n local depsMember = childQueuePrefix .. ':' .. childJobIdStr\n redis.call('SADD', depsKey, depsMember)\n if childDelay > 0 then\n local score = childPriority * PRIORITY_SHIFT + (timestamp + childDelay)\n redis.call('ZADD', childScheduledKey, score, childJobIdStr)\n elseif childPriority > 0 then\n local score = childPriority * PRIORITY_SHIFT\n redis.call('ZADD', childScheduledKey, score, childJobIdStr)\n else\n redis.call('XADD', childStreamKey, '*', 'jobId', childJobIdStr)\n end\n emitEvent(childEventsKey, 'added', childJobIdStr, {'name', childName})\n childIds[#childIds + 1] = childJobIdStr\n end\n local extraDepsOffset = childArgOffset + numChildren * 8\n local numExtraDeps = tonumber(args[extraDepsOffset + 1]) or 0\n for i = 1, numExtraDeps do\n local extraMember = args[extraDepsOffset + 1 + i]\n redis.call('SADD', depsKey, extraMember)\n end\n emitEvent(parentEventsKey, 'added', parentJobIdStr, {'name', parentName})\n local result = {parentJobIdStr}\n for i = 1, #childIds do\n result[#result + 1] = childIds[i]\n end\n return cjson.encode(result)\nend)\n\nredis.register_function('glidemq_completeChild', function(keys, args)\n local depsKey = keys[1]\n local parentJobKey = keys[2]\n local parentStreamKey = keys[3]\n local parentEventsKey = keys[4]\n local depsMember = args[1]\n local parentId = args[2]\n local doneCount = redis.call('HINCRBY', parentJobKey, 'depsCompleted', 1)\n local totalDeps = redis.call('SCARD', depsKey)\n local remaining = totalDeps - doneCount\n if remaining <= 0 then\n redis.call('HSET', parentJobKey, 'state', 'waiting')\n redis.call('XADD', parentStreamKey, '*', 'jobId', parentId)\n emitEvent(parentEventsKey, 'active', parentId, nil)\n end\n return remaining\nend)\n\nredis.register_function('glidemq_removeJob', function(keys, args)\n local jobKey = keys[1]\n local streamKey = keys[2]\n local scheduledKey = keys[3]\n local completedKey = keys[4]\n local failedKey = keys[5]\n local eventsKey = keys[6]\n local logKey = keys[7]\n local jobId = args[1]\n local exists = redis.call('EXISTS', jobKey)\n if exists == 0 then\n return 0\n end\n redis.call('ZREM', scheduledKey, jobId)\n redis.call('ZREM', completedKey, jobId)\n redis.call('ZREM', failedKey, jobId)\n redis.call('DEL', jobKey)\n redis.call('DEL', logKey)\n emitEvent(eventsKey, 'removed', jobId, nil)\n return 1\nend)\n\nredis.register_function('glidemq_revoke', function(keys, args)\n local jobKey = keys[1]\n local streamKey = keys[2]\n local scheduledKey = keys[3]\n local failedKey = keys[4]\n local eventsKey = keys[5]\n local jobId = args[1]\n local timestamp = tonumber(args[2])\n local group = args[3]\n local exists = redis.call('EXISTS', jobKey)\n if exists == 0 then\n return 'not_found'\n end\n redis.call('HSET', jobKey, 'revoked', '1')\n local state = redis.call('HGET', jobKey, 'state')\n if state == 'waiting' or state == 'delayed' or state == 'prioritized' then\n redis.call('ZREM', scheduledKey, jobId)\n local entries = redis.call('XRANGE', streamKey, '-', '+')\n for i = 1, #entries do\n local entryId = entries[i][1]\n local fields = entries[i][2]\n for j = 1, #fields, 2 do\n if fields[j] == 'jobId' and fields[j+1] == jobId then\n redis.call('XACK', streamKey, group, entryId)\n redis.call('XDEL', streamKey, entryId)\n break\n end\n end\n end\n redis.call('ZADD', failedKey, timestamp, jobId)\n redis.call('HSET', jobKey,\n 'state', 'failed',\n 'failedReason', 'revoked',\n 'finishedOn', tostring(timestamp)\n )\n emitEvent(eventsKey, 'revoked', jobId, nil)\n return 'revoked'\n end\n emitEvent(eventsKey, 'revoked', jobId, nil)\n return 'flagged'\nend)\n";
|
|
7
|
+
export type QueueKeys = ReturnType<typeof import('../utils').buildKeys>;
|
|
8
|
+
/**
|
|
9
|
+
* Add a job to the queue atomically.
|
|
10
|
+
* Returns the new job ID (string).
|
|
11
|
+
*/
|
|
12
|
+
export declare function addJob(client: Client, k: QueueKeys, jobName: string, data: string, opts: string, timestamp: number, delay: number, priority: number, parentId: string, maxAttempts: number): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Add a job with deduplication. Checks the dedup hash and either skips or adds the job.
|
|
15
|
+
* Returns "skipped" if deduplicated, otherwise the new job ID (string).
|
|
16
|
+
*/
|
|
17
|
+
export declare function dedup(client: Client, k: QueueKeys, dedupId: string, ttlMs: number, mode: string, jobName: string, data: string, opts: string, timestamp: number, delay: number, priority: number, parentId: string, maxAttempts: number): Promise<string>;
|
|
18
|
+
/**
|
|
19
|
+
* Promote delayed/prioritized jobs whose score <= now from scheduled ZSet to stream.
|
|
20
|
+
* Returns the number of jobs promoted.
|
|
21
|
+
*/
|
|
22
|
+
export declare function promote(client: Client, k: QueueKeys, timestamp: number): Promise<number>;
|
|
23
|
+
/**
|
|
24
|
+
* Complete a job: XACK, move to completed ZSet, update job hash, emit event.
|
|
25
|
+
* Optionally applies retention cleanup based on removeOnComplete.
|
|
26
|
+
* If the job has a parent (depsMember and parentId provided), also handles
|
|
27
|
+
* the completeChild logic inline: removes from parent deps, re-queues parent when all children done.
|
|
28
|
+
*/
|
|
29
|
+
export declare function completeJob(client: Client, k: QueueKeys, jobId: string, entryId: string, returnvalue: string, timestamp: number, group?: string, removeOnComplete?: boolean | number | {
|
|
30
|
+
age: number;
|
|
31
|
+
count: number;
|
|
32
|
+
}, parentInfo?: {
|
|
33
|
+
depsMember: string;
|
|
34
|
+
parentId: string;
|
|
35
|
+
parentKeys: QueueKeys;
|
|
36
|
+
}): Promise<GlideReturnType>;
|
|
37
|
+
/**
|
|
38
|
+
* Complete current job AND fetch+activate the next job in a single round trip.
|
|
39
|
+
* In steady state (jobs available), this reduces per-job overhead from 2 RTTs to 1.
|
|
40
|
+
*
|
|
41
|
+
* Returns:
|
|
42
|
+
* - { completed, next: false } if no more jobs in the stream
|
|
43
|
+
* - { completed, next: 'REVOKED', nextJobId, nextEntryId } if next job is revoked
|
|
44
|
+
* - { completed, next: Record<string,string>, nextJobId, nextEntryId } with next job hash fields
|
|
45
|
+
*/
|
|
46
|
+
export interface CompleteAndFetchResult {
|
|
47
|
+
completed: string;
|
|
48
|
+
next: false | 'REVOKED' | string[];
|
|
49
|
+
nextJobId?: string;
|
|
50
|
+
nextEntryId?: string;
|
|
51
|
+
}
|
|
52
|
+
export declare function completeAndFetchNext(client: Client, k: QueueKeys, jobId: string, entryId: string, returnvalue: string, timestamp: number, group: string, consumer: string, removeOnComplete?: boolean | number | {
|
|
53
|
+
age: number;
|
|
54
|
+
count: number;
|
|
55
|
+
}, parentInfo?: {
|
|
56
|
+
depsMember: string;
|
|
57
|
+
parentId: string;
|
|
58
|
+
parentKeys: QueueKeys;
|
|
59
|
+
}): Promise<CompleteAndFetchResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Fail a job: XACK, retry with backoff if attempts remain, else move to failed ZSet.
|
|
62
|
+
* Optionally applies retention cleanup based on removeOnFail.
|
|
63
|
+
* Returns "failed" or "retrying".
|
|
64
|
+
*/
|
|
65
|
+
export declare function failJob(client: Client, k: QueueKeys, jobId: string, entryId: string, failedReason: string, timestamp: number, maxAttempts: number, backoffDelay: number, group?: string, removeOnFail?: boolean | number | {
|
|
66
|
+
age: number;
|
|
67
|
+
count: number;
|
|
68
|
+
}): Promise<string>;
|
|
69
|
+
/**
|
|
70
|
+
* Reclaim stalled jobs via XAUTOCLAIM. Jobs exceeding maxStalledCount are moved to failed.
|
|
71
|
+
* Returns the number of jobs reclaimed.
|
|
72
|
+
*/
|
|
73
|
+
export declare function reclaimStalled(client: Client, k: QueueKeys, consumer: string, minIdleMs: number, maxStalledCount: number, timestamp: number, group?: string): Promise<number>;
|
|
74
|
+
/**
|
|
75
|
+
* Pause a queue: sets paused=1 in meta hash, emits event.
|
|
76
|
+
*/
|
|
77
|
+
export declare function pause(client: Client, k: QueueKeys): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Resume a queue: sets paused=0 in meta hash, emits event.
|
|
80
|
+
*/
|
|
81
|
+
export declare function resume(client: Client, k: QueueKeys): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Check and enforce rate limiting using a sliding window counter.
|
|
84
|
+
* Returns 0 if the job is allowed, or a positive number of ms to wait.
|
|
85
|
+
*/
|
|
86
|
+
export declare function rateLimit(client: Client, k: QueueKeys, maxPerWindow: number, windowDuration: number, timestamp: number): Promise<number>;
|
|
87
|
+
/**
|
|
88
|
+
* Check global concurrency: returns -1 if no limit is set, 0 if blocked
|
|
89
|
+
* (pending >= globalConcurrency), or a positive number indicating remaining
|
|
90
|
+
* capacity (globalConcurrency - pending).
|
|
91
|
+
*/
|
|
92
|
+
export declare function checkConcurrency(client: Client, k: QueueKeys, group?: string): Promise<number>;
|
|
93
|
+
/**
|
|
94
|
+
* Move a job to active state in a single round trip.
|
|
95
|
+
* Reads the full job hash, checks revoked flag, sets state=active + processedOn + lastActive.
|
|
96
|
+
* Returns:
|
|
97
|
+
* - null if job hash doesn't exist
|
|
98
|
+
* - 'REVOKED' if the job's revoked flag is set
|
|
99
|
+
* - Record<string, string> with all job fields otherwise
|
|
100
|
+
*
|
|
101
|
+
* Replaces: HGETALL + revoked check + HSET lastActive (3 round trips -> 1)
|
|
102
|
+
*/
|
|
103
|
+
export declare function moveToActive(client: Client, k: QueueKeys, jobId: string, timestamp: number): Promise<Record<string, string> | 'REVOKED' | null>;
|
|
104
|
+
/**
|
|
105
|
+
* Remove a job from all data structures (hash, stream, scheduled, completed, failed).
|
|
106
|
+
* Returns 1 if removed, 0 if not found.
|
|
107
|
+
*/
|
|
108
|
+
export declare function removeJob(client: Client, k: QueueKeys, jobId: string): Promise<number>;
|
|
109
|
+
/**
|
|
110
|
+
* Revoke a job. Sets 'revoked' flag on the job hash.
|
|
111
|
+
* If the job is waiting/delayed/prioritized, removes from stream/scheduled and moves to failed.
|
|
112
|
+
* If the job is active (being processed), just sets the flag - worker checks it cooperatively.
|
|
113
|
+
* Returns 'revoked' (moved to failed), 'flagged' (flag set, job is active), or 'not_found'.
|
|
114
|
+
*/
|
|
115
|
+
export declare function revokeJob(client: Client, k: QueueKeys, jobId: string, timestamp: number, group?: string): Promise<string>;
|
|
116
|
+
/**
|
|
117
|
+
* Atomically create a parent job (waiting-children) and its child jobs.
|
|
118
|
+
* Returns a JSON array: [parentId, childId1, childId2, ...].
|
|
119
|
+
*/
|
|
120
|
+
export declare function addFlow(client: Client, parentKeys: QueueKeys, parentName: string, parentData: string, parentOpts: string, timestamp: number, parentDelay: number, parentPriority: number, parentMaxAttempts: number, children: {
|
|
121
|
+
name: string;
|
|
122
|
+
data: string;
|
|
123
|
+
opts: string;
|
|
124
|
+
delay: number;
|
|
125
|
+
priority: number;
|
|
126
|
+
maxAttempts: number;
|
|
127
|
+
keys: QueueKeys;
|
|
128
|
+
queuePrefix: string;
|
|
129
|
+
parentQueueName: string;
|
|
130
|
+
}[], extraDeps?: string[]): Promise<string[]>;
|
|
131
|
+
/**
|
|
132
|
+
* Remove a child from the parent's deps set. If all children are done, re-queues the parent.
|
|
133
|
+
* Returns the number of remaining children (0 means parent was re-queued).
|
|
134
|
+
*/
|
|
135
|
+
export declare function completeChild(client: Client, parentKeys: QueueKeys, parentId: string, depsMember: string): Promise<number>;
|
|
136
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/functions/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,eAAO,MAAM,YAAY,YAAY,CAAC;AACtC,eAAO,MAAM,eAAe,MAAM,CAAC;AAGnC,eAAO,MAAM,cAAc,YAAY,CAAC;AAIxC,eAAO,MAAM,cAAc,iw1BAwvB1B,CAAC;AAIF,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,cAAc,UAAU,EAAE,SAAS,CAAC,CAAC;AAIxE;;;GAGG;AACH,wBAAsB,MAAM,CAC1B,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED;;;GAGG;AACH,wBAAsB,KAAK,CACzB,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,EACZ,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAOjB;AAoBD;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,MAAuB,EAC9B,gBAAgB,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EACpE,UAAU,CAAC,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,SAAS,CAAA;CAAE,GAC3E,OAAO,CAAC,eAAe,CAAC,CA6B1B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,EAAE,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,gBAAgB,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EACpE,UAAU,CAAC,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,SAAS,CAAA;CAAE,GAC3E,OAAO,CAAC,sBAAsB,CAAC,CAmCjC;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAC3B,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,KAAK,GAAE,MAAuB,EAC9B,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/D,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,MAAuB,GAC7B,OAAO,CAAC,MAAM,CAAC,CAcjB;AAED;;GAEG;AACH,wBAAsB,KAAK,CACzB,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,GACX,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;GAEG;AACH,wBAAsB,MAAM,CAC1B,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,GACX,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,EACZ,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,EACZ,KAAK,GAAE,MAAuB,GAC7B,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,EACZ,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC,CAgBpD;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,SAAS,EACZ,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,MAAuB,GAC7B,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,SAAS,EACrB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE;IACR,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB,EAAE,EACH,SAAS,GAAE,MAAM,EAAO,GACvB,OAAO,CAAC,MAAM,EAAE,CAAC,CAwCnB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,SAAS,EACrB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAOjB"}
|