Welcome aboard
${avatarBlock}
-
Hi ${user2.name}
+
Hi ${user3.name}
Thanks for verifying your email. CodeSM is where you practice coding problems, join contests, run submissions, and discuss solutions with the community. Here is how to get the most out of your account.
@@ -163957,7 +144101,7 @@ var sendOnboardingWelcomeEmail = async (email, user2) => {
return sendEmail({
to: email,
subject,
- text: `Welcome to CodeSM, ${user2.name}! Your email is verified. Open ${baseUrl}/ to get started.`,
+ text: `Welcome to CodeSM, ${user3.name}! Your email is verified. Open ${baseUrl}/ to get started.`,
html,
senderName: "CodeSM",
senderEmail: config_default.EMAIL_USER
@@ -164046,15 +144190,15 @@ var verifyEmail = async (token) => {
if (users.length === 0) {
throw new ApiError_default("Invalid or expired verification token", E.BAD_REQUEST);
}
- const user2 = users[0];
+ const user3 = users[0];
await db.update(user).set({
isEmailVerified: true,
verificationToken: null
- }).where(eq(user.id, user2.id));
- if (user2.email) {
- await sendOnboardingWelcomeEmail(user2.email, {
- name: user2.displayName || "User",
- heroImageUrl: user2.avatarUrl || undefined
+ }).where(eq(user.id, user3.id));
+ if (user3.email) {
+ await sendOnboardingWelcomeEmail(user3.email, {
+ name: user3.displayName || "User",
+ heroImageUrl: user3.avatarUrl || undefined
}).catch((error) => {
logger_default.error("Failed to send onboarding email after verification:", error);
});
@@ -164223,8 +144367,8 @@ var googleOAuthCallback = asyncHandler_default(async (req, res, next) => {
res.redirect(302, redirectUrl);
});
var getCurrentUser = asyncHandler_default(async (req, res, next) => {
- const user2 = req.user;
- if (!user2) {
+ const user3 = req.user;
+ if (!user3) {
return res.status(E.UNAUTHORIZED).json({
success: false,
message: "User not found or not authenticated"
@@ -164233,49 +144377,14 @@ var getCurrentUser = asyncHandler_default(async (req, res, next) => {
res.status(E.OK).json({
success: true,
data: {
- id: user2.id,
- email: user2.email,
- username: user2.username,
- role: user2.role
+ id: user3.id,
+ email: user3.email,
+ username: user3.username,
+ role: user3.role
}
});
});
-// src/middlewares/auth.middleware.ts
-var import_jsonwebtoken4 = __toESM(require_jsonwebtoken(), 1);
-var verifyJWT2 = asyncHandler_default(async (req, res, next) => {
- try {
- const token = req.headers.authorization?.startsWith("Bearer ") ? req.headers.authorization.split(" ")[1] : req.cookies?.token;
- if (!token) {
- throw new ApiError_default("Unauthorized Request: No token provided", 401);
- }
- const secret = process.env.ACCESS_TOKEN_SECRET;
- if (!secret) {
- throw new ApiError_default("Server misconfiguration: ACCESS_TOKEN_SECRET missing", 500);
- }
- const decodedToken = import_jsonwebtoken4.default.verify(token, secret);
- const userId = decodedToken?.userId;
- if (!userId) {
- throw new ApiError_default("Invalid Access Token", 401);
- }
- const users = await db.select().from(user).where(eq(user.id, userId)).limit(1);
- if (users.length === 0) {
- throw new ApiError_default("Invalid Access Token", 401);
- }
- const user2 = users[0];
- req.user = user2;
- next();
- } catch (error) {
- const statusCode = error instanceof ApiError_default ? error.statusCode : 500;
- const message = error instanceof ApiError_default ? error.message : "Internal Server Error";
- console.error("JWT Verification Error:", error instanceof Error ? error.message : String(error));
- return res.status(statusCode).json({
- status: "error",
- message
- });
- }
-});
-
// src/api/auth/auth-schema.ts
var emailPasswordLoginSchema = create$3().shape({
email: create$6().email("Invalid email format").required("Email is required"),
@@ -164294,7 +144403,7 @@ router.get("/verify-email", verifyEmail2);
router.post("/login", validate("body", emailPasswordLoginSchema), emailPasswordLogin);
router.get("/google", initiateGoogleAuth);
router.get("/google/callback", googleOAuthCallback);
-router.get("/me", verifyJWT2, getCurrentUser);
+router.get("/me", verifyJWT, getCurrentUser);
var auth_route_default = router;
// src/api/problem/problem-route.ts
@@ -164323,6 +144432,936 @@ var createProblemSchema = create$3({
sampleTestcases: create$5().required()
});
+// node_modules/.pnpm/@google+generative-ai@0.24.1/node_modules/@google/generative-ai/dist/index.mjs
+var SchemaType;
+(function(SchemaType2) {
+ SchemaType2["STRING"] = "string";
+ SchemaType2["NUMBER"] = "number";
+ SchemaType2["INTEGER"] = "integer";
+ SchemaType2["BOOLEAN"] = "boolean";
+ SchemaType2["ARRAY"] = "array";
+ SchemaType2["OBJECT"] = "object";
+})(SchemaType || (SchemaType = {}));
+var ExecutableCodeLanguage;
+(function(ExecutableCodeLanguage2) {
+ ExecutableCodeLanguage2["LANGUAGE_UNSPECIFIED"] = "language_unspecified";
+ ExecutableCodeLanguage2["PYTHON"] = "python";
+})(ExecutableCodeLanguage || (ExecutableCodeLanguage = {}));
+var Outcome;
+(function(Outcome2) {
+ Outcome2["OUTCOME_UNSPECIFIED"] = "outcome_unspecified";
+ Outcome2["OUTCOME_OK"] = "outcome_ok";
+ Outcome2["OUTCOME_FAILED"] = "outcome_failed";
+ Outcome2["OUTCOME_DEADLINE_EXCEEDED"] = "outcome_deadline_exceeded";
+})(Outcome || (Outcome = {}));
+var POSSIBLE_ROLES = ["user", "model", "function", "system"];
+var HarmCategory;
+(function(HarmCategory2) {
+ HarmCategory2["HARM_CATEGORY_UNSPECIFIED"] = "HARM_CATEGORY_UNSPECIFIED";
+ HarmCategory2["HARM_CATEGORY_HATE_SPEECH"] = "HARM_CATEGORY_HATE_SPEECH";
+ HarmCategory2["HARM_CATEGORY_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_SEXUALLY_EXPLICIT";
+ HarmCategory2["HARM_CATEGORY_HARASSMENT"] = "HARM_CATEGORY_HARASSMENT";
+ HarmCategory2["HARM_CATEGORY_DANGEROUS_CONTENT"] = "HARM_CATEGORY_DANGEROUS_CONTENT";
+ HarmCategory2["HARM_CATEGORY_CIVIC_INTEGRITY"] = "HARM_CATEGORY_CIVIC_INTEGRITY";
+})(HarmCategory || (HarmCategory = {}));
+var HarmBlockThreshold;
+(function(HarmBlockThreshold2) {
+ HarmBlockThreshold2["HARM_BLOCK_THRESHOLD_UNSPECIFIED"] = "HARM_BLOCK_THRESHOLD_UNSPECIFIED";
+ HarmBlockThreshold2["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE";
+ HarmBlockThreshold2["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE";
+ HarmBlockThreshold2["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH";
+ HarmBlockThreshold2["BLOCK_NONE"] = "BLOCK_NONE";
+})(HarmBlockThreshold || (HarmBlockThreshold = {}));
+var HarmProbability;
+(function(HarmProbability2) {
+ HarmProbability2["HARM_PROBABILITY_UNSPECIFIED"] = "HARM_PROBABILITY_UNSPECIFIED";
+ HarmProbability2["NEGLIGIBLE"] = "NEGLIGIBLE";
+ HarmProbability2["LOW"] = "LOW";
+ HarmProbability2["MEDIUM"] = "MEDIUM";
+ HarmProbability2["HIGH"] = "HIGH";
+})(HarmProbability || (HarmProbability = {}));
+var BlockReason;
+(function(BlockReason2) {
+ BlockReason2["BLOCKED_REASON_UNSPECIFIED"] = "BLOCKED_REASON_UNSPECIFIED";
+ BlockReason2["SAFETY"] = "SAFETY";
+ BlockReason2["OTHER"] = "OTHER";
+})(BlockReason || (BlockReason = {}));
+var FinishReason;
+(function(FinishReason2) {
+ FinishReason2["FINISH_REASON_UNSPECIFIED"] = "FINISH_REASON_UNSPECIFIED";
+ FinishReason2["STOP"] = "STOP";
+ FinishReason2["MAX_TOKENS"] = "MAX_TOKENS";
+ FinishReason2["SAFETY"] = "SAFETY";
+ FinishReason2["RECITATION"] = "RECITATION";
+ FinishReason2["LANGUAGE"] = "LANGUAGE";
+ FinishReason2["BLOCKLIST"] = "BLOCKLIST";
+ FinishReason2["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT";
+ FinishReason2["SPII"] = "SPII";
+ FinishReason2["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL";
+ FinishReason2["OTHER"] = "OTHER";
+})(FinishReason || (FinishReason = {}));
+var TaskType;
+(function(TaskType2) {
+ TaskType2["TASK_TYPE_UNSPECIFIED"] = "TASK_TYPE_UNSPECIFIED";
+ TaskType2["RETRIEVAL_QUERY"] = "RETRIEVAL_QUERY";
+ TaskType2["RETRIEVAL_DOCUMENT"] = "RETRIEVAL_DOCUMENT";
+ TaskType2["SEMANTIC_SIMILARITY"] = "SEMANTIC_SIMILARITY";
+ TaskType2["CLASSIFICATION"] = "CLASSIFICATION";
+ TaskType2["CLUSTERING"] = "CLUSTERING";
+})(TaskType || (TaskType = {}));
+var FunctionCallingMode;
+(function(FunctionCallingMode2) {
+ FunctionCallingMode2["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED";
+ FunctionCallingMode2["AUTO"] = "AUTO";
+ FunctionCallingMode2["ANY"] = "ANY";
+ FunctionCallingMode2["NONE"] = "NONE";
+})(FunctionCallingMode || (FunctionCallingMode = {}));
+var DynamicRetrievalMode;
+(function(DynamicRetrievalMode2) {
+ DynamicRetrievalMode2["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED";
+ DynamicRetrievalMode2["MODE_DYNAMIC"] = "MODE_DYNAMIC";
+})(DynamicRetrievalMode || (DynamicRetrievalMode = {}));
+
+class GoogleGenerativeAIError extends Error {
+ constructor(message) {
+ super(`[GoogleGenerativeAI Error]: ${message}`);
+ }
+}
+
+class GoogleGenerativeAIResponseError extends GoogleGenerativeAIError {
+ constructor(message, response) {
+ super(message);
+ this.response = response;
+ }
+}
+
+class GoogleGenerativeAIFetchError extends GoogleGenerativeAIError {
+ constructor(message, status, statusText, errorDetails) {
+ super(message);
+ this.status = status;
+ this.statusText = statusText;
+ this.errorDetails = errorDetails;
+ }
+}
+
+class GoogleGenerativeAIRequestInputError extends GoogleGenerativeAIError {
+}
+
+class GoogleGenerativeAIAbortError extends GoogleGenerativeAIError {
+}
+var DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com";
+var DEFAULT_API_VERSION = "v1beta";
+var PACKAGE_VERSION = "0.24.1";
+var PACKAGE_LOG_HEADER = "genai-js";
+var Task;
+(function(Task2) {
+ Task2["GENERATE_CONTENT"] = "generateContent";
+ Task2["STREAM_GENERATE_CONTENT"] = "streamGenerateContent";
+ Task2["COUNT_TOKENS"] = "countTokens";
+ Task2["EMBED_CONTENT"] = "embedContent";
+ Task2["BATCH_EMBED_CONTENTS"] = "batchEmbedContents";
+})(Task || (Task = {}));
+
+class RequestUrl {
+ constructor(model, task, apiKey, stream, requestOptions) {
+ this.model = model;
+ this.task = task;
+ this.apiKey = apiKey;
+ this.stream = stream;
+ this.requestOptions = requestOptions;
+ }
+ toString() {
+ var _a, _b;
+ const apiVersion = ((_a = this.requestOptions) === null || _a === undefined ? undefined : _a.apiVersion) || DEFAULT_API_VERSION;
+ const baseUrl2 = ((_b = this.requestOptions) === null || _b === undefined ? undefined : _b.baseUrl) || DEFAULT_BASE_URL;
+ let url = `${baseUrl2}/${apiVersion}/${this.model}:${this.task}`;
+ if (this.stream) {
+ url += "?alt=sse";
+ }
+ return url;
+ }
+}
+function getClientHeaders(requestOptions) {
+ const clientHeaders = [];
+ if (requestOptions === null || requestOptions === undefined ? undefined : requestOptions.apiClient) {
+ clientHeaders.push(requestOptions.apiClient);
+ }
+ clientHeaders.push(`${PACKAGE_LOG_HEADER}/${PACKAGE_VERSION}`);
+ return clientHeaders.join(" ");
+}
+async function getHeaders(url) {
+ var _a;
+ const headers = new Headers;
+ headers.append("Content-Type", "application/json");
+ headers.append("x-goog-api-client", getClientHeaders(url.requestOptions));
+ headers.append("x-goog-api-key", url.apiKey);
+ let customHeaders = (_a = url.requestOptions) === null || _a === undefined ? undefined : _a.customHeaders;
+ if (customHeaders) {
+ if (!(customHeaders instanceof Headers)) {
+ try {
+ customHeaders = new Headers(customHeaders);
+ } catch (e2) {
+ throw new GoogleGenerativeAIRequestInputError(`unable to convert customHeaders value ${JSON.stringify(customHeaders)} to Headers: ${e2.message}`);
+ }
+ }
+ for (const [headerName, headerValue] of customHeaders.entries()) {
+ if (headerName === "x-goog-api-key") {
+ throw new GoogleGenerativeAIRequestInputError(`Cannot set reserved header name ${headerName}`);
+ } else if (headerName === "x-goog-api-client") {
+ throw new GoogleGenerativeAIRequestInputError(`Header name ${headerName} can only be set using the apiClient field`);
+ }
+ headers.append(headerName, headerValue);
+ }
+ }
+ return headers;
+}
+async function constructModelRequest(model, task, apiKey, stream, body, requestOptions) {
+ const url = new RequestUrl(model, task, apiKey, stream, requestOptions);
+ return {
+ url: url.toString(),
+ fetchOptions: Object.assign(Object.assign({}, buildFetchOptions(requestOptions)), { method: "POST", headers: await getHeaders(url), body })
+ };
+}
+async function makeModelRequest(model, task, apiKey, stream, body, requestOptions = {}, fetchFn = fetch) {
+ const { url, fetchOptions } = await constructModelRequest(model, task, apiKey, stream, body, requestOptions);
+ return makeRequest(url, fetchOptions, fetchFn);
+}
+async function makeRequest(url, fetchOptions, fetchFn = fetch) {
+ let response;
+ try {
+ response = await fetchFn(url, fetchOptions);
+ } catch (e2) {
+ handleResponseError(e2, url);
+ }
+ if (!response.ok) {
+ await handleResponseNotOk(response, url);
+ }
+ return response;
+}
+function handleResponseError(e2, url) {
+ let err = e2;
+ if (err.name === "AbortError") {
+ err = new GoogleGenerativeAIAbortError(`Request aborted when fetching ${url.toString()}: ${e2.message}`);
+ err.stack = e2.stack;
+ } else if (!(e2 instanceof GoogleGenerativeAIFetchError || e2 instanceof GoogleGenerativeAIRequestInputError)) {
+ err = new GoogleGenerativeAIError(`Error fetching from ${url.toString()}: ${e2.message}`);
+ err.stack = e2.stack;
+ }
+ throw err;
+}
+async function handleResponseNotOk(response, url) {
+ let message = "";
+ let errorDetails;
+ try {
+ const json3 = await response.json();
+ message = json3.error.message;
+ if (json3.error.details) {
+ message += ` ${JSON.stringify(json3.error.details)}`;
+ errorDetails = json3.error.details;
+ }
+ } catch (e2) {}
+ throw new GoogleGenerativeAIFetchError(`Error fetching from ${url.toString()}: [${response.status} ${response.statusText}] ${message}`, response.status, response.statusText, errorDetails);
+}
+function buildFetchOptions(requestOptions) {
+ const fetchOptions = {};
+ if ((requestOptions === null || requestOptions === undefined ? undefined : requestOptions.signal) !== undefined || (requestOptions === null || requestOptions === undefined ? undefined : requestOptions.timeout) >= 0) {
+ const controller = new AbortController;
+ if ((requestOptions === null || requestOptions === undefined ? undefined : requestOptions.timeout) >= 0) {
+ setTimeout(() => controller.abort(), requestOptions.timeout);
+ }
+ if (requestOptions === null || requestOptions === undefined ? undefined : requestOptions.signal) {
+ requestOptions.signal.addEventListener("abort", () => {
+ controller.abort();
+ });
+ }
+ fetchOptions.signal = controller.signal;
+ }
+ return fetchOptions;
+}
+function addHelpers(response) {
+ response.text = () => {
+ if (response.candidates && response.candidates.length > 0) {
+ if (response.candidates.length > 1) {
+ console.warn(`This response had ${response.candidates.length} ` + `candidates. Returning text from the first candidate only. ` + `Access response.candidates directly to use the other candidates.`);
+ }
+ if (hadBadFinishReason(response.candidates[0])) {
+ throw new GoogleGenerativeAIResponseError(`${formatBlockErrorMessage(response)}`, response);
+ }
+ return getText(response);
+ } else if (response.promptFeedback) {
+ throw new GoogleGenerativeAIResponseError(`Text not available. ${formatBlockErrorMessage(response)}`, response);
+ }
+ return "";
+ };
+ response.functionCall = () => {
+ if (response.candidates && response.candidates.length > 0) {
+ if (response.candidates.length > 1) {
+ console.warn(`This response had ${response.candidates.length} ` + `candidates. Returning function calls from the first candidate only. ` + `Access response.candidates directly to use the other candidates.`);
+ }
+ if (hadBadFinishReason(response.candidates[0])) {
+ throw new GoogleGenerativeAIResponseError(`${formatBlockErrorMessage(response)}`, response);
+ }
+ console.warn(`response.functionCall() is deprecated. ` + `Use response.functionCalls() instead.`);
+ return getFunctionCalls(response)[0];
+ } else if (response.promptFeedback) {
+ throw new GoogleGenerativeAIResponseError(`Function call not available. ${formatBlockErrorMessage(response)}`, response);
+ }
+ return;
+ };
+ response.functionCalls = () => {
+ if (response.candidates && response.candidates.length > 0) {
+ if (response.candidates.length > 1) {
+ console.warn(`This response had ${response.candidates.length} ` + `candidates. Returning function calls from the first candidate only. ` + `Access response.candidates directly to use the other candidates.`);
+ }
+ if (hadBadFinishReason(response.candidates[0])) {
+ throw new GoogleGenerativeAIResponseError(`${formatBlockErrorMessage(response)}`, response);
+ }
+ return getFunctionCalls(response);
+ } else if (response.promptFeedback) {
+ throw new GoogleGenerativeAIResponseError(`Function call not available. ${formatBlockErrorMessage(response)}`, response);
+ }
+ return;
+ };
+ return response;
+}
+function getText(response) {
+ var _a, _b, _c, _d;
+ const textStrings = [];
+ if ((_b = (_a = response.candidates) === null || _a === undefined ? undefined : _a[0].content) === null || _b === undefined ? undefined : _b.parts) {
+ for (const part of (_d = (_c = response.candidates) === null || _c === undefined ? undefined : _c[0].content) === null || _d === undefined ? undefined : _d.parts) {
+ if (part.text) {
+ textStrings.push(part.text);
+ }
+ if (part.executableCode) {
+ textStrings.push("\n```" + part.executableCode.language + `
+` + part.executableCode.code + "\n```\n");
+ }
+ if (part.codeExecutionResult) {
+ textStrings.push("\n```\n" + part.codeExecutionResult.output + "\n```\n");
+ }
+ }
+ }
+ if (textStrings.length > 0) {
+ return textStrings.join("");
+ } else {
+ return "";
+ }
+}
+function getFunctionCalls(response) {
+ var _a, _b, _c, _d;
+ const functionCalls = [];
+ if ((_b = (_a = response.candidates) === null || _a === undefined ? undefined : _a[0].content) === null || _b === undefined ? undefined : _b.parts) {
+ for (const part of (_d = (_c = response.candidates) === null || _c === undefined ? undefined : _c[0].content) === null || _d === undefined ? undefined : _d.parts) {
+ if (part.functionCall) {
+ functionCalls.push(part.functionCall);
+ }
+ }
+ }
+ if (functionCalls.length > 0) {
+ return functionCalls;
+ } else {
+ return;
+ }
+}
+var badFinishReasons = [
+ FinishReason.RECITATION,
+ FinishReason.SAFETY,
+ FinishReason.LANGUAGE
+];
+function hadBadFinishReason(candidate) {
+ return !!candidate.finishReason && badFinishReasons.includes(candidate.finishReason);
+}
+function formatBlockErrorMessage(response) {
+ var _a, _b, _c;
+ let message = "";
+ if ((!response.candidates || response.candidates.length === 0) && response.promptFeedback) {
+ message += "Response was blocked";
+ if ((_a = response.promptFeedback) === null || _a === undefined ? undefined : _a.blockReason) {
+ message += ` due to ${response.promptFeedback.blockReason}`;
+ }
+ if ((_b = response.promptFeedback) === null || _b === undefined ? undefined : _b.blockReasonMessage) {
+ message += `: ${response.promptFeedback.blockReasonMessage}`;
+ }
+ } else if ((_c = response.candidates) === null || _c === undefined ? undefined : _c[0]) {
+ const firstCandidate = response.candidates[0];
+ if (hadBadFinishReason(firstCandidate)) {
+ message += `Candidate was blocked due to ${firstCandidate.finishReason}`;
+ if (firstCandidate.finishMessage) {
+ message += `: ${firstCandidate.finishMessage}`;
+ }
+ }
+ }
+ return message;
+}
+function __await(v) {
+ return this instanceof __await ? (this.v = v, this) : new __await(v);
+}
+function __asyncGenerator(thisArg, _arguments, generator) {
+ if (!Symbol.asyncIterator)
+ throw new TypeError("Symbol.asyncIterator is not defined.");
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
+ return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
+ return this;
+ }, i;
+ function verb(n) {
+ if (g[n])
+ i[n] = function(v) {
+ return new Promise(function(a, b) {
+ q.push([n, v, a, b]) > 1 || resume(n, v);
+ });
+ };
+ }
+ function resume(n, v) {
+ try {
+ step(g[n](v));
+ } catch (e2) {
+ settle(q[0][3], e2);
+ }
+ }
+ function step(r) {
+ r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);
+ }
+ function fulfill(value) {
+ resume("next", value);
+ }
+ function reject(value) {
+ resume("throw", value);
+ }
+ function settle(f, v) {
+ if (f(v), q.shift(), q.length)
+ resume(q[0][0], q[0][1]);
+ }
+}
+var responseLineRE = /^data\: (.*)(?:\n\n|\r\r|\r\n\r\n)/;
+function processStream(response) {
+ const inputStream = response.body.pipeThrough(new TextDecoderStream("utf8", { fatal: true }));
+ const responseStream = getResponseStream(inputStream);
+ const [stream1, stream2] = responseStream.tee();
+ return {
+ stream: generateResponseSequence(stream1),
+ response: getResponsePromise(stream2)
+ };
+}
+async function getResponsePromise(stream) {
+ const allResponses = [];
+ const reader = stream.getReader();
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) {
+ return addHelpers(aggregateResponses(allResponses));
+ }
+ allResponses.push(value);
+ }
+}
+function generateResponseSequence(stream) {
+ return __asyncGenerator(this, arguments, function* generateResponseSequence_1() {
+ const reader = stream.getReader();
+ while (true) {
+ const { value, done } = yield __await(reader.read());
+ if (done) {
+ break;
+ }
+ yield yield __await(addHelpers(value));
+ }
+ });
+}
+function getResponseStream(inputStream) {
+ const reader = inputStream.getReader();
+ const stream = new ReadableStream({
+ start(controller) {
+ let currentText = "";
+ return pump();
+ function pump() {
+ return reader.read().then(({ value, done }) => {
+ if (done) {
+ if (currentText.trim()) {
+ controller.error(new GoogleGenerativeAIError("Failed to parse stream"));
+ return;
+ }
+ controller.close();
+ return;
+ }
+ currentText += value;
+ let match = currentText.match(responseLineRE);
+ let parsedResponse;
+ while (match) {
+ try {
+ parsedResponse = JSON.parse(match[1]);
+ } catch (e2) {
+ controller.error(new GoogleGenerativeAIError(`Error parsing JSON response: "${match[1]}"`));
+ return;
+ }
+ controller.enqueue(parsedResponse);
+ currentText = currentText.substring(match[0].length);
+ match = currentText.match(responseLineRE);
+ }
+ return pump();
+ }).catch((e2) => {
+ let err = e2;
+ err.stack = e2.stack;
+ if (err.name === "AbortError") {
+ err = new GoogleGenerativeAIAbortError("Request aborted when reading from the stream");
+ } else {
+ err = new GoogleGenerativeAIError("Error reading from the stream");
+ }
+ throw err;
+ });
+ }
+ }
+ });
+ return stream;
+}
+function aggregateResponses(responses) {
+ const lastResponse = responses[responses.length - 1];
+ const aggregatedResponse = {
+ promptFeedback: lastResponse === null || lastResponse === undefined ? undefined : lastResponse.promptFeedback
+ };
+ for (const response of responses) {
+ if (response.candidates) {
+ let candidateIndex = 0;
+ for (const candidate of response.candidates) {
+ if (!aggregatedResponse.candidates) {
+ aggregatedResponse.candidates = [];
+ }
+ if (!aggregatedResponse.candidates[candidateIndex]) {
+ aggregatedResponse.candidates[candidateIndex] = {
+ index: candidateIndex
+ };
+ }
+ aggregatedResponse.candidates[candidateIndex].citationMetadata = candidate.citationMetadata;
+ aggregatedResponse.candidates[candidateIndex].groundingMetadata = candidate.groundingMetadata;
+ aggregatedResponse.candidates[candidateIndex].finishReason = candidate.finishReason;
+ aggregatedResponse.candidates[candidateIndex].finishMessage = candidate.finishMessage;
+ aggregatedResponse.candidates[candidateIndex].safetyRatings = candidate.safetyRatings;
+ if (candidate.content && candidate.content.parts) {
+ if (!aggregatedResponse.candidates[candidateIndex].content) {
+ aggregatedResponse.candidates[candidateIndex].content = {
+ role: candidate.content.role || "user",
+ parts: []
+ };
+ }
+ const newPart = {};
+ for (const part of candidate.content.parts) {
+ if (part.text) {
+ newPart.text = part.text;
+ }
+ if (part.functionCall) {
+ newPart.functionCall = part.functionCall;
+ }
+ if (part.executableCode) {
+ newPart.executableCode = part.executableCode;
+ }
+ if (part.codeExecutionResult) {
+ newPart.codeExecutionResult = part.codeExecutionResult;
+ }
+ if (Object.keys(newPart).length === 0) {
+ newPart.text = "";
+ }
+ aggregatedResponse.candidates[candidateIndex].content.parts.push(newPart);
+ }
+ }
+ }
+ candidateIndex++;
+ }
+ if (response.usageMetadata) {
+ aggregatedResponse.usageMetadata = response.usageMetadata;
+ }
+ }
+ return aggregatedResponse;
+}
+async function generateContentStream(apiKey, model, params, requestOptions) {
+ const response = await makeModelRequest(model, Task.STREAM_GENERATE_CONTENT, apiKey, true, JSON.stringify(params), requestOptions);
+ return processStream(response);
+}
+async function generateContent(apiKey, model, params, requestOptions) {
+ const response = await makeModelRequest(model, Task.GENERATE_CONTENT, apiKey, false, JSON.stringify(params), requestOptions);
+ const responseJson = await response.json();
+ const enhancedResponse = addHelpers(responseJson);
+ return {
+ response: enhancedResponse
+ };
+}
+function formatSystemInstruction(input) {
+ if (input == null) {
+ return;
+ } else if (typeof input === "string") {
+ return { role: "system", parts: [{ text: input }] };
+ } else if (input.text) {
+ return { role: "system", parts: [input] };
+ } else if (input.parts) {
+ if (!input.role) {
+ return { role: "system", parts: input.parts };
+ } else {
+ return input;
+ }
+ }
+}
+function formatNewContent(request) {
+ let newParts = [];
+ if (typeof request === "string") {
+ newParts = [{ text: request }];
+ } else {
+ for (const partOrString of request) {
+ if (typeof partOrString === "string") {
+ newParts.push({ text: partOrString });
+ } else {
+ newParts.push(partOrString);
+ }
+ }
+ }
+ return assignRoleToPartsAndValidateSendMessageRequest(newParts);
+}
+function assignRoleToPartsAndValidateSendMessageRequest(parts) {
+ const userContent = { role: "user", parts: [] };
+ const functionContent = { role: "function", parts: [] };
+ let hasUserContent = false;
+ let hasFunctionContent = false;
+ for (const part of parts) {
+ if ("functionResponse" in part) {
+ functionContent.parts.push(part);
+ hasFunctionContent = true;
+ } else {
+ userContent.parts.push(part);
+ hasUserContent = true;
+ }
+ }
+ if (hasUserContent && hasFunctionContent) {
+ throw new GoogleGenerativeAIError("Within a single message, FunctionResponse cannot be mixed with other type of part in the request for sending chat message.");
+ }
+ if (!hasUserContent && !hasFunctionContent) {
+ throw new GoogleGenerativeAIError("No content is provided for sending chat message.");
+ }
+ if (hasUserContent) {
+ return userContent;
+ }
+ return functionContent;
+}
+function formatCountTokensInput(params, modelParams) {
+ var _a;
+ let formattedGenerateContentRequest = {
+ model: modelParams === null || modelParams === undefined ? undefined : modelParams.model,
+ generationConfig: modelParams === null || modelParams === undefined ? undefined : modelParams.generationConfig,
+ safetySettings: modelParams === null || modelParams === undefined ? undefined : modelParams.safetySettings,
+ tools: modelParams === null || modelParams === undefined ? undefined : modelParams.tools,
+ toolConfig: modelParams === null || modelParams === undefined ? undefined : modelParams.toolConfig,
+ systemInstruction: modelParams === null || modelParams === undefined ? undefined : modelParams.systemInstruction,
+ cachedContent: (_a = modelParams === null || modelParams === undefined ? undefined : modelParams.cachedContent) === null || _a === undefined ? undefined : _a.name,
+ contents: []
+ };
+ const containsGenerateContentRequest = params.generateContentRequest != null;
+ if (params.contents) {
+ if (containsGenerateContentRequest) {
+ throw new GoogleGenerativeAIRequestInputError("CountTokensRequest must have one of contents or generateContentRequest, not both.");
+ }
+ formattedGenerateContentRequest.contents = params.contents;
+ } else if (containsGenerateContentRequest) {
+ formattedGenerateContentRequest = Object.assign(Object.assign({}, formattedGenerateContentRequest), params.generateContentRequest);
+ } else {
+ const content = formatNewContent(params);
+ formattedGenerateContentRequest.contents = [content];
+ }
+ return { generateContentRequest: formattedGenerateContentRequest };
+}
+function formatGenerateContentInput(params) {
+ let formattedRequest;
+ if (params.contents) {
+ formattedRequest = params;
+ } else {
+ const content = formatNewContent(params);
+ formattedRequest = { contents: [content] };
+ }
+ if (params.systemInstruction) {
+ formattedRequest.systemInstruction = formatSystemInstruction(params.systemInstruction);
+ }
+ return formattedRequest;
+}
+function formatEmbedContentInput(params) {
+ if (typeof params === "string" || Array.isArray(params)) {
+ const content = formatNewContent(params);
+ return { content };
+ }
+ return params;
+}
+var VALID_PART_FIELDS = [
+ "text",
+ "inlineData",
+ "functionCall",
+ "functionResponse",
+ "executableCode",
+ "codeExecutionResult"
+];
+var VALID_PARTS_PER_ROLE = {
+ user: ["text", "inlineData"],
+ function: ["functionResponse"],
+ model: ["text", "functionCall", "executableCode", "codeExecutionResult"],
+ system: ["text"]
+};
+function validateChatHistory(history) {
+ let prevContent = false;
+ for (const currContent of history) {
+ const { role, parts } = currContent;
+ if (!prevContent && role !== "user") {
+ throw new GoogleGenerativeAIError(`First content should be with role 'user', got ${role}`);
+ }
+ if (!POSSIBLE_ROLES.includes(role)) {
+ throw new GoogleGenerativeAIError(`Each item should include role field. Got ${role} but valid roles are: ${JSON.stringify(POSSIBLE_ROLES)}`);
+ }
+ if (!Array.isArray(parts)) {
+ throw new GoogleGenerativeAIError("Content should have 'parts' property with an array of Parts");
+ }
+ if (parts.length === 0) {
+ throw new GoogleGenerativeAIError("Each Content should have at least one part");
+ }
+ const countFields = {
+ text: 0,
+ inlineData: 0,
+ functionCall: 0,
+ functionResponse: 0,
+ fileData: 0,
+ executableCode: 0,
+ codeExecutionResult: 0
+ };
+ for (const part of parts) {
+ for (const key of VALID_PART_FIELDS) {
+ if (key in part) {
+ countFields[key] += 1;
+ }
+ }
+ }
+ const validParts = VALID_PARTS_PER_ROLE[role];
+ for (const key of VALID_PART_FIELDS) {
+ if (!validParts.includes(key) && countFields[key] > 0) {
+ throw new GoogleGenerativeAIError(`Content with role '${role}' can't contain '${key}' part`);
+ }
+ }
+ prevContent = true;
+ }
+}
+function isValidResponse(response) {
+ var _a;
+ if (response.candidates === undefined || response.candidates.length === 0) {
+ return false;
+ }
+ const content = (_a = response.candidates[0]) === null || _a === undefined ? undefined : _a.content;
+ if (content === undefined) {
+ return false;
+ }
+ if (content.parts === undefined || content.parts.length === 0) {
+ return false;
+ }
+ for (const part of content.parts) {
+ if (part === undefined || Object.keys(part).length === 0) {
+ return false;
+ }
+ if (part.text !== undefined && part.text === "") {
+ return false;
+ }
+ }
+ return true;
+}
+var SILENT_ERROR = "SILENT_ERROR";
+
+class ChatSession {
+ constructor(apiKey, model, params, _requestOptions = {}) {
+ this.model = model;
+ this.params = params;
+ this._requestOptions = _requestOptions;
+ this._history = [];
+ this._sendPromise = Promise.resolve();
+ this._apiKey = apiKey;
+ if (params === null || params === undefined ? undefined : params.history) {
+ validateChatHistory(params.history);
+ this._history = params.history;
+ }
+ }
+ async getHistory() {
+ await this._sendPromise;
+ return this._history;
+ }
+ async sendMessage(request, requestOptions = {}) {
+ var _a, _b, _c, _d, _e, _f;
+ await this._sendPromise;
+ const newContent = formatNewContent(request);
+ const generateContentRequest = {
+ safetySettings: (_a = this.params) === null || _a === undefined ? undefined : _a.safetySettings,
+ generationConfig: (_b = this.params) === null || _b === undefined ? undefined : _b.generationConfig,
+ tools: (_c = this.params) === null || _c === undefined ? undefined : _c.tools,
+ toolConfig: (_d = this.params) === null || _d === undefined ? undefined : _d.toolConfig,
+ systemInstruction: (_e = this.params) === null || _e === undefined ? undefined : _e.systemInstruction,
+ cachedContent: (_f = this.params) === null || _f === undefined ? undefined : _f.cachedContent,
+ contents: [...this._history, newContent]
+ };
+ const chatSessionRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
+ let finalResult;
+ this._sendPromise = this._sendPromise.then(() => generateContent(this._apiKey, this.model, generateContentRequest, chatSessionRequestOptions)).then((result) => {
+ var _a2;
+ if (isValidResponse(result.response)) {
+ this._history.push(newContent);
+ const responseContent = Object.assign({
+ parts: [],
+ role: "model"
+ }, (_a2 = result.response.candidates) === null || _a2 === undefined ? undefined : _a2[0].content);
+ this._history.push(responseContent);
+ } else {
+ const blockErrorMessage = formatBlockErrorMessage(result.response);
+ if (blockErrorMessage) {
+ console.warn(`sendMessage() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.`);
+ }
+ }
+ finalResult = result;
+ }).catch((e2) => {
+ this._sendPromise = Promise.resolve();
+ throw e2;
+ });
+ await this._sendPromise;
+ return finalResult;
+ }
+ async sendMessageStream(request, requestOptions = {}) {
+ var _a, _b, _c, _d, _e, _f;
+ await this._sendPromise;
+ const newContent = formatNewContent(request);
+ const generateContentRequest = {
+ safetySettings: (_a = this.params) === null || _a === undefined ? undefined : _a.safetySettings,
+ generationConfig: (_b = this.params) === null || _b === undefined ? undefined : _b.generationConfig,
+ tools: (_c = this.params) === null || _c === undefined ? undefined : _c.tools,
+ toolConfig: (_d = this.params) === null || _d === undefined ? undefined : _d.toolConfig,
+ systemInstruction: (_e = this.params) === null || _e === undefined ? undefined : _e.systemInstruction,
+ cachedContent: (_f = this.params) === null || _f === undefined ? undefined : _f.cachedContent,
+ contents: [...this._history, newContent]
+ };
+ const chatSessionRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
+ const streamPromise = generateContentStream(this._apiKey, this.model, generateContentRequest, chatSessionRequestOptions);
+ this._sendPromise = this._sendPromise.then(() => streamPromise).catch((_ignored) => {
+ throw new Error(SILENT_ERROR);
+ }).then((streamResult) => streamResult.response).then((response) => {
+ if (isValidResponse(response)) {
+ this._history.push(newContent);
+ const responseContent = Object.assign({}, response.candidates[0].content);
+ if (!responseContent.role) {
+ responseContent.role = "model";
+ }
+ this._history.push(responseContent);
+ } else {
+ const blockErrorMessage = formatBlockErrorMessage(response);
+ if (blockErrorMessage) {
+ console.warn(`sendMessageStream() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.`);
+ }
+ }
+ }).catch((e2) => {
+ if (e2.message !== SILENT_ERROR) {
+ console.error(e2);
+ }
+ });
+ return streamPromise;
+ }
+}
+async function countTokens(apiKey, model, params, singleRequestOptions) {
+ const response = await makeModelRequest(model, Task.COUNT_TOKENS, apiKey, false, JSON.stringify(params), singleRequestOptions);
+ return response.json();
+}
+async function embedContent(apiKey, model, params, requestOptions) {
+ const response = await makeModelRequest(model, Task.EMBED_CONTENT, apiKey, false, JSON.stringify(params), requestOptions);
+ return response.json();
+}
+async function batchEmbedContents(apiKey, model, params, requestOptions) {
+ const requestsWithModel = params.requests.map((request) => {
+ return Object.assign(Object.assign({}, request), { model });
+ });
+ const response = await makeModelRequest(model, Task.BATCH_EMBED_CONTENTS, apiKey, false, JSON.stringify({ requests: requestsWithModel }), requestOptions);
+ return response.json();
+}
+
+class GenerativeModel {
+ constructor(apiKey, modelParams, _requestOptions = {}) {
+ this.apiKey = apiKey;
+ this._requestOptions = _requestOptions;
+ if (modelParams.model.includes("/")) {
+ this.model = modelParams.model;
+ } else {
+ this.model = `models/${modelParams.model}`;
+ }
+ this.generationConfig = modelParams.generationConfig || {};
+ this.safetySettings = modelParams.safetySettings || [];
+ this.tools = modelParams.tools;
+ this.toolConfig = modelParams.toolConfig;
+ this.systemInstruction = formatSystemInstruction(modelParams.systemInstruction);
+ this.cachedContent = modelParams.cachedContent;
+ }
+ async generateContent(request, requestOptions = {}) {
+ var _a;
+ const formattedParams = formatGenerateContentInput(request);
+ const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
+ return generateContent(this.apiKey, this.model, Object.assign({ generationConfig: this.generationConfig, safetySettings: this.safetySettings, tools: this.tools, toolConfig: this.toolConfig, systemInstruction: this.systemInstruction, cachedContent: (_a = this.cachedContent) === null || _a === undefined ? undefined : _a.name }, formattedParams), generativeModelRequestOptions);
+ }
+ async generateContentStream(request, requestOptions = {}) {
+ var _a;
+ const formattedParams = formatGenerateContentInput(request);
+ const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
+ return generateContentStream(this.apiKey, this.model, Object.assign({ generationConfig: this.generationConfig, safetySettings: this.safetySettings, tools: this.tools, toolConfig: this.toolConfig, systemInstruction: this.systemInstruction, cachedContent: (_a = this.cachedContent) === null || _a === undefined ? undefined : _a.name }, formattedParams), generativeModelRequestOptions);
+ }
+ startChat(startChatParams) {
+ var _a;
+ return new ChatSession(this.apiKey, this.model, Object.assign({ generationConfig: this.generationConfig, safetySettings: this.safetySettings, tools: this.tools, toolConfig: this.toolConfig, systemInstruction: this.systemInstruction, cachedContent: (_a = this.cachedContent) === null || _a === undefined ? undefined : _a.name }, startChatParams), this._requestOptions);
+ }
+ async countTokens(request, requestOptions = {}) {
+ const formattedParams = formatCountTokensInput(request, {
+ model: this.model,
+ generationConfig: this.generationConfig,
+ safetySettings: this.safetySettings,
+ tools: this.tools,
+ toolConfig: this.toolConfig,
+ systemInstruction: this.systemInstruction,
+ cachedContent: this.cachedContent
+ });
+ const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
+ return countTokens(this.apiKey, this.model, formattedParams, generativeModelRequestOptions);
+ }
+ async embedContent(request, requestOptions = {}) {
+ const formattedParams = formatEmbedContentInput(request);
+ const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
+ return embedContent(this.apiKey, this.model, formattedParams, generativeModelRequestOptions);
+ }
+ async batchEmbedContents(batchEmbedContentRequest, requestOptions = {}) {
+ const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
+ return batchEmbedContents(this.apiKey, this.model, batchEmbedContentRequest, generativeModelRequestOptions);
+ }
+}
+
+class GoogleGenerativeAI {
+ constructor(apiKey) {
+ this.apiKey = apiKey;
+ }
+ getGenerativeModel(modelParams, requestOptions) {
+ if (!modelParams.model) {
+ throw new GoogleGenerativeAIError(`Must provide a model name. ` + `Example: genai.getGenerativeModel({ model: 'my-model-name' })`);
+ }
+ return new GenerativeModel(this.apiKey, modelParams, requestOptions);
+ }
+ getGenerativeModelFromCachedContent(cachedContent, modelParams, requestOptions) {
+ if (!cachedContent.name) {
+ throw new GoogleGenerativeAIRequestInputError("Cached content must contain a `name` field.");
+ }
+ if (!cachedContent.model) {
+ throw new GoogleGenerativeAIRequestInputError("Cached content must contain a `model` field.");
+ }
+ const disallowedDuplicates = ["model", "systemInstruction"];
+ for (const key of disallowedDuplicates) {
+ if ((modelParams === null || modelParams === undefined ? undefined : modelParams[key]) && cachedContent[key] && (modelParams === null || modelParams === undefined ? undefined : modelParams[key]) !== cachedContent[key]) {
+ if (key === "model") {
+ const modelParamsComp = modelParams.model.startsWith("models/") ? modelParams.model.replace("models/", "") : modelParams.model;
+ const cachedContentComp = cachedContent.model.startsWith("models/") ? cachedContent.model.replace("models/", "") : cachedContent.model;
+ if (modelParamsComp === cachedContentComp) {
+ continue;
+ }
+ }
+ throw new GoogleGenerativeAIRequestInputError(`Different value for "${key}" specified in modelParams` + ` (${modelParams[key]}) and cachedContent (${cachedContent[key]})`);
+ }
+ }
+ const modelParamsFromCache = Object.assign(Object.assign({}, modelParams), { model: cachedContent.model, tools: cachedContent.tools, toolConfig: cachedContent.toolConfig, systemInstruction: cachedContent.systemInstruction, cachedContent });
+ return new GenerativeModel(this.apiKey, modelParamsFromCache, requestOptions);
+ }
+}
+
// src/api/problem/problem-helper.ts
var verifyProblemCreationPermission = async (userId) => {
const users = await db.select().from(user).where(eq(user.id, userId));
@@ -164333,6 +145372,75 @@ var verifyProblemCreationPermission = async (userId) => {
throw new Error("You do not have permission to create problems");
}
};
+var genAI = new GoogleGenerativeAI(config_default.GEMINI_API_KEY);
+var model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
+async function generateHintsWithAI(problem3) {
+ const prompt = `
+ You are an expert programming tutor for a competitive programming platform called "codesm".
+ Your task is to provide a series of high-quality, step-by-step hints for the following programming problem.
+
+ **RULES:**
+ 1. **DO NOT** provide the final code solution or large snippets of code in any language. Your goal is to guide, not to solve.
+ 2. Break down the solution into 4 logical steps or hints.
+ 3. The hints must be progressive. Start with a high-level conceptual hint and gradually get more specific.
+ 4. The final hint can suggest the main algorithm, data structure, or key observation needed to solve the problem efficiently (e.g., "Consider using a hash map to track frequencies" or "Think about a two-pointer approach").
+ 5. Tailor the tone and complexity of the hints based on the problem's **difficulty** and **tags**.
+ 6. The response **MUST** be a valid JSON object. Do not include any markdown formatting (like \`\`\`) or any text outside of the JSON structure.
+
+ **OUTPUT FORMAT:**
+ Your output must be a JSON object with a single key "hints", which is an array of hint objects. Each hint object must have a "title" and a "content" key.
+ Example format:
+ {
+ "hints": [
+ {
+ "title": "Understanding the Problem",
+ "content": "First, make sure you understand what the input represents and what the expected output should be. Look at the examples carefully.",
+ "order": "1",
+ },
+ {
+ "title": "Thinking about the Logic",
+ "content": "Think about the logic of the problem and how you can solve it efficiently.",
+ "order": "2",
+ },
+ {
+ "title": "Choosing the Right Approach",
+ "content": "What data structure would be efficient for storing and retrieving data quickly?",
+ "order": "3",
+ },
+ {
+ "title": "Let's Try Coding",
+ "content": "Try to code the solution using the hints above. If you get stuck, come back and we'll help you further!",
+ "order": "4",
+ }
+ ]
+ }
+
+ **PROBLEM TO ANALYZE:**
+ Title: ${problem3.title}
+ Difficulty (800-3000): ${problem3.difficulty}
+ Description: ${problem3.description}
+ Input Format: ${problem3.inputFormat}
+ Output Format: ${problem3.outputFormat}
+ Constraints: ${problem3.constraints}
+ `;
+ try {
+ const result = await model.generateContent(prompt);
+ const response = await result.response;
+ const text3 = response.text().replace(/```json/g, "").replace(/```/g, "").trim();
+ const parsedResult = JSON.parse(text3);
+ if (!parsedResult.hints || !Array.isArray(parsedResult.hints)) {
+ throw new Error("AI response did not follow the expected JSON format.");
+ }
+ return parsedResult.hints;
+ } catch (error) {
+ console.error("AI Generation Error:", error);
+ return [{
+ title: "Hints Unavailable",
+ content: "We couldn't generate hints for this problem at the moment. Please try again later or check the editorial.",
+ order: 0
+ }];
+ }
+}
// node_modules/.pnpm/@aws-sdk+middleware-expect-continue@3.972.10/node_modules/@aws-sdk/middleware-expect-continue/dist-es/index.js
var import_protocol_http = __toESM(require_dist_cjs2(), 1);
@@ -164500,8 +145608,8 @@ var {
__spread,
__spreadArrays,
__spreadArray,
- __await,
- __asyncGenerator,
+ __await: __await2,
+ __asyncGenerator: __asyncGenerator2,
__asyncDelegator,
__asyncValues,
__makeTemplateObject,
@@ -165892,15 +147000,15 @@ class S3ExpressIdentityProviderImpl {
console.warn(`Error while clearing expired entries in S3ExpressIdentityCache:
` + error);
});
- const session2 = await this.createSessionFn(key);
- if (!session2.Credentials?.AccessKeyId || !session2.Credentials?.SecretAccessKey) {
+ const session3 = await this.createSessionFn(key);
+ if (!session3.Credentials?.AccessKeyId || !session3.Credentials?.SecretAccessKey) {
throw new Error("s3#createSession response credential missing AccessKeyId or SecretAccessKey.");
}
const identity = {
- accessKeyId: session2.Credentials.AccessKeyId,
- secretAccessKey: session2.Credentials.SecretAccessKey,
- sessionToken: session2.Credentials.SessionToken,
- expiration: session2.Credentials.Expiration ? new Date(session2.Credentials.Expiration) : undefined
+ accessKeyId: session3.Credentials.AccessKeyId,
+ secretAccessKey: session3.Credentials.SecretAccessKey,
+ sessionToken: session3.Credentials.SessionToken,
+ expiration: session3.Credentials.Expiration ? new Date(session3.Credentials.Expiration) : undefined
};
return identity;
}
@@ -166051,8 +147159,8 @@ var getS3ExpressHttpSigningPlugin = (config) => ({
}
});
// node_modules/.pnpm/@aws-sdk+middleware-sdk-s3@3.972.30/node_modules/@aws-sdk/middleware-sdk-s3/dist-es/s3Configuration.js
-var resolveS3Config = (input, { session: session2 }) => {
- const [s3ClientProvider, CreateSessionCommandCtor] = session2;
+var resolveS3Config = (input, { session: session3 }) => {
+ const [s3ClientProvider, CreateSessionCommandCtor] = session3;
const { forcePathStyle, useAccelerateEndpoint, disableMultiregionAccessPoints, followRegionRedirects, s3ExpressIdentityProvider, bucketEndpoint, expectContinueHeader } = input;
return Object.assign(input, {
forcePathStyle: forcePathStyle ?? false,
@@ -166197,7 +147305,7 @@ var getValidateBucketNamePlugin = (options) => ({
});
// node_modules/.pnpm/@aws-sdk+middleware-sdk-s3@3.972.30/node_modules/@aws-sdk/middleware-sdk-s3/dist-es/protocol/S3RestXmlProtocol.js
var import_protocols = __toESM(require_protocols2(), 1);
-var import_schema6 = __toESM(require_schema3(), 1);
+var import_schema6 = __toESM(require_schema(), 1);
class S3RestXmlProtocol extends import_protocols.AwsRestXmlProtocol {
async serializeRequest(operationSchema, input, context) {
@@ -166226,7 +147334,7 @@ class S3RestXmlProtocol extends import_protocols.AwsRestXmlProtocol {
var import_middleware_user_agent = __toESM(require_dist_cjs31(), 1);
var import_config_resolver2 = __toESM(require_dist_cjs32(), 1);
var import_core3 = __toESM(require_dist_cjs24(), 1);
-var import_schema8 = __toESM(require_schema3(), 1);
+var import_schema8 = __toESM(require_schema(), 1);
// node_modules/.pnpm/@smithy+eventstream-serde-config-resolver@4.3.14/node_modules/@smithy/eventstream-serde-config-resolver/dist-es/EventStreamSerdeConfig.js
var resolveEventStreamSerdeConfig = (input) => Object.assign(input, {
@@ -166714,7 +147822,7 @@ var commonParams = {
};
// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/schemas/schemas_0.js
-var import_schema7 = __toESM(require_schema3(), 1);
+var import_schema7 = __toESM(require_schema(), 1);
// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/models/S3ServiceException.js
var import_smithy_client3 = __toESM(require_dist_cjs21(), 1);
@@ -172105,1876 +153213,17844 @@ var WriteGetObjectResponse$ = [
() => __Unit
];
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/commands/CreateSessionCommand.js
-class CreateSessionCommand extends import_smithy_client4.Command.classBuilder().ep({
- ...commonParams,
- DisableS3ExpressSessionAuth: { type: "staticContextParams", value: true },
- Bucket: { type: "contextParams", name: "Bucket" }
-}).m(function(Command, cs2, config, o2) {
- return [
- import_middleware_endpoint2.getEndpointPlugin(config, Command.getEndpointParameterInstructions()),
- getThrow200ExceptionsPlugin(config)
- ];
-}).s("AmazonS3", "CreateSession", {}).n("S3Client", "CreateSessionCommand").sc(CreateSession$).build() {
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/commands/CreateSessionCommand.js
+class CreateSessionCommand extends import_smithy_client4.Command.classBuilder().ep({
+ ...commonParams,
+ DisableS3ExpressSessionAuth: { type: "staticContextParams", value: true },
+ Bucket: { type: "contextParams", name: "Bucket" }
+}).m(function(Command, cs2, config, o2) {
+ return [
+ import_middleware_endpoint2.getEndpointPlugin(config, Command.getEndpointParameterInstructions()),
+ getThrow200ExceptionsPlugin(config)
+ ];
+}).s("AmazonS3", "CreateSession", {}).n("S3Client", "CreateSessionCommand").sc(CreateSession$).build() {
+}
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/package.json
+var package_default = {
+ name: "@aws-sdk/client-s3",
+ description: "AWS SDK for JavaScript S3 Client for Node.js, Browser and React Native",
+ version: "3.1032.0",
+ scripts: {
+ build: "concurrently 'yarn:build:types' 'yarn:build:es' && yarn build:cjs",
+ "build:cjs": "node ../../scripts/compilation/inline client-s3",
+ "build:es": "tsc -p tsconfig.es.json",
+ "build:include:deps": 'yarn g:turbo run build -F="$npm_package_name"',
+ "build:types": "tsc -p tsconfig.types.json",
+ "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4",
+ clean: "premove dist-cjs dist-es dist-types tsconfig.cjs.tsbuildinfo tsconfig.es.tsbuildinfo tsconfig.types.tsbuildinfo",
+ "extract:docs": "api-extractor run --local",
+ "generate:client": "node ../../scripts/generate-clients/single-service --solo s3",
+ test: "yarn g:vitest run",
+ "test:browser": "node ./test/browser-build/esbuild && yarn g:vitest run -c vitest.config.browser.mts",
+ "test:browser:watch": "node ./test/browser-build/esbuild && yarn g:vitest watch -c vitest.config.browser.mts",
+ "test:e2e": "yarn g:vitest run -c vitest.config.e2e.mts && yarn test:browser",
+ "test:e2e:watch": "yarn g:vitest watch -c vitest.config.e2e.mts",
+ "test:index": "tsc --noEmit ./test/index-types.ts && node ./test/index-objects.spec.mjs",
+ "test:integration": "yarn g:vitest run -c vitest.config.integ.mts",
+ "test:integration:watch": "yarn g:vitest watch -c vitest.config.integ.mts",
+ "test:watch": "yarn g:vitest watch"
+ },
+ main: "./dist-cjs/index.js",
+ types: "./dist-types/index.d.ts",
+ module: "./dist-es/index.js",
+ sideEffects: false,
+ dependencies: {
+ "@aws-crypto/sha1-browser": "5.2.0",
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.974.1",
+ "@aws-sdk/credential-provider-node": "^3.972.32",
+ "@aws-sdk/middleware-bucket-endpoint": "^3.972.10",
+ "@aws-sdk/middleware-expect-continue": "^3.972.10",
+ "@aws-sdk/middleware-flexible-checksums": "^3.974.9",
+ "@aws-sdk/middleware-host-header": "^3.972.10",
+ "@aws-sdk/middleware-location-constraint": "^3.972.10",
+ "@aws-sdk/middleware-logger": "^3.972.10",
+ "@aws-sdk/middleware-recursion-detection": "^3.972.11",
+ "@aws-sdk/middleware-sdk-s3": "^3.972.30",
+ "@aws-sdk/middleware-ssec": "^3.972.10",
+ "@aws-sdk/middleware-user-agent": "^3.972.31",
+ "@aws-sdk/region-config-resolver": "^3.972.12",
+ "@aws-sdk/signature-v4-multi-region": "^3.996.18",
+ "@aws-sdk/types": "^3.973.8",
+ "@aws-sdk/util-endpoints": "^3.996.7",
+ "@aws-sdk/util-user-agent-browser": "^3.972.10",
+ "@aws-sdk/util-user-agent-node": "^3.973.17",
+ "@smithy/config-resolver": "^4.4.16",
+ "@smithy/core": "^3.23.15",
+ "@smithy/eventstream-serde-browser": "^4.2.14",
+ "@smithy/eventstream-serde-config-resolver": "^4.3.14",
+ "@smithy/eventstream-serde-node": "^4.2.14",
+ "@smithy/fetch-http-handler": "^5.3.17",
+ "@smithy/hash-blob-browser": "^4.2.15",
+ "@smithy/hash-node": "^4.2.14",
+ "@smithy/hash-stream-node": "^4.2.14",
+ "@smithy/invalid-dependency": "^4.2.14",
+ "@smithy/md5-js": "^4.2.14",
+ "@smithy/middleware-content-length": "^4.2.14",
+ "@smithy/middleware-endpoint": "^4.4.30",
+ "@smithy/middleware-retry": "^4.5.3",
+ "@smithy/middleware-serde": "^4.2.18",
+ "@smithy/middleware-stack": "^4.2.14",
+ "@smithy/node-config-provider": "^4.3.14",
+ "@smithy/node-http-handler": "^4.5.3",
+ "@smithy/protocol-http": "^5.3.14",
+ "@smithy/smithy-client": "^4.12.11",
+ "@smithy/types": "^4.14.1",
+ "@smithy/url-parser": "^4.2.14",
+ "@smithy/util-base64": "^4.3.2",
+ "@smithy/util-body-length-browser": "^4.2.2",
+ "@smithy/util-body-length-node": "^4.2.3",
+ "@smithy/util-defaults-mode-browser": "^4.3.47",
+ "@smithy/util-defaults-mode-node": "^4.2.52",
+ "@smithy/util-endpoints": "^3.4.1",
+ "@smithy/util-middleware": "^4.2.14",
+ "@smithy/util-retry": "^4.3.2",
+ "@smithy/util-stream": "^4.5.23",
+ "@smithy/util-utf8": "^4.2.2",
+ "@smithy/util-waiter": "^4.2.16",
+ tslib: "^2.6.2"
+ },
+ devDependencies: {
+ "@aws-sdk/signature-v4-crt": "3.1032.0",
+ "@smithy/snapshot-testing": "^2.0.6",
+ "@tsconfig/node20": "20.1.8",
+ "@types/node": "^20.14.8",
+ concurrently: "7.0.0",
+ "downlevel-dts": "0.10.1",
+ premove: "4.0.0",
+ typescript: "~5.8.3",
+ vitest: "^4.0.17"
+ },
+ engines: {
+ node: ">=20.0.0"
+ },
+ typesVersions: {
+ "<4.5": {
+ "dist-types/*": [
+ "dist-types/ts3.4/*"
+ ]
+ }
+ },
+ files: [
+ "dist-*/**"
+ ],
+ author: {
+ name: "AWS SDK for JavaScript Team",
+ url: "https://aws.amazon.com/javascript/"
+ },
+ license: "Apache-2.0",
+ browser: {
+ "./dist-es/runtimeConfig": "./dist-es/runtimeConfig.browser"
+ },
+ "react-native": {
+ "./dist-es/runtimeConfig": "./dist-es/runtimeConfig.native"
+ },
+ homepage: "https://github.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3",
+ repository: {
+ type: "git",
+ url: "https://github.com/aws/aws-sdk-js-v3.git",
+ directory: "clients/client-s3"
+ }
+};
+
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.js
+var import_client17 = __toESM(require_client3(), 1);
+var import_httpAuthSchemes3 = __toESM(require_httpAuthSchemes(), 1);
+
+// node_modules/.pnpm/@aws-sdk+credential-provider-node@3.972.32/node_modules/@aws-sdk/credential-provider-node/dist-es/defaultProvider.js
+init_dist_es();
+var import_property_provider23 = __toESM(require_dist_cjs34(), 1);
+var import_shared_ini_file_loader12 = __toESM(require_dist_cjs35(), 1);
+
+// node_modules/.pnpm/@aws-sdk+credential-provider-node@3.972.32/node_modules/@aws-sdk/credential-provider-node/dist-es/remoteProvider.js
+var import_property_provider9 = __toESM(require_dist_cjs34(), 1);
+var ENV_IMDS_DISABLED = "AWS_EC2_METADATA_DISABLED";
+var remoteProvider = async (init3) => {
+ const { ENV_CMDS_FULL_URI: ENV_CMDS_FULL_URI2, ENV_CMDS_RELATIVE_URI: ENV_CMDS_RELATIVE_URI2, fromContainerMetadata: fromContainerMetadata3, fromInstanceMetadata: fromInstanceMetadata3 } = await Promise.resolve().then(() => (init_dist_es2(), exports_dist_es2));
+ if (process.env[ENV_CMDS_RELATIVE_URI2] || process.env[ENV_CMDS_FULL_URI2]) {
+ init3.logger?.debug("@aws-sdk/credential-provider-node - remoteProvider::fromHttp/fromContainerMetadata");
+ const { fromHttp: fromHttp2 } = await Promise.resolve().then(() => (init_dist_es3(), exports_dist_es3));
+ return import_property_provider9.chain(fromHttp2(init3), fromContainerMetadata3(init3));
+ }
+ if (process.env[ENV_IMDS_DISABLED] && process.env[ENV_IMDS_DISABLED] !== "false") {
+ return async () => {
+ throw new import_property_provider9.CredentialsProviderError("EC2 Instance Metadata Service access disabled", { logger: init3.logger });
+ };
+ }
+ init3.logger?.debug("@aws-sdk/credential-provider-node - remoteProvider::fromInstanceMetadata");
+ return fromInstanceMetadata3(init3);
+};
+
+// node_modules/.pnpm/@aws-sdk+credential-provider-node@3.972.32/node_modules/@aws-sdk/credential-provider-node/dist-es/runtime/memoize-chain.js
+function memoizeChain(providers, treatAsExpired) {
+ const chain2 = internalCreateChain(providers);
+ let activeLock;
+ let passiveLock;
+ let credentials;
+ const provider = async (options) => {
+ if (options?.forceRefresh) {
+ return await chain2(options);
+ }
+ if (credentials?.expiration) {
+ if (credentials?.expiration?.getTime() < Date.now()) {
+ credentials = undefined;
+ }
+ }
+ if (activeLock) {
+ await activeLock;
+ } else if (!credentials || treatAsExpired?.(credentials)) {
+ if (credentials) {
+ if (!passiveLock) {
+ passiveLock = chain2(options).then((c2) => {
+ credentials = c2;
+ }).finally(() => {
+ passiveLock = undefined;
+ });
+ }
+ } else {
+ activeLock = chain2(options).then((c2) => {
+ credentials = c2;
+ }).finally(() => {
+ activeLock = undefined;
+ });
+ return provider(options);
+ }
+ }
+ return credentials;
+ };
+ return provider;
+}
+var internalCreateChain = (providers) => async (awsIdentityProperties) => {
+ let lastProviderError;
+ for (const provider of providers) {
+ try {
+ return await provider(awsIdentityProperties);
+ } catch (err) {
+ lastProviderError = err;
+ if (err?.tryNextLink) {
+ continue;
+ }
+ throw err;
+ }
+ }
+ throw lastProviderError;
+};
+
+// node_modules/.pnpm/@aws-sdk+credential-provider-node@3.972.32/node_modules/@aws-sdk/credential-provider-node/dist-es/defaultProvider.js
+var multipleCredentialSourceWarningEmitted = false;
+var defaultProvider = (init3 = {}) => memoizeChain([
+ async () => {
+ const profile = init3.profile ?? process.env[import_shared_ini_file_loader12.ENV_PROFILE];
+ if (profile) {
+ const envStaticCredentialsAreSet = process.env[ENV_KEY] && process.env[ENV_SECRET];
+ if (envStaticCredentialsAreSet) {
+ if (!multipleCredentialSourceWarningEmitted) {
+ const warnFn = init3.logger?.warn && init3.logger?.constructor?.name !== "NoOpLogger" ? init3.logger.warn.bind(init3.logger) : console.warn;
+ warnFn(`@aws-sdk/credential-provider-node - defaultProvider::fromEnv WARNING:
+ Multiple credential sources detected:
+ Both AWS_PROFILE and the pair AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY static credentials are set.
+ This SDK will proceed with the AWS_PROFILE value.
+
+ However, a future version may change this behavior to prefer the ENV static credentials.
+ Please ensure that your environment only sets either the AWS_PROFILE or the
+ AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY pair.
+`);
+ multipleCredentialSourceWarningEmitted = true;
+ }
+ }
+ throw new import_property_provider23.CredentialsProviderError("AWS_PROFILE is set, skipping fromEnv provider.", {
+ logger: init3.logger,
+ tryNextLink: true
+ });
+ }
+ init3.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromEnv");
+ return fromEnv(init3)();
+ },
+ async (awsIdentityProperties) => {
+ init3.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromSSO");
+ const { ssoStartUrl, ssoAccountId, ssoRegion, ssoRoleName, ssoSession } = init3;
+ if (!ssoStartUrl && !ssoAccountId && !ssoRegion && !ssoRoleName && !ssoSession) {
+ throw new import_property_provider23.CredentialsProviderError("Skipping SSO provider in default chain (inputs do not include SSO fields).", { logger: init3.logger });
+ }
+ const { fromSSO: fromSSO3 } = await Promise.resolve().then(() => (init_dist_es5(), exports_dist_es4));
+ return fromSSO3(init3)(awsIdentityProperties);
+ },
+ async (awsIdentityProperties) => {
+ init3.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromIni");
+ const { fromIni: fromIni3 } = await Promise.resolve().then(() => (init_dist_es9(), exports_dist_es7));
+ return fromIni3(init3)(awsIdentityProperties);
+ },
+ async (awsIdentityProperties) => {
+ init3.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromProcess");
+ const { fromProcess: fromProcess3 } = await Promise.resolve().then(() => (init_dist_es7(), exports_dist_es5));
+ return fromProcess3(init3)(awsIdentityProperties);
+ },
+ async (awsIdentityProperties) => {
+ init3.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromTokenFile");
+ const { fromTokenFile: fromTokenFile3 } = await Promise.resolve().then(() => (init_dist_es8(), exports_dist_es6));
+ return fromTokenFile3(init3)(awsIdentityProperties);
+ },
+ async () => {
+ init3.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::remoteProvider");
+ return (await remoteProvider(init3))();
+ },
+ async () => {
+ throw new import_property_provider23.CredentialsProviderError("Could not load credentials from any providers", {
+ tryNextLink: false,
+ logger: init3.logger
+ });
+ }
+], credentialsTreatedAsExpired);
+var credentialsTreatedAsExpired = (credentials) => credentials?.expiration !== undefined && credentials.expiration.getTime() - Date.now() < 300000;
+
+// node_modules/.pnpm/@aws-sdk+middleware-bucket-endpoint@3.972.10/node_modules/@aws-sdk/middleware-bucket-endpoint/dist-es/NodeUseArnRegionConfigOptions.js
+var import_util_config_provider2 = __toESM(require_dist_cjs23(), 1);
+var NODE_USE_ARN_REGION_ENV_NAME = "AWS_S3_USE_ARN_REGION";
+var NODE_USE_ARN_REGION_INI_NAME = "s3_use_arn_region";
+var NODE_USE_ARN_REGION_CONFIG_OPTIONS = {
+ environmentVariableSelector: (env2) => import_util_config_provider2.booleanSelector(env2, NODE_USE_ARN_REGION_ENV_NAME, import_util_config_provider2.SelectorType.ENV),
+ configFileSelector: (profile) => import_util_config_provider2.booleanSelector(profile, NODE_USE_ARN_REGION_INI_NAME, import_util_config_provider2.SelectorType.CONFIG),
+ default: undefined
+};
+
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.js
+var import_util_user_agent_node = __toESM(require_dist_cjs40(), 1);
+var import_config_resolver = __toESM(require_dist_cjs32(), 1);
+
+// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/HeaderMarshaller.js
+var import_util_hex_encoding2 = __toESM(require_dist_cjs11(), 1);
+
+// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/Int64.js
+var import_util_hex_encoding = __toESM(require_dist_cjs11(), 1);
+
+class Int64 {
+ bytes;
+ constructor(bytes) {
+ this.bytes = bytes;
+ if (bytes.byteLength !== 8) {
+ throw new Error("Int64 buffers must be exactly 8 bytes");
+ }
+ }
+ static fromNumber(number2) {
+ if (number2 > 9223372036854776000 || number2 < -9223372036854776000) {
+ throw new Error(`${number2} is too large (or, if negative, too small) to represent as an Int64`);
+ }
+ const bytes = new Uint8Array(8);
+ for (let i2 = 7, remaining = Math.abs(Math.round(number2));i2 > -1 && remaining > 0; i2--, remaining /= 256) {
+ bytes[i2] = remaining;
+ }
+ if (number2 < 0) {
+ negate(bytes);
+ }
+ return new Int64(bytes);
+ }
+ valueOf() {
+ const bytes = this.bytes.slice(0);
+ const negative = bytes[0] & 128;
+ if (negative) {
+ negate(bytes);
+ }
+ return parseInt(import_util_hex_encoding.toHex(bytes), 16) * (negative ? -1 : 1);
+ }
+ toString() {
+ return String(this.valueOf());
+ }
+}
+function negate(bytes) {
+ for (let i2 = 0;i2 < 8; i2++) {
+ bytes[i2] ^= 255;
+ }
+ for (let i2 = 7;i2 > -1; i2--) {
+ bytes[i2]++;
+ if (bytes[i2] !== 0)
+ break;
+ }
+}
+
+// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/HeaderMarshaller.js
+class HeaderMarshaller {
+ toUtf8;
+ fromUtf8;
+ constructor(toUtf82, fromUtf84) {
+ this.toUtf8 = toUtf82;
+ this.fromUtf8 = fromUtf84;
+ }
+ format(headers) {
+ const chunks = [];
+ for (const headerName of Object.keys(headers)) {
+ const bytes = this.fromUtf8(headerName);
+ chunks.push(Uint8Array.from([bytes.byteLength]), bytes, this.formatHeaderValue(headers[headerName]));
+ }
+ const out = new Uint8Array(chunks.reduce((carry, bytes) => carry + bytes.byteLength, 0));
+ let position = 0;
+ for (const chunk of chunks) {
+ out.set(chunk, position);
+ position += chunk.byteLength;
+ }
+ return out;
+ }
+ formatHeaderValue(header) {
+ switch (header.type) {
+ case "boolean":
+ return Uint8Array.from([header.value ? 0 : 1]);
+ case "byte":
+ return Uint8Array.from([2, header.value]);
+ case "short":
+ const shortView = new DataView(new ArrayBuffer(3));
+ shortView.setUint8(0, 3);
+ shortView.setInt16(1, header.value, false);
+ return new Uint8Array(shortView.buffer);
+ case "integer":
+ const intView = new DataView(new ArrayBuffer(5));
+ intView.setUint8(0, 4);
+ intView.setInt32(1, header.value, false);
+ return new Uint8Array(intView.buffer);
+ case "long":
+ const longBytes = new Uint8Array(9);
+ longBytes[0] = 5;
+ longBytes.set(header.value.bytes, 1);
+ return longBytes;
+ case "binary":
+ const binView = new DataView(new ArrayBuffer(3 + header.value.byteLength));
+ binView.setUint8(0, 6);
+ binView.setUint16(1, header.value.byteLength, false);
+ const binBytes = new Uint8Array(binView.buffer);
+ binBytes.set(header.value, 3);
+ return binBytes;
+ case "string":
+ const utf8Bytes = this.fromUtf8(header.value);
+ const strView = new DataView(new ArrayBuffer(3 + utf8Bytes.byteLength));
+ strView.setUint8(0, 7);
+ strView.setUint16(1, utf8Bytes.byteLength, false);
+ const strBytes = new Uint8Array(strView.buffer);
+ strBytes.set(utf8Bytes, 3);
+ return strBytes;
+ case "timestamp":
+ const tsBytes = new Uint8Array(9);
+ tsBytes[0] = 8;
+ tsBytes.set(Int64.fromNumber(header.value.valueOf()).bytes, 1);
+ return tsBytes;
+ case "uuid":
+ if (!UUID_PATTERN.test(header.value)) {
+ throw new Error(`Invalid UUID received: ${header.value}`);
+ }
+ const uuidBytes = new Uint8Array(17);
+ uuidBytes[0] = 9;
+ uuidBytes.set(import_util_hex_encoding2.fromHex(header.value.replace(/\-/g, "")), 1);
+ return uuidBytes;
+ }
+ }
+ parse(headers) {
+ const out = {};
+ let position = 0;
+ while (position < headers.byteLength) {
+ const nameLength = headers.getUint8(position++);
+ const name = this.toUtf8(new Uint8Array(headers.buffer, headers.byteOffset + position, nameLength));
+ position += nameLength;
+ switch (headers.getUint8(position++)) {
+ case 0:
+ out[name] = {
+ type: BOOLEAN_TAG,
+ value: true
+ };
+ break;
+ case 1:
+ out[name] = {
+ type: BOOLEAN_TAG,
+ value: false
+ };
+ break;
+ case 2:
+ out[name] = {
+ type: BYTE_TAG,
+ value: headers.getInt8(position++)
+ };
+ break;
+ case 3:
+ out[name] = {
+ type: SHORT_TAG,
+ value: headers.getInt16(position, false)
+ };
+ position += 2;
+ break;
+ case 4:
+ out[name] = {
+ type: INT_TAG,
+ value: headers.getInt32(position, false)
+ };
+ position += 4;
+ break;
+ case 5:
+ out[name] = {
+ type: LONG_TAG,
+ value: new Int64(new Uint8Array(headers.buffer, headers.byteOffset + position, 8))
+ };
+ position += 8;
+ break;
+ case 6:
+ const binaryLength = headers.getUint16(position, false);
+ position += 2;
+ out[name] = {
+ type: BINARY_TAG,
+ value: new Uint8Array(headers.buffer, headers.byteOffset + position, binaryLength)
+ };
+ position += binaryLength;
+ break;
+ case 7:
+ const stringLength = headers.getUint16(position, false);
+ position += 2;
+ out[name] = {
+ type: STRING_TAG,
+ value: this.toUtf8(new Uint8Array(headers.buffer, headers.byteOffset + position, stringLength))
+ };
+ position += stringLength;
+ break;
+ case 8:
+ out[name] = {
+ type: TIMESTAMP_TAG,
+ value: new Date(new Int64(new Uint8Array(headers.buffer, headers.byteOffset + position, 8)).valueOf())
+ };
+ position += 8;
+ break;
+ case 9:
+ const uuidBytes = new Uint8Array(headers.buffer, headers.byteOffset + position, 16);
+ position += 16;
+ out[name] = {
+ type: UUID_TAG,
+ value: `${import_util_hex_encoding2.toHex(uuidBytes.subarray(0, 4))}-${import_util_hex_encoding2.toHex(uuidBytes.subarray(4, 6))}-${import_util_hex_encoding2.toHex(uuidBytes.subarray(6, 8))}-${import_util_hex_encoding2.toHex(uuidBytes.subarray(8, 10))}-${import_util_hex_encoding2.toHex(uuidBytes.subarray(10))}`
+ };
+ break;
+ default:
+ throw new Error(`Unrecognized header type tag`);
+ }
+ }
+ return out;
+ }
+}
+var HEADER_VALUE_TYPE;
+(function(HEADER_VALUE_TYPE2) {
+ HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["boolTrue"] = 0] = "boolTrue";
+ HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["boolFalse"] = 1] = "boolFalse";
+ HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["byte"] = 2] = "byte";
+ HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["short"] = 3] = "short";
+ HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["integer"] = 4] = "integer";
+ HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["long"] = 5] = "long";
+ HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["byteArray"] = 6] = "byteArray";
+ HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["string"] = 7] = "string";
+ HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["timestamp"] = 8] = "timestamp";
+ HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["uuid"] = 9] = "uuid";
+})(HEADER_VALUE_TYPE || (HEADER_VALUE_TYPE = {}));
+var BOOLEAN_TAG = "boolean";
+var BYTE_TAG = "byte";
+var SHORT_TAG = "short";
+var INT_TAG = "integer";
+var LONG_TAG = "long";
+var BINARY_TAG = "binary";
+var STRING_TAG = "string";
+var TIMESTAMP_TAG = "timestamp";
+var UUID_TAG = "uuid";
+var UUID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
+
+// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/splitMessage.js
+var PRELUDE_MEMBER_LENGTH = 4;
+var PRELUDE_LENGTH = PRELUDE_MEMBER_LENGTH * 2;
+var CHECKSUM_LENGTH = 4;
+var MINIMUM_MESSAGE_LENGTH = PRELUDE_LENGTH + CHECKSUM_LENGTH * 2;
+function splitMessage({ byteLength, byteOffset, buffer }) {
+ if (byteLength < MINIMUM_MESSAGE_LENGTH) {
+ throw new Error("Provided message too short to accommodate event stream message overhead");
+ }
+ const view = new DataView(buffer, byteOffset, byteLength);
+ const messageLength = view.getUint32(0, false);
+ if (byteLength !== messageLength) {
+ throw new Error("Reported message length does not match received message length");
+ }
+ const headerLength = view.getUint32(PRELUDE_MEMBER_LENGTH, false);
+ const expectedPreludeChecksum = view.getUint32(PRELUDE_LENGTH, false);
+ const expectedMessageChecksum = view.getUint32(byteLength - CHECKSUM_LENGTH, false);
+ const checksummer = new Crc32().update(new Uint8Array(buffer, byteOffset, PRELUDE_LENGTH));
+ if (expectedPreludeChecksum !== checksummer.digest()) {
+ throw new Error(`The prelude checksum specified in the message (${expectedPreludeChecksum}) does not match the calculated CRC32 checksum (${checksummer.digest()})`);
+ }
+ checksummer.update(new Uint8Array(buffer, byteOffset + PRELUDE_LENGTH, byteLength - (PRELUDE_LENGTH + CHECKSUM_LENGTH)));
+ if (expectedMessageChecksum !== checksummer.digest()) {
+ throw new Error(`The message checksum (${checksummer.digest()}) did not match the expected value of ${expectedMessageChecksum}`);
+ }
+ return {
+ headers: new DataView(buffer, byteOffset + PRELUDE_LENGTH + CHECKSUM_LENGTH, headerLength),
+ body: new Uint8Array(buffer, byteOffset + PRELUDE_LENGTH + CHECKSUM_LENGTH + headerLength, messageLength - headerLength - (PRELUDE_LENGTH + CHECKSUM_LENGTH + CHECKSUM_LENGTH))
+ };
+}
+
+// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/EventStreamCodec.js
+class EventStreamCodec {
+ headerMarshaller;
+ messageBuffer;
+ isEndOfStream;
+ constructor(toUtf82, fromUtf84) {
+ this.headerMarshaller = new HeaderMarshaller(toUtf82, fromUtf84);
+ this.messageBuffer = [];
+ this.isEndOfStream = false;
+ }
+ feed(message) {
+ this.messageBuffer.push(this.decode(message));
+ }
+ endOfStream() {
+ this.isEndOfStream = true;
+ }
+ getMessage() {
+ const message = this.messageBuffer.pop();
+ const isEndOfStream = this.isEndOfStream;
+ return {
+ getMessage() {
+ return message;
+ },
+ isEndOfStream() {
+ return isEndOfStream;
+ }
+ };
+ }
+ getAvailableMessages() {
+ const messages = this.messageBuffer;
+ this.messageBuffer = [];
+ const isEndOfStream = this.isEndOfStream;
+ return {
+ getMessages() {
+ return messages;
+ },
+ isEndOfStream() {
+ return isEndOfStream;
+ }
+ };
+ }
+ encode({ headers: rawHeaders, body }) {
+ const headers = this.headerMarshaller.format(rawHeaders);
+ const length = headers.byteLength + body.byteLength + 16;
+ const out = new Uint8Array(length);
+ const view = new DataView(out.buffer, out.byteOffset, out.byteLength);
+ const checksum = new Crc32;
+ view.setUint32(0, length, false);
+ view.setUint32(4, headers.byteLength, false);
+ view.setUint32(8, checksum.update(out.subarray(0, 8)).digest(), false);
+ out.set(headers, 12);
+ out.set(body, headers.byteLength + 12);
+ view.setUint32(length - 4, checksum.update(out.subarray(8, length - 4)).digest(), false);
+ return out;
+ }
+ decode(message) {
+ const { headers, body } = splitMessage(message);
+ return { headers: this.headerMarshaller.parse(headers), body };
+ }
+ formatHeaders(rawHeaders) {
+ return this.headerMarshaller.format(rawHeaders);
+ }
+}
+
+// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/MessageDecoderStream.js
+class MessageDecoderStream {
+ options;
+ constructor(options) {
+ this.options = options;
+ }
+ [Symbol.asyncIterator]() {
+ return this.asyncIterator();
+ }
+ async* asyncIterator() {
+ for await (const bytes of this.options.inputStream) {
+ const decoded = this.options.decoder.decode(bytes);
+ yield decoded;
+ }
+ }
+}
+
+// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/MessageEncoderStream.js
+class MessageEncoderStream {
+ options;
+ constructor(options) {
+ this.options = options;
+ }
+ [Symbol.asyncIterator]() {
+ return this.asyncIterator();
+ }
+ async* asyncIterator() {
+ for await (const msg of this.options.messageStream) {
+ const encoded = this.options.encoder.encode(msg);
+ yield encoded;
+ }
+ if (this.options.includeEndFrame) {
+ yield new Uint8Array(0);
+ }
+ }
+}
+
+// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/SmithyMessageDecoderStream.js
+class SmithyMessageDecoderStream {
+ options;
+ constructor(options) {
+ this.options = options;
+ }
+ [Symbol.asyncIterator]() {
+ return this.asyncIterator();
+ }
+ async* asyncIterator() {
+ for await (const message of this.options.messageStream) {
+ const deserialized = await this.options.deserializer(message);
+ if (deserialized === undefined)
+ continue;
+ yield deserialized;
+ }
+ }
+}
+
+// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/SmithyMessageEncoderStream.js
+class SmithyMessageEncoderStream {
+ options;
+ constructor(options) {
+ this.options = options;
+ }
+ [Symbol.asyncIterator]() {
+ return this.asyncIterator();
+ }
+ async* asyncIterator() {
+ for await (const chunk of this.options.inputStream) {
+ const payloadBuf = this.options.serializer(chunk);
+ yield payloadBuf;
+ }
+ }
+}
+
+// node_modules/.pnpm/@smithy+eventstream-serde-universal@4.2.14/node_modules/@smithy/eventstream-serde-universal/dist-es/getChunkedStream.js
+function getChunkedStream(source) {
+ let currentMessageTotalLength = 0;
+ let currentMessagePendingLength = 0;
+ let currentMessage = null;
+ let messageLengthBuffer = null;
+ const allocateMessage = (size) => {
+ if (typeof size !== "number") {
+ throw new Error("Attempted to allocate an event message where size was not a number: " + size);
+ }
+ currentMessageTotalLength = size;
+ currentMessagePendingLength = 4;
+ currentMessage = new Uint8Array(size);
+ const currentMessageView = new DataView(currentMessage.buffer);
+ currentMessageView.setUint32(0, size, false);
+ };
+ const iterator = async function* () {
+ const sourceIterator = source[Symbol.asyncIterator]();
+ while (true) {
+ const { value, done } = await sourceIterator.next();
+ if (done) {
+ if (!currentMessageTotalLength) {
+ return;
+ } else if (currentMessageTotalLength === currentMessagePendingLength) {
+ yield currentMessage;
+ } else {
+ throw new Error("Truncated event message received.");
+ }
+ return;
+ }
+ const chunkLength = value.length;
+ let currentOffset = 0;
+ while (currentOffset < chunkLength) {
+ if (!currentMessage) {
+ const bytesRemaining = chunkLength - currentOffset;
+ if (!messageLengthBuffer) {
+ messageLengthBuffer = new Uint8Array(4);
+ }
+ const numBytesForTotal = Math.min(4 - currentMessagePendingLength, bytesRemaining);
+ messageLengthBuffer.set(value.slice(currentOffset, currentOffset + numBytesForTotal), currentMessagePendingLength);
+ currentMessagePendingLength += numBytesForTotal;
+ currentOffset += numBytesForTotal;
+ if (currentMessagePendingLength < 4) {
+ break;
+ }
+ allocateMessage(new DataView(messageLengthBuffer.buffer).getUint32(0, false));
+ messageLengthBuffer = null;
+ }
+ const numBytesToWrite = Math.min(currentMessageTotalLength - currentMessagePendingLength, chunkLength - currentOffset);
+ currentMessage.set(value.slice(currentOffset, currentOffset + numBytesToWrite), currentMessagePendingLength);
+ currentMessagePendingLength += numBytesToWrite;
+ currentOffset += numBytesToWrite;
+ if (currentMessageTotalLength && currentMessageTotalLength === currentMessagePendingLength) {
+ yield currentMessage;
+ currentMessage = null;
+ currentMessageTotalLength = 0;
+ currentMessagePendingLength = 0;
+ }
+ }
+ }
+ };
+ return {
+ [Symbol.asyncIterator]: iterator
+ };
+}
+
+// node_modules/.pnpm/@smithy+eventstream-serde-universal@4.2.14/node_modules/@smithy/eventstream-serde-universal/dist-es/getUnmarshalledStream.js
+function getMessageUnmarshaller(deserializer, toUtf82) {
+ return async function(message) {
+ const { value: messageType } = message.headers[":message-type"];
+ if (messageType === "error") {
+ const unmodeledError = new Error(message.headers[":error-message"].value || "UnknownError");
+ unmodeledError.name = message.headers[":error-code"].value;
+ throw unmodeledError;
+ } else if (messageType === "exception") {
+ const code = message.headers[":exception-type"].value;
+ const exception = { [code]: message };
+ const deserializedException = await deserializer(exception);
+ if (deserializedException.$unknown) {
+ const error = new Error(toUtf82(message.body));
+ error.name = code;
+ throw error;
+ }
+ throw deserializedException[code];
+ } else if (messageType === "event") {
+ const event = {
+ [message.headers[":event-type"].value]: message
+ };
+ const deserialized = await deserializer(event);
+ if (deserialized.$unknown)
+ return;
+ return deserialized;
+ } else {
+ throw Error(`Unrecognizable event type: ${message.headers[":event-type"].value}`);
+ }
+ };
+}
+
+// node_modules/.pnpm/@smithy+eventstream-serde-universal@4.2.14/node_modules/@smithy/eventstream-serde-universal/dist-es/EventStreamMarshaller.js
+class EventStreamMarshaller {
+ eventStreamCodec;
+ utfEncoder;
+ constructor({ utf8Encoder, utf8Decoder }) {
+ this.eventStreamCodec = new EventStreamCodec(utf8Encoder, utf8Decoder);
+ this.utfEncoder = utf8Encoder;
+ }
+ deserialize(body, deserializer) {
+ const inputStream = getChunkedStream(body);
+ return new SmithyMessageDecoderStream({
+ messageStream: new MessageDecoderStream({ inputStream, decoder: this.eventStreamCodec }),
+ deserializer: getMessageUnmarshaller(deserializer, this.utfEncoder)
+ });
+ }
+ serialize(inputStream, serializer) {
+ return new MessageEncoderStream({
+ messageStream: new SmithyMessageEncoderStream({ inputStream, serializer }),
+ encoder: this.eventStreamCodec,
+ includeEndFrame: true
+ });
+ }
+}
+
+// node_modules/.pnpm/@smithy+eventstream-serde-node@4.2.14/node_modules/@smithy/eventstream-serde-node/dist-es/EventStreamMarshaller.js
+import { Readable } from "stream";
+
+// node_modules/.pnpm/@smithy+eventstream-serde-node@4.2.14/node_modules/@smithy/eventstream-serde-node/dist-es/utils.js
+async function* readabletoIterable(readStream) {
+ let streamEnded = false;
+ let generationEnded = false;
+ const records = new Array;
+ readStream.on("error", (err) => {
+ if (!streamEnded) {
+ streamEnded = true;
+ }
+ if (err) {
+ throw err;
+ }
+ });
+ readStream.on("data", (data) => {
+ records.push(data);
+ });
+ readStream.on("end", () => {
+ streamEnded = true;
+ });
+ while (!generationEnded) {
+ const value = await new Promise((resolve) => setTimeout(() => resolve(records.shift()), 0));
+ if (value) {
+ yield value;
+ }
+ generationEnded = streamEnded && records.length === 0;
+ }
+}
+
+// node_modules/.pnpm/@smithy+eventstream-serde-node@4.2.14/node_modules/@smithy/eventstream-serde-node/dist-es/EventStreamMarshaller.js
+class EventStreamMarshaller2 {
+ universalMarshaller;
+ constructor({ utf8Encoder, utf8Decoder }) {
+ this.universalMarshaller = new EventStreamMarshaller({
+ utf8Decoder,
+ utf8Encoder
+ });
+ }
+ deserialize(body, deserializer) {
+ const bodyIterable = typeof body[Symbol.asyncIterator] === "function" ? body : readabletoIterable(body);
+ return this.universalMarshaller.deserialize(bodyIterable, deserializer);
+ }
+ serialize(input, serializer) {
+ return Readable.from(this.universalMarshaller.serialize(input, serializer));
+ }
+}
+
+// node_modules/.pnpm/@smithy+eventstream-serde-node@4.2.14/node_modules/@smithy/eventstream-serde-node/dist-es/provider.js
+var eventStreamSerdeProvider = (options) => new EventStreamMarshaller2(options);
+
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.js
+var import_hash_node = __toESM(require_dist_cjs41(), 1);
+
+// node_modules/.pnpm/@smithy+hash-stream-node@4.2.14/node_modules/@smithy/hash-stream-node/dist-es/HashCalculator.js
+var import_util_utf83 = __toESM(require_dist_cjs5(), 1);
+import { Writable } from "stream";
+
+class HashCalculator extends Writable {
+ hash;
+ constructor(hash4, options) {
+ super(options);
+ this.hash = hash4;
+ }
+ _write(chunk, encoding, callback) {
+ try {
+ this.hash.update(import_util_utf83.toUint8Array(chunk));
+ } catch (err) {
+ return callback(err);
+ }
+ callback();
+ }
+}
+
+// node_modules/.pnpm/@smithy+hash-stream-node@4.2.14/node_modules/@smithy/hash-stream-node/dist-es/readableStreamHasher.js
+var readableStreamHasher = (hashCtor, readableStream) => {
+ if (readableStream.readableFlowing !== null) {
+ throw new Error("Unable to calculate hash for flowing readable stream");
+ }
+ const hash4 = new hashCtor;
+ const hashCalculator = new HashCalculator(hash4);
+ readableStream.pipe(hashCalculator);
+ return new Promise((resolve, reject) => {
+ readableStream.on("error", (err) => {
+ hashCalculator.end();
+ reject(err);
+ });
+ hashCalculator.on("error", reject);
+ hashCalculator.on("finish", () => {
+ hash4.digest().then(resolve).catch(reject);
+ });
+ });
+};
+
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.js
+var import_middleware_retry = __toESM(require_dist_cjs39(), 1);
+var import_node_config_provider3 = __toESM(require_dist_cjs36(), 1);
+var import_node_http_handler2 = __toESM(require_dist_cjs9(), 1);
+var import_smithy_client7 = __toESM(require_dist_cjs21(), 1);
+var import_util_body_length_node = __toESM(require_dist_cjs42(), 1);
+var import_util_defaults_mode_node = __toESM(require_dist_cjs43(), 1);
+var import_util_retry = __toESM(require_dist_cjs30(), 1);
+
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.shared.js
+var import_httpAuthSchemes2 = __toESM(require_httpAuthSchemes(), 1);
+var import_smithy_client6 = __toESM(require_dist_cjs21(), 1);
+var import_url_parser2 = __toESM(require_dist_cjs19(), 1);
+var import_util_base64 = __toESM(require_dist_cjs6(), 1);
+var import_util_stream5 = __toESM(require_dist_cjs12(), 1);
+var import_util_utf84 = __toESM(require_dist_cjs5(), 1);
+var getRuntimeConfig = (config) => {
+ return {
+ apiVersion: "2006-03-01",
+ base64Decoder: config?.base64Decoder ?? import_util_base64.fromBase64,
+ base64Encoder: config?.base64Encoder ?? import_util_base64.toBase64,
+ disableHostPrefix: config?.disableHostPrefix ?? false,
+ endpointProvider: config?.endpointProvider ?? defaultEndpointResolver,
+ extensions: config?.extensions ?? [],
+ getAwsChunkedEncodingStream: config?.getAwsChunkedEncodingStream ?? import_util_stream5.getAwsChunkedEncodingStream,
+ httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? defaultS3HttpAuthSchemeProvider,
+ httpAuthSchemes: config?.httpAuthSchemes ?? [
+ {
+ schemeId: "aws.auth#sigv4",
+ identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4"),
+ signer: new import_httpAuthSchemes2.AwsSdkSigV4Signer
+ },
+ {
+ schemeId: "aws.auth#sigv4a",
+ identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4a"),
+ signer: new import_httpAuthSchemes2.AwsSdkSigV4ASigner
+ }
+ ],
+ logger: config?.logger ?? new import_smithy_client6.NoOpLogger,
+ protocol: config?.protocol ?? S3RestXmlProtocol,
+ protocolSettings: config?.protocolSettings ?? {
+ defaultNamespace: "com.amazonaws.s3",
+ errorTypeRegistries,
+ xmlNamespace: "http://s3.amazonaws.com/doc/2006-03-01/",
+ version: "2006-03-01",
+ serviceTarget: "AmazonS3"
+ },
+ sdkStreamMixin: config?.sdkStreamMixin ?? import_util_stream5.sdkStreamMixin,
+ serviceId: config?.serviceId ?? "S3",
+ signerConstructor: config?.signerConstructor ?? SignatureV4MultiRegion,
+ signingEscapePath: config?.signingEscapePath ?? false,
+ urlParser: config?.urlParser ?? import_url_parser2.parseUrl,
+ useArnRegion: config?.useArnRegion ?? undefined,
+ utf8Decoder: config?.utf8Decoder ?? import_util_utf84.fromUtf8,
+ utf8Encoder: config?.utf8Encoder ?? import_util_utf84.toUtf8
+ };
+};
+
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.js
+var getRuntimeConfig2 = (config) => {
+ import_smithy_client7.emitWarningIfUnsupportedVersion(process.version);
+ const defaultsMode = import_util_defaults_mode_node.resolveDefaultsModeConfig(config);
+ const defaultConfigProvider = () => defaultsMode().then(import_smithy_client7.loadConfigsForDefaultMode);
+ const clientSharedValues = getRuntimeConfig(config);
+ import_client17.emitWarningIfUnsupportedVersion(process.version);
+ const loaderConfig = {
+ profile: config?.profile,
+ logger: clientSharedValues.logger
+ };
+ return {
+ ...clientSharedValues,
+ ...config,
+ runtime: "node",
+ defaultsMode,
+ authSchemePreference: config?.authSchemePreference ?? import_node_config_provider3.loadConfig(import_httpAuthSchemes3.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig),
+ bodyLengthChecker: config?.bodyLengthChecker ?? import_util_body_length_node.calculateBodyLength,
+ credentialDefaultProvider: config?.credentialDefaultProvider ?? defaultProvider,
+ defaultUserAgentProvider: config?.defaultUserAgentProvider ?? import_util_user_agent_node.createDefaultUserAgentProvider({ serviceId: clientSharedValues.serviceId, clientVersion: package_default.version }),
+ disableS3ExpressSessionAuth: config?.disableS3ExpressSessionAuth ?? import_node_config_provider3.loadConfig(NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_OPTIONS, loaderConfig),
+ eventStreamSerdeProvider: config?.eventStreamSerdeProvider ?? eventStreamSerdeProvider,
+ maxAttempts: config?.maxAttempts ?? import_node_config_provider3.loadConfig(import_middleware_retry.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config),
+ md5: config?.md5 ?? import_hash_node.Hash.bind(null, "md5"),
+ region: config?.region ?? import_node_config_provider3.loadConfig(import_config_resolver.NODE_REGION_CONFIG_OPTIONS, { ...import_config_resolver.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }),
+ requestChecksumCalculation: config?.requestChecksumCalculation ?? import_node_config_provider3.loadConfig(NODE_REQUEST_CHECKSUM_CALCULATION_CONFIG_OPTIONS, loaderConfig),
+ requestHandler: import_node_http_handler2.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider),
+ responseChecksumValidation: config?.responseChecksumValidation ?? import_node_config_provider3.loadConfig(NODE_RESPONSE_CHECKSUM_VALIDATION_CONFIG_OPTIONS, loaderConfig),
+ retryMode: config?.retryMode ?? import_node_config_provider3.loadConfig({
+ ...import_middleware_retry.NODE_RETRY_MODE_CONFIG_OPTIONS,
+ default: async () => (await defaultConfigProvider()).retryMode || import_util_retry.DEFAULT_RETRY_MODE
+ }, config),
+ sha1: config?.sha1 ?? import_hash_node.Hash.bind(null, "sha1"),
+ sha256: config?.sha256 ?? import_hash_node.Hash.bind(null, "sha256"),
+ sigv4aSigningRegionSet: config?.sigv4aSigningRegionSet ?? import_node_config_provider3.loadConfig(import_httpAuthSchemes3.NODE_SIGV4A_CONFIG_OPTIONS, loaderConfig),
+ streamCollector: config?.streamCollector ?? import_node_http_handler2.streamCollector,
+ streamHasher: config?.streamHasher ?? readableStreamHasher,
+ useArnRegion: config?.useArnRegion ?? import_node_config_provider3.loadConfig(NODE_USE_ARN_REGION_CONFIG_OPTIONS, loaderConfig),
+ useDualstackEndpoint: config?.useDualstackEndpoint ?? import_node_config_provider3.loadConfig(import_config_resolver.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
+ useFipsEndpoint: config?.useFipsEndpoint ?? import_node_config_provider3.loadConfig(import_config_resolver.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
+ userAgentAppId: config?.userAgentAppId ?? import_node_config_provider3.loadConfig(import_util_user_agent_node.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig)
+ };
+};
+
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeExtensions.js
+var import_region_config_resolver = __toESM(require_dist_cjs44(), 1);
+var import_protocol_http11 = __toESM(require_dist_cjs2(), 1);
+var import_smithy_client8 = __toESM(require_dist_cjs21(), 1);
+
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/auth/httpAuthExtensionConfiguration.js
+var getHttpAuthExtensionConfiguration = (runtimeConfig) => {
+ const _httpAuthSchemes = runtimeConfig.httpAuthSchemes;
+ let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider;
+ let _credentials = runtimeConfig.credentials;
+ return {
+ setHttpAuthScheme(httpAuthScheme) {
+ const index3 = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId);
+ if (index3 === -1) {
+ _httpAuthSchemes.push(httpAuthScheme);
+ } else {
+ _httpAuthSchemes.splice(index3, 1, httpAuthScheme);
+ }
+ },
+ httpAuthSchemes() {
+ return _httpAuthSchemes;
+ },
+ setHttpAuthSchemeProvider(httpAuthSchemeProvider) {
+ _httpAuthSchemeProvider = httpAuthSchemeProvider;
+ },
+ httpAuthSchemeProvider() {
+ return _httpAuthSchemeProvider;
+ },
+ setCredentials(credentials) {
+ _credentials = credentials;
+ },
+ credentials() {
+ return _credentials;
+ }
+ };
+};
+var resolveHttpAuthRuntimeConfig = (config) => {
+ return {
+ httpAuthSchemes: config.httpAuthSchemes(),
+ httpAuthSchemeProvider: config.httpAuthSchemeProvider(),
+ credentials: config.credentials()
+ };
+};
+
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeExtensions.js
+var resolveRuntimeExtensions = (runtimeConfig, extensions) => {
+ const extensionConfiguration = Object.assign(import_region_config_resolver.getAwsRegionExtensionConfiguration(runtimeConfig), import_smithy_client8.getDefaultExtensionConfiguration(runtimeConfig), import_protocol_http11.getHttpHandlerExtensionConfiguration(runtimeConfig), getHttpAuthExtensionConfiguration(runtimeConfig));
+ extensions.forEach((extension) => extension.configure(extensionConfiguration));
+ return Object.assign(runtimeConfig, import_region_config_resolver.resolveAwsRegionExtensionConfiguration(extensionConfiguration), import_smithy_client8.resolveDefaultRuntimeConfig(extensionConfiguration), import_protocol_http11.resolveHttpHandlerRuntimeConfig(extensionConfiguration), resolveHttpAuthRuntimeConfig(extensionConfiguration));
+};
+
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/S3Client.js
+class S3Client extends import_smithy_client9.Client {
+ config;
+ constructor(...[configuration]) {
+ const _config_0 = getRuntimeConfig2(configuration || {});
+ super(_config_0);
+ this.initConfig = _config_0;
+ const _config_1 = resolveClientEndpointParameters(_config_0);
+ const _config_2 = import_middleware_user_agent.resolveUserAgentConfig(_config_1);
+ const _config_3 = resolveFlexibleChecksumsConfig(_config_2);
+ const _config_4 = import_middleware_retry2.resolveRetryConfig(_config_3);
+ const _config_5 = import_config_resolver2.resolveRegionConfig(_config_4);
+ const _config_6 = import_middleware_host_header.resolveHostHeaderConfig(_config_5);
+ const _config_7 = import_middleware_endpoint3.resolveEndpointConfig(_config_6);
+ const _config_8 = resolveEventStreamSerdeConfig(_config_7);
+ const _config_9 = resolveHttpAuthSchemeConfig(_config_8);
+ const _config_10 = resolveS3Config(_config_9, { session: [() => this, CreateSessionCommand] });
+ const _config_11 = resolveRuntimeExtensions(_config_10, configuration?.extensions || []);
+ this.config = _config_11;
+ this.middlewareStack.use(import_schema8.getSchemaSerdePlugin(this.config));
+ this.middlewareStack.use(import_middleware_user_agent.getUserAgentPlugin(this.config));
+ this.middlewareStack.use(import_middleware_retry2.getRetryPlugin(this.config));
+ this.middlewareStack.use(import_middleware_content_length.getContentLengthPlugin(this.config));
+ this.middlewareStack.use(import_middleware_host_header.getHostHeaderPlugin(this.config));
+ this.middlewareStack.use(import_middleware_logger.getLoggerPlugin(this.config));
+ this.middlewareStack.use(import_middleware_recursion_detection.getRecursionDetectionPlugin(this.config));
+ this.middlewareStack.use(import_core3.getHttpAuthSchemeEndpointRuleSetPlugin(this.config, {
+ httpAuthSchemeParametersProvider: defaultS3HttpAuthSchemeParametersProvider,
+ identityProviderConfigProvider: async (config) => new import_core3.DefaultIdentityProviderConfig({
+ "aws.auth#sigv4": config.credentials,
+ "aws.auth#sigv4a": config.credentials
+ })
+ }));
+ this.middlewareStack.use(import_core3.getHttpSigningPlugin(this.config));
+ this.middlewareStack.use(getValidateBucketNamePlugin(this.config));
+ this.middlewareStack.use(getAddExpectContinuePlugin(this.config));
+ this.middlewareStack.use(getRegionRedirectMiddlewarePlugin(this.config));
+ this.middlewareStack.use(getS3ExpressPlugin(this.config));
+ this.middlewareStack.use(getS3ExpressHttpSigningPlugin(this.config));
+ }
+ destroy() {
+ super.destroy();
+ }
+}
+
+// node_modules/.pnpm/@aws-sdk+middleware-ssec@3.972.10/node_modules/@aws-sdk/middleware-ssec/dist-es/index.js
+function ssecMiddleware(options) {
+ return (next) => async (args) => {
+ const input = { ...args.input };
+ const properties = [
+ {
+ target: "SSECustomerKey",
+ hash: "SSECustomerKeyMD5"
+ },
+ {
+ target: "CopySourceSSECustomerKey",
+ hash: "CopySourceSSECustomerKeyMD5"
+ }
+ ];
+ for (const prop of properties) {
+ const value = input[prop.target];
+ if (value) {
+ let valueForHash;
+ if (typeof value === "string") {
+ if (isValidBase64EncodedSSECustomerKey(value, options)) {
+ valueForHash = options.base64Decoder(value);
+ } else {
+ valueForHash = options.utf8Decoder(value);
+ input[prop.target] = options.base64Encoder(valueForHash);
+ }
+ } else {
+ valueForHash = ArrayBuffer.isView(value) ? new Uint8Array(value.buffer, value.byteOffset, value.byteLength) : new Uint8Array(value);
+ input[prop.target] = options.base64Encoder(valueForHash);
+ }
+ const hash4 = new options.md5;
+ hash4.update(valueForHash);
+ input[prop.hash] = options.base64Encoder(await hash4.digest());
+ }
+ }
+ return next({
+ ...args,
+ input
+ });
+ };
+}
+var ssecMiddlewareOptions = {
+ name: "ssecMiddleware",
+ step: "initialize",
+ tags: ["SSE"],
+ override: true
+};
+var getSsecPlugin = (config) => ({
+ applyToStack: (clientStack) => {
+ clientStack.add(ssecMiddleware(config), ssecMiddlewareOptions);
+ }
+});
+function isValidBase64EncodedSSECustomerKey(str, options) {
+ const base64Regex = /^(?:[A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
+ if (!base64Regex.test(str))
+ return false;
+ try {
+ const decodedBytes = options.base64Decoder(str);
+ return decodedBytes.length === 32;
+ } catch {
+ return false;
+ }
+}
+
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/commands/GetObjectCommand.js
+var import_middleware_endpoint4 = __toESM(require_dist_cjs38(), 1);
+var import_smithy_client10 = __toESM(require_dist_cjs21(), 1);
+class GetObjectCommand extends import_smithy_client10.Command.classBuilder().ep({
+ ...commonParams,
+ Bucket: { type: "contextParams", name: "Bucket" },
+ Key: { type: "contextParams", name: "Key" }
+}).m(function(Command, cs2, config, o2) {
+ return [
+ import_middleware_endpoint4.getEndpointPlugin(config, Command.getEndpointParameterInstructions()),
+ getFlexibleChecksumsPlugin(config, {
+ requestChecksumRequired: false,
+ requestValidationModeMember: "ChecksumMode",
+ responseAlgorithms: ["CRC64NVME", "CRC32", "CRC32C", "SHA256", "SHA1"]
+ }),
+ getSsecPlugin(config),
+ getS3ExpiresMiddlewarePlugin(config)
+ ];
+}).s("AmazonS3", "GetObject", {}).n("S3Client", "GetObjectCommand").sc(GetObject$).build() {
+}
+
+// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/commands/PutObjectCommand.js
+var import_middleware_endpoint5 = __toESM(require_dist_cjs38(), 1);
+var import_smithy_client11 = __toESM(require_dist_cjs21(), 1);
+class PutObjectCommand extends import_smithy_client11.Command.classBuilder().ep({
+ ...commonParams,
+ Bucket: { type: "contextParams", name: "Bucket" },
+ Key: { type: "contextParams", name: "Key" }
+}).m(function(Command, cs2, config, o2) {
+ return [
+ import_middleware_endpoint5.getEndpointPlugin(config, Command.getEndpointParameterInstructions()),
+ getFlexibleChecksumsPlugin(config, {
+ requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" },
+ requestChecksumRequired: false
+ }),
+ getCheckContentLengthHeaderPlugin(config),
+ getThrow200ExceptionsPlugin(config),
+ getSsecPlugin(config)
+ ];
+}).s("AmazonS3", "PutObject", {}).n("S3Client", "PutObjectCommand").sc(PutObject$).build() {
+}
+
+// node_modules/.pnpm/@aws-sdk+util-format-url@3.972.10/node_modules/@aws-sdk/util-format-url/dist-es/index.js
+var import_querystring_builder = __toESM(require_dist_cjs8(), 1);
+function formatUrl(request2) {
+ const { port, query } = request2;
+ let { protocol, path: path2, hostname } = request2;
+ if (protocol && protocol.slice(-1) !== ":") {
+ protocol += ":";
+ }
+ if (port) {
+ hostname += `:${port}`;
+ }
+ if (path2 && path2.charAt(0) !== "/") {
+ path2 = `/${path2}`;
+ }
+ let queryString = query ? import_querystring_builder.buildQueryString(query) : "";
+ if (queryString && queryString[0] !== "?") {
+ queryString = `?${queryString}`;
+ }
+ let auth = "";
+ if (request2.username != null || request2.password != null) {
+ const username = request2.username ?? "";
+ const password = request2.password ?? "";
+ auth = `${username}:${password}@`;
+ }
+ let fragment = "";
+ if (request2.fragment) {
+ fragment = `#${request2.fragment}`;
+ }
+ return `${protocol}//${auth}${hostname}${path2}${queryString}${fragment}`;
+}
+
+// node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1032.0/node_modules/@aws-sdk/s3-request-presigner/dist-es/getSignedUrl.js
+var import_middleware_endpoint6 = __toESM(require_dist_cjs38(), 1);
+var import_protocol_http12 = __toESM(require_dist_cjs2(), 1);
+
+// node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1032.0/node_modules/@aws-sdk/s3-request-presigner/dist-es/constants.js
+var UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD";
+var SHA256_HEADER = "X-Amz-Content-Sha256";
+
+// node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1032.0/node_modules/@aws-sdk/s3-request-presigner/dist-es/presigner.js
+class S3RequestPresigner {
+ signer;
+ constructor(options) {
+ const resolvedOptions = {
+ service: options.signingName || options.service || "s3",
+ uriEscapePath: options.uriEscapePath || false,
+ applyChecksum: options.applyChecksum || false,
+ ...options
+ };
+ this.signer = new SignatureV4MultiRegion(resolvedOptions);
+ }
+ presign(requestToSign, { unsignableHeaders = new Set, hoistableHeaders = new Set, unhoistableHeaders = new Set, ...options } = {}) {
+ this.prepareRequest(requestToSign, {
+ unsignableHeaders,
+ unhoistableHeaders,
+ hoistableHeaders
+ });
+ return this.signer.presign(requestToSign, {
+ expiresIn: 900,
+ unsignableHeaders,
+ unhoistableHeaders,
+ ...options
+ });
+ }
+ presignWithCredentials(requestToSign, credentials, { unsignableHeaders = new Set, hoistableHeaders = new Set, unhoistableHeaders = new Set, ...options } = {}) {
+ this.prepareRequest(requestToSign, {
+ unsignableHeaders,
+ unhoistableHeaders,
+ hoistableHeaders
+ });
+ return this.signer.presignWithCredentials(requestToSign, credentials, {
+ expiresIn: 900,
+ unsignableHeaders,
+ unhoistableHeaders,
+ ...options
+ });
+ }
+ prepareRequest(requestToSign, { unsignableHeaders = new Set, unhoistableHeaders = new Set, hoistableHeaders = new Set } = {}) {
+ unsignableHeaders.add("content-type");
+ Object.keys(requestToSign.headers).map((header) => header.toLowerCase()).filter((header) => header.startsWith("x-amz-server-side-encryption")).forEach((header) => {
+ if (!hoistableHeaders.has(header)) {
+ unhoistableHeaders.add(header);
+ }
+ });
+ requestToSign.headers[SHA256_HEADER] = UNSIGNED_PAYLOAD;
+ const currentHostHeader = requestToSign.headers.host;
+ const port = requestToSign.port;
+ const expectedHostHeader = `${requestToSign.hostname}${requestToSign.port != null ? ":" + port : ""}`;
+ if (!currentHostHeader || currentHostHeader === requestToSign.hostname && requestToSign.port != null) {
+ requestToSign.headers.host = expectedHostHeader;
+ }
+ }
+}
+
+// node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1032.0/node_modules/@aws-sdk/s3-request-presigner/dist-es/getSignedUrl.js
+var getSignedUrl = async (client, command, options = {}) => {
+ let s3Presigner;
+ let region;
+ if (typeof client.config.endpointProvider === "function") {
+ const endpointV2 = await import_middleware_endpoint6.getEndpointFromInstructions(command.input, command.constructor, client.config);
+ const authScheme = endpointV2.properties?.authSchemes?.[0];
+ if (authScheme?.name === "sigv4a") {
+ region = authScheme?.signingRegionSet?.join(",");
+ } else {
+ region = authScheme?.signingRegion;
+ }
+ s3Presigner = new S3RequestPresigner({
+ ...client.config,
+ signingName: authScheme?.signingName,
+ region: async () => region
+ });
+ } else {
+ s3Presigner = new S3RequestPresigner(client.config);
+ }
+ const presignInterceptMiddleware = (next, context) => async (args) => {
+ const { request: request2 } = args;
+ if (!import_protocol_http12.HttpRequest.isInstance(request2)) {
+ throw new Error("Request to be presigned is not an valid HTTP request.");
+ }
+ delete request2.headers["amz-sdk-invocation-id"];
+ delete request2.headers["amz-sdk-request"];
+ delete request2.headers["x-amz-user-agent"];
+ let presigned2;
+ const presignerOptions = {
+ ...options,
+ signingRegion: options.signingRegion ?? context["signing_region"] ?? region,
+ signingService: options.signingService ?? context["signing_service"]
+ };
+ if (context.s3ExpressIdentity) {
+ presigned2 = await s3Presigner.presignWithCredentials(request2, context.s3ExpressIdentity, presignerOptions);
+ } else {
+ presigned2 = await s3Presigner.presign(request2, presignerOptions);
+ }
+ return {
+ response: {},
+ output: {
+ $metadata: { httpStatusCode: 200 },
+ presigned: presigned2
+ }
+ };
+ };
+ const middlewareName = "presignInterceptMiddleware";
+ const clientStack = client.middlewareStack.clone();
+ clientStack.addRelativeTo(presignInterceptMiddleware, {
+ name: middlewareName,
+ relation: "before",
+ toMiddleware: "awsAuthMiddleware",
+ override: true
+ });
+ const handler = command.resolveMiddleware(clientStack, client.config, {});
+ const { output } = await handler({ input: command.input });
+ const { presigned } = output;
+ return formatUrl(presigned);
+};
+
+// src/config/index.js
+var import_dotenv2 = __toESM(require_main(), 1);
+import_dotenv2.default.config({});
+var envSchema2 = create$3({
+ API_VERSION: create$6().required(),
+ ACCESS_TOKEN_EXPIRY: create$6().required(),
+ ACCESS_TOKEN_SECRET: create$6().required(),
+ REFRESH_TOKEN_EXPIRY: create$6().required(),
+ REFRESH_TOKEN_SECRET: create$6().required(),
+ PORT: create$5().default(5000),
+ DATABASE_URL: create$6().required(),
+ MONGO_URI: create$6().required(),
+ CLIENT_URL: create$6().required(),
+ VITE_API_URL: create$6().required(),
+ AWS_ACCESS_KEY_ID: create$6().required(),
+ AWS_SECRET_ACCESS_KEY: create$6().required(),
+ AWS_REGION: create$6().required(),
+ AWS_BUCKET_NAME: create$6().required(),
+ CLOUDINARY_API_KEY: create$6().required(),
+ CLOUDINARY_API_SECRET: create$6().required(),
+ GOOGLE_CLIENT_ID: create$6().required(),
+ GOOGLE_CLIENT_SECRET: create$6().required(),
+ GOOGLE_CALLBACK_URL: create$6().required(),
+ GEMINI_API_KEY: create$6().required(),
+ MURF_API_KEY: create$6().required(),
+ REDIS_HOST: create$6().required(),
+ REDIS_PORT: create$5().required(),
+ REDIS_URL: create$6().required(),
+ REDIS_USER: create$6().required(),
+ ALLOWED_ORIGINS: create$6().required(),
+ SMTP_VERIFY_URL: create$6().required(),
+ EMAIL_FROM: create$6().required(),
+ EMAIL_HOST: create$6().required(),
+ EMAIL_PORT: create$5().required(),
+ EMAIL_USER: create$6().required(),
+ EMAIL_PASS: create$6().required(),
+ IDEMPOTENCY_SUBMIT_TTL_SEC: create$5().required()
+});
+var parsedEnv2 = envSchema2.validateSync(process.env, {
+ abortEarly: false,
+ stripUnknown: true
+});
+var env2 = parsedEnv2;
+var config_default2 = env2;
+
+// src/services/aws.service.js
+var s3Client = new S3Client({
+ region: config_default2.AWS_REGION,
+ credentials: {
+ accessKeyId: config_default2.AWS_ACCESS_KEY_ID,
+ secretAccessKey: config_default2.AWS_SECRET_ACCESS_KEY
+ }
+});
+async function generateUploadURL(key, filename) {
+ const params = new PutObjectCommand({
+ Bucket: config_default2.AWS_BUCKET_NAME,
+ Key: `${key}/${filename}`,
+ ContentType: "application/json"
+ });
+ const url = await getSignedUrl(s3Client, params, { expiresIn: 3600 });
+ return url;
+}
+var streamToString = (stream) => new Promise((resolve, reject) => {
+ const chunks = [];
+ stream.on("data", (chunk) => chunks.push(chunk));
+ stream.on("error", reject);
+ stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
+});
+async function fetchTestcasesFromS3(s3Key) {
+ try {
+ const command = new GetObjectCommand({
+ Bucket: config_default2.AWS_BUCKET_NAME,
+ Key: s3Key
+ });
+ const response = await s3Client.send(command);
+ const jsonString = await streamToString(response.Body);
+ const data = JSON.parse(jsonString);
+ return data;
+ } catch (err) {
+ console.error("Error fetching testcases:", err);
+ return null;
+ }
+}
+async function fetchFileFromS3(s3Key) {
+ try {
+ const command = new GetObjectCommand({
+ Bucket: config_default2.AWS_BUCKET_NAME,
+ Key: s3Key
+ });
+ const response = await s3Client.send(command);
+ const text3 = await streamToString(response.Body);
+ return text3;
+ } catch (err) {
+ console.error("Error fetching file from S3:", err);
+ return null;
+ }
+}
+
+// src/api/problem/problem-service.ts
+var handleCreateProblem = async (userId, input) => {
+ await verifyProblemCreationPermission(userId);
+ try {
+ const existingProblem = await db.select().from(problem).where(eq(problem.slug, input.slug));
+ if (existingProblem.length > 0) {
+ throw new ApiError_default("Problem already exists", E.BAD_REQUEST);
+ }
+ const problemId = createId();
+ const key = `problems/${problemId}`;
+ const testcasePromises = Array.from({ length: input.testcases }).map((_, i2) => {
+ const fileName = `testcase_${i2}.json`;
+ return generateUploadURL(key, fileName).then((url) => ({
+ url,
+ fileName,
+ order: i2,
+ isSample: false,
+ isHidden: i2 >= Math.min(3, input.testcases)
+ }));
+ });
+ const samplePromises = Array.from({ length: input.sampleTestcases }).map((_, i2) => {
+ const fileName = `sampleTestcase_${i2}.json`;
+ return generateUploadURL(key, fileName).then((url) => ({
+ url,
+ fileName,
+ order: i2,
+ isSample: true,
+ isHidden: false
+ }));
+ });
+ const allTestData = await Promise.all([...testcasePromises, ...samplePromises]);
+ const uploadUrls = allTestData.map((d2) => d2.url);
+ await db.transaction(async (tx) => {
+ await tx.insert(problem).values({
+ id: problemId,
+ title: input.title,
+ description: input.description,
+ slug: input.slug,
+ difficulty: input.difficulty,
+ authorId: userId,
+ inputFormat: input.inputFormat,
+ outputFormat: input.outputFormat,
+ constraints: input.constraints,
+ timeLimit: input.timeLimit,
+ memoryLimit: input.memoryLimit
+ });
+ await tx.insert(editorial).values({
+ problemId,
+ contentS3Key: `${key}/content.md`,
+ solutionS3Key: `${key}/solution.md`,
+ editorialLink: input.editorialLink
+ });
+ if (input.tags && input.tags.length > 0) {
+ const uniqueTagNames = [...new Set(input.tags)];
+ const tagIds = [];
+ for (const tagName of uniqueTagNames) {
+ const insertedTag = await tx.insert(tag).values({ name: tagName }).onConflictDoUpdate({
+ target: tag.name,
+ set: { name: tagName }
+ }).returning({ id: tag.id });
+ tagIds.push(insertedTag[0].id);
+ }
+ if (tagIds.length > 0) {
+ await tx.insert(problemTag).values(tagIds.map((tagId) => ({
+ problemId,
+ tagId
+ }))).onConflictDoNothing();
+ }
+ }
+ if (allTestData.length > 0) {
+ await tx.insert(testcase).values(allTestData.map((td) => ({
+ problemId,
+ order: td.order,
+ isHidden: td.isHidden,
+ s3Key: `${key}/${td.fileName}`,
+ isSample: td.isSample
+ })));
+ }
+ });
+ return {
+ message: "Problem created successfully",
+ problemId,
+ uploadUrls,
+ uploadContentUrl: await generateUploadURL(key, "content.md"),
+ uploadSolutionUrl: await generateUploadURL(key, "solution.md")
+ };
+ } catch (error) {
+ if (error instanceof ApiError_default) {
+ throw error;
+ }
+ console.error("Error creating problem:", error);
+ throw new ApiError_default("Failed to create problem", E.INTERNAL_SERVER_ERROR);
+ }
+};
+var handleFinalizeProblem = async (userId, problemId) => {
+ try {
+ const problemResult = await db.select().from(problem).where(eq(problem.id, problemId));
+ if (problemResult.length === 0) {
+ throw new ApiError_default("Problem not found", E.NOT_FOUND);
+ }
+ if (problemResult[0].authorId !== userId) {
+ throw new ApiError_default("You do not have permission to finalize this problem", E.FORBIDDEN);
+ }
+ const testcasesResult = await db.select().from(testcase).where(eq(testcase.problemId, problemId));
+ if (testcasesResult.length === 0) {
+ throw new ApiError_default("No testcases found. Please upload testcases before finalizing.", E.BAD_REQUEST);
+ }
+ const sampleTestcases = testcasesResult.filter((tc) => tc.isSample);
+ const hiddenTestcases = testcasesResult.filter((tc) => !tc.isSample);
+ if (sampleTestcases.length === 0) {
+ throw new ApiError_default("At least one sample testcase is required.", E.BAD_REQUEST);
+ }
+ if (hiddenTestcases.length === 0) {
+ throw new ApiError_default("At least one hidden testcase is required.", E.BAD_REQUEST);
+ }
+ await Promise.all(testcasesResult.map(async (tc) => {
+ const response = await fetchTestcasesFromS3(tc.s3Key);
+ if (!response) {
+ throw new ApiError_default(`Testcase file not found in storage: ${tc.s3Key}`, E.BAD_REQUEST);
+ }
+ }));
+ const editorialResult = await db.select({
+ solutionS3Key: editorial.solutionS3Key,
+ contentS3Key: editorial.contentS3Key
+ }).from(editorial).where(eq(editorial.problemId, problemId)).limit(1);
+ if (editorialResult.length === 0) {
+ throw new ApiError_default("Editorial not found. Please upload editorial before finalizing.", E.BAD_REQUEST);
+ }
+ const editorialData = editorialResult[0];
+ const contentResponse = await fetchTestcasesFromS3(editorialData.contentS3Key);
+ if (!contentResponse) {
+ throw new ApiError_default("Content file not found in storage: /content.md", E.BAD_REQUEST);
+ }
+ const solutionResponse = await fetchTestcasesFromS3(editorialData.solutionS3Key);
+ if (!solutionResponse) {
+ throw new ApiError_default("Solution file not found in storage: /solution.md", E.BAD_REQUEST);
+ }
+ await db.update(problem).set({
+ status: "DONE"
+ }).where(eq(problem.id, problemId));
+ return {
+ message: "Problem finalized successfully",
+ status: true
+ };
+ } catch (error) {
+ if (error instanceof ApiError_default) {
+ throw error;
+ }
+ console.error("Error finalizing problem:", error);
+ throw new ApiError_default("Failed to finalize problem", E.INTERNAL_SERVER_ERROR);
+ }
+};
+var handleGetProblems = async (input) => {
+ try {
+ let cursorCreatedAt = null;
+ let cursorId = null;
+ if (input.cursor) {
+ try {
+ const decoded = Buffer.from(input.cursor, "base64").toString("utf-8");
+ const [timeStr, id] = decoded.split(":");
+ cursorCreatedAt = new Date(parseInt(timeStr));
+ cursorId = id;
+ } catch (e3) {
+ throw new ApiError_default("Invalid cursor", E.BAD_REQUEST);
+ }
+ }
+ const problemsResult = await db.select({
+ id: problem.id,
+ title: problem.title,
+ description: problem.description,
+ slug: problem.slug,
+ difficulty: problem.difficulty,
+ createdAt: problem.createdAt,
+ updatedAt: problem.updatedAt
+ }).from(problem).where(and(eq(problem.status, "DONE"), cursorCreatedAt && cursorId ? or(lt(problem.createdAt, cursorCreatedAt), and(eq(problem.createdAt, cursorCreatedAt), lt(problem.id, cursorId))) : undefined)).limit(input.limit + 1).orderBy(desc(problem.createdAt), desc(problem.id));
+ const hasNextPage = problemsResult.length > input.limit;
+ const problems = hasNextPage ? problemsResult.slice(0, input.limit) : problemsResult;
+ let nextCursor = null;
+ if (hasNextPage && problems.length > 0) {
+ const lastProblem = problems[problems.length - 1];
+ const time3 = lastProblem.createdAt.getTime();
+ nextCursor = Buffer.from(`${time3}:${lastProblem.id}`).toString("base64");
+ }
+ if (problems.length === 0) {
+ return { problems: [], nextCursor: null };
+ }
+ const problemIds = problems.map((p2) => p2.id);
+ const tagsResult = await db.select({
+ problemId: problemTag.problemId,
+ tagName: tag.name
+ }).from(problemTag).innerJoin(tag, eq(problemTag.tagId, tag.id)).where(inArray(problemTag.problemId, problemIds));
+ const assembledProblems = problems.map((p2) => {
+ const pTags = tagsResult.filter((t9) => t9.problemId === p2.id).map((t9) => t9.tagName);
+ return {
+ ...p2,
+ tags: pTags
+ };
+ });
+ return {
+ problems: assembledProblems,
+ nextCursor
+ };
+ } catch (error) {
+ if (error instanceof ApiError_default) {
+ throw error;
+ }
+ console.error("Error fetching problems:", error);
+ throw new ApiError_default("Failed to fetch problems", E.INTERNAL_SERVER_ERROR);
+ }
+};
+var handleGetProblemById = async (problemId) => {
+ try {
+ const problemResult = await db.select().from(problem).where(and(eq(problem.id, problemId), eq(problem.status, "DONE"))).limit(1);
+ if (problemResult.length === 0) {
+ throw new ApiError_default("Problem not found", E.NOT_FOUND);
+ }
+ const p2 = problemResult[0];
+ const tagsResult = await db.select({
+ tagName: tag.name
+ }).from(problemTag).innerJoin(tag, eq(problemTag.tagId, tag.id)).where(eq(problemTag.problemId, problemId));
+ const testcasesResult = await db.select({
+ id: testcase.id,
+ order: testcase.order,
+ s3Key: testcase.s3Key
+ }).from(testcase).where(and(eq(testcase.problemId, problemId), eq(testcase.isSample, true)));
+ const sampleTestcases = await Promise.all(testcasesResult.map(async (tc) => {
+ const response = await fetchTestcasesFromS3(tc.s3Key);
+ if (!response) {
+ throw new ApiError_default("Testcase file not found: " + tc.s3Key, E.INTERNAL_SERVER_ERROR);
+ }
+ return {
+ id: tc.id,
+ order: tc.order,
+ input: response.input,
+ output: response.output
+ };
+ }));
+ return {
+ ...p2,
+ difficulty: p2.difficulty,
+ tags: tagsResult.map((t9) => t9.tagName),
+ sampleTestcases
+ };
+ } catch (error) {
+ if (error instanceof ApiError_default) {
+ throw error;
+ }
+ console.error("Error fetching problem by id:", error);
+ throw new ApiError_default("Failed to fetch problem details", E.INTERNAL_SERVER_ERROR);
+ }
+};
+var handleGetEditorialSolution = async (problemId) => {
+ try {
+ const editorialResult = await db.select().from(editorial).where(eq(editorial.problemId, problemId)).limit(1);
+ if (editorialResult.length === 0) {
+ throw new ApiError_default("Editorial not found", E.NOT_FOUND);
+ }
+ const editorials = editorialResult[0];
+ const solutionResponse = await fetchFileFromS3(editorials.solutionS3Key);
+ if (!solutionResponse) {
+ throw new ApiError_default("Solution file not found in storage: " + editorials.solutionS3Key, E.INTERNAL_SERVER_ERROR);
+ }
+ return solutionResponse;
+ } catch (error) {
+ if (error instanceof ApiError_default) {
+ throw error;
+ }
+ console.error("Error fetching editorial solution:", error);
+ throw new ApiError_default("Failed to fetch editorial solution", E.INTERNAL_SERVER_ERROR);
+ }
+};
+var handleGetEditorialContent = async (problemId) => {
+ try {
+ const editorialResult = await db.select({
+ contentS3Key: editorial.contentS3Key,
+ editorialLink: editorial.editorialLink
+ }).from(editorial).where(eq(editorial.problemId, problemId)).limit(1);
+ if (editorialResult.length === 0) {
+ throw new ApiError_default("Editorial not found", E.NOT_FOUND);
+ }
+ const editorials = editorialResult[0];
+ const editorialContentResponse = await fetchFileFromS3(editorials.contentS3Key);
+ if (!editorialContentResponse) {
+ throw new ApiError_default("Editorial content not found in storage: " + editorials.contentS3Key, E.INTERNAL_SERVER_ERROR);
+ }
+ return {
+ editorialContent: editorialContentResponse,
+ editorialLink: editorials.editorialLink
+ };
+ } catch (error) {
+ if (error instanceof ApiError_default) {
+ throw error;
+ }
+ console.error("Error fetching editorial content:", error);
+ throw new ApiError_default("Failed to fetch editorial content", E.INTERNAL_SERVER_ERROR);
+ }
+};
+var handleGetHints = async (problemId) => {
+ try {
+ const result = await db.select({
+ difficulty: problem.difficulty,
+ description: problem.description,
+ inputFormat: problem.inputFormat,
+ outputFormat: problem.outputFormat,
+ constraints: problem.constraints
+ }).from(problem).innerJoin(problemTag, eq(problem.id, problemTag.problemId)).innerJoin(tag, eq(problemTag.tagId, tag.id)).innerJoin(testcase, eq(problem.id, testcase.problemId)).where(eq(problem.id, problemId));
+ if (!result) {
+ throw new ApiError_default("Problem not found", E.NOT_FOUND);
+ }
+ const hintResults = await db.select({
+ title: hint.title,
+ content: hint.content,
+ order: hint.order
+ }).from(hint).where(eq(hint.problemId, problemId));
+ if (hintResults.length > 0) {
+ const hints2 = hintResults.map((h2) => {
+ return {
+ title: h2.title,
+ content: h2.content,
+ order: h2.order
+ };
+ });
+ return hints2;
+ }
+ const hints = await generateHintsWithAI(result[0]);
+ const hintsToInsert = hints.map((h2) => ({
+ ...h2,
+ problemId
+ }));
+ await db.insert(hint).values(hintsToInsert);
+ return hints;
+ } catch (error) {
+ if (error instanceof ApiError_default) {
+ throw error;
+ }
+ console.error("Error fetching hints:", error);
+ throw new ApiError_default("Failed to fetch hints", E.INTERNAL_SERVER_ERROR);
+ }
+};
+
+// src/api/problem/problem-controller.ts
+var createProblem = asyncHandler_default(async (req, res) => {
+ const response = await handleCreateProblem(req.user.id, req.body);
+ return res.status(200).json({
+ status: "success",
+ message: "Problem created successfully",
+ data: response
+ });
+});
+var finalizeProblem = asyncHandler_default(async (req, res) => {
+ const problemId = req.query.problemId;
+ await handleFinalizeProblem(req.user.id, problemId);
+ return res.status(200).json({
+ status: "success",
+ message: "Problem finalized successfully"
+ });
+});
+var getProblems = asyncHandler_default(async (req, res) => {
+ const limit = parseInt(req.query.limit) || 10;
+ const cursor = req.query.cursor;
+ const response = await handleGetProblems({ limit, cursor });
+ return res.status(200).json({
+ status: "success",
+ message: "Problems fetched successfully",
+ data: response
+ });
+});
+var getProblemById = asyncHandler_default(async (req, res) => {
+ const problemId = req.params.problemId;
+ const response = await handleGetProblemById(problemId);
+ return res.status(200).json({
+ status: "success",
+ message: "Problem fetched successfully",
+ data: response
+ });
+});
+var getEditorialSolution = asyncHandler_default(async (req, res) => {
+ const problemId = req.params.problemId;
+ const response = await handleGetEditorialSolution(problemId);
+ return res.status(200).json({
+ status: "success",
+ message: "Editorial solution fetched successfully",
+ data: response
+ });
+});
+var getEditorialContent = asyncHandler_default(async (req, res) => {
+ const problemId = req.params.problemId;
+ const response = await handleGetEditorialContent(problemId);
+ return res.status(200).json({
+ status: "success",
+ message: "Editorial solution fetched successfully",
+ data: response
+ });
+});
+var getHints = asyncHandler_default(async (req, res) => {
+ const problemId = req.params.problemId;
+ const response = await handleGetHints(problemId);
+ if (response.length > 0) {
+ return res.status(200).json({
+ status: "success",
+ message: "Hints are generated successfully",
+ data: response
+ });
+ } else {
+ return res.status(200).json({
+ status: "success",
+ message: "Hints are not generated yet",
+ data: []
+ });
+ }
+});
+
+// src/api/problem/problem-route.ts
+var router2 = import_express2.Router();
+router2.post("/create", validate("body", createProblemSchema), verifyJWT, createProblem);
+router2.post("/finalize", verifyJWT, finalizeProblem);
+router2.get("/", validate("query", getProblemsSchema), getProblems);
+router2.get("/:problemId", getProblemById);
+router2.get("/:problemId/editorial-solution", getEditorialSolution);
+router2.get("/:problemId/editorial-content", getEditorialContent);
+router2.get("/:problemId/hints", getHints);
+var problem_route_default = router2;
+
+// src/api/submission/submission-route.ts
+var import_express3 = __toESM(require_express(), 1);
+
+// src/api/submission/submission-schema.ts
+var createSubmissionSchema = create$3({
+ code: create$6().required("Code is required"),
+ language: create$6().required("Language is required")
+});
+var problemIdSchema = create$3({
+ problemId: create$6().required("Problem ID is required")
+});
+
+// src/loaders/redis.ts
+var import_ioredis = __toESM(require_built3(), 1);
+var import_dotenv3 = __toESM(require_main(), 1);
+import_dotenv3.default.config();
+var redisUrl = process.env.REDIS_URL;
+if (!redisUrl) {
+ throw new Error("REDIS_URL is not set");
+}
+var redis = new import_ioredis.default(redisUrl);
+var redis_default = redis;
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/backoffs.js
+class Backoffs {
+ static normalize(backoff) {
+ if (Number.isFinite(backoff)) {
+ return {
+ type: "fixed",
+ delay: backoff
+ };
+ } else if (backoff) {
+ return backoff;
+ }
+ }
+ static calculate(backoff, attemptsMade, err, job, customStrategy) {
+ if (backoff) {
+ const strategy = lookupStrategy(backoff, customStrategy);
+ return strategy(attemptsMade, backoff.type, err, job);
+ }
+ }
+}
+Backoffs.builtinStrategies = {
+ fixed: function(delay, jitter = 0) {
+ return function() {
+ if (jitter > 0) {
+ const minDelay = delay * (1 - jitter);
+ return Math.floor(Math.random() * delay * jitter + minDelay);
+ } else {
+ return delay;
+ }
+ };
+ },
+ exponential: function(delay, jitter = 0) {
+ return function(attemptsMade) {
+ if (jitter > 0) {
+ const maxDelay = Math.round(Math.pow(2, attemptsMade - 1) * delay);
+ const minDelay = maxDelay * (1 - jitter);
+ return Math.floor(Math.random() * maxDelay * jitter + minDelay);
+ } else {
+ return Math.round(Math.pow(2, attemptsMade - 1) * delay);
+ }
+ };
+ }
+};
+function lookupStrategy(backoff, customStrategy) {
+ if (backoff.type in Backoffs.builtinStrategies) {
+ return Backoffs.builtinStrategies[backoff.type](backoff.delay, backoff.jitter);
+ } else if (customStrategy) {
+ return customStrategy;
+ } else {
+ throw new Error(`Unknown backoff strategy ${backoff.type}.
+ If a custom backoff strategy is used, specify it when the queue is created.`);
+ }
+}
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/enums/child-command.js
+var ChildCommand;
+(function(ChildCommand2) {
+ ChildCommand2[ChildCommand2["Init"] = 0] = "Init";
+ ChildCommand2[ChildCommand2["Start"] = 1] = "Start";
+ ChildCommand2[ChildCommand2["Stop"] = 2] = "Stop";
+ ChildCommand2[ChildCommand2["GetChildrenValuesResponse"] = 3] = "GetChildrenValuesResponse";
+ ChildCommand2[ChildCommand2["GetIgnoredChildrenFailuresResponse"] = 4] = "GetIgnoredChildrenFailuresResponse";
+ ChildCommand2[ChildCommand2["GetDependenciesCountResponse"] = 5] = "GetDependenciesCountResponse";
+ ChildCommand2[ChildCommand2["MoveToWaitingChildrenResponse"] = 6] = "MoveToWaitingChildrenResponse";
+ ChildCommand2[ChildCommand2["Cancel"] = 7] = "Cancel";
+ ChildCommand2[ChildCommand2["GetDependenciesResponse"] = 8] = "GetDependenciesResponse";
+})(ChildCommand || (ChildCommand = {}));
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/enums/error-code.js
+var ErrorCode;
+(function(ErrorCode2) {
+ ErrorCode2[ErrorCode2["JobNotExist"] = -1] = "JobNotExist";
+ ErrorCode2[ErrorCode2["JobLockNotExist"] = -2] = "JobLockNotExist";
+ ErrorCode2[ErrorCode2["JobNotInState"] = -3] = "JobNotInState";
+ ErrorCode2[ErrorCode2["JobPendingChildren"] = -4] = "JobPendingChildren";
+ ErrorCode2[ErrorCode2["ParentJobNotExist"] = -5] = "ParentJobNotExist";
+ ErrorCode2[ErrorCode2["JobLockMismatch"] = -6] = "JobLockMismatch";
+ ErrorCode2[ErrorCode2["ParentJobCannotBeReplaced"] = -7] = "ParentJobCannotBeReplaced";
+ ErrorCode2[ErrorCode2["JobBelongsToJobScheduler"] = -8] = "JobBelongsToJobScheduler";
+ ErrorCode2[ErrorCode2["JobHasFailedChildren"] = -9] = "JobHasFailedChildren";
+ ErrorCode2[ErrorCode2["SchedulerJobIdCollision"] = -10] = "SchedulerJobIdCollision";
+ ErrorCode2[ErrorCode2["SchedulerJobSlotsBusy"] = -11] = "SchedulerJobSlotsBusy";
+})(ErrorCode || (ErrorCode = {}));
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/enums/parent-command.js
+var ParentCommand;
+(function(ParentCommand2) {
+ ParentCommand2[ParentCommand2["Completed"] = 0] = "Completed";
+ ParentCommand2[ParentCommand2["Error"] = 1] = "Error";
+ ParentCommand2[ParentCommand2["Failed"] = 2] = "Failed";
+ ParentCommand2[ParentCommand2["InitFailed"] = 3] = "InitFailed";
+ ParentCommand2[ParentCommand2["InitCompleted"] = 4] = "InitCompleted";
+ ParentCommand2[ParentCommand2["Log"] = 5] = "Log";
+ ParentCommand2[ParentCommand2["MoveToDelayed"] = 6] = "MoveToDelayed";
+ ParentCommand2[ParentCommand2["MoveToWait"] = 7] = "MoveToWait";
+ ParentCommand2[ParentCommand2["Progress"] = 8] = "Progress";
+ ParentCommand2[ParentCommand2["Update"] = 9] = "Update";
+ ParentCommand2[ParentCommand2["GetChildrenValues"] = 10] = "GetChildrenValues";
+ ParentCommand2[ParentCommand2["GetIgnoredChildrenFailures"] = 11] = "GetIgnoredChildrenFailures";
+ ParentCommand2[ParentCommand2["GetDependenciesCount"] = 12] = "GetDependenciesCount";
+ ParentCommand2[ParentCommand2["MoveToWaitingChildren"] = 13] = "MoveToWaitingChildren";
+ ParentCommand2[ParentCommand2["GetDependencies"] = 14] = "GetDependencies";
+})(ParentCommand || (ParentCommand = {}));
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/enums/metrics-time.js
+var MetricsTime;
+(function(MetricsTime2) {
+ MetricsTime2[MetricsTime2["ONE_MINUTE"] = 1] = "ONE_MINUTE";
+ MetricsTime2[MetricsTime2["FIVE_MINUTES"] = 5] = "FIVE_MINUTES";
+ MetricsTime2[MetricsTime2["FIFTEEN_MINUTES"] = 15] = "FIFTEEN_MINUTES";
+ MetricsTime2[MetricsTime2["THIRTY_MINUTES"] = 30] = "THIRTY_MINUTES";
+ MetricsTime2[MetricsTime2["ONE_HOUR"] = 60] = "ONE_HOUR";
+ MetricsTime2[MetricsTime2["ONE_WEEK"] = 10080] = "ONE_WEEK";
+ MetricsTime2[MetricsTime2["TWO_WEEKS"] = 20160] = "TWO_WEEKS";
+ MetricsTime2[MetricsTime2["ONE_MONTH"] = 80640] = "ONE_MONTH";
+})(MetricsTime || (MetricsTime = {}));
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/enums/telemetry-attributes.js
+var TelemetryAttributes;
+(function(TelemetryAttributes2) {
+ TelemetryAttributes2["QueueName"] = "bullmq.queue.name";
+ TelemetryAttributes2["QueueOperation"] = "bullmq.queue.operation";
+ TelemetryAttributes2["BulkCount"] = "bullmq.job.bulk.count";
+ TelemetryAttributes2["BulkNames"] = "bullmq.job.bulk.names";
+ TelemetryAttributes2["JobName"] = "bullmq.job.name";
+ TelemetryAttributes2["JobId"] = "bullmq.job.id";
+ TelemetryAttributes2["JobKey"] = "bullmq.job.key";
+ TelemetryAttributes2["JobIds"] = "bullmq.job.ids";
+ TelemetryAttributes2["JobAttemptsMade"] = "bullmq.job.attempts.made";
+ TelemetryAttributes2["DeduplicationKey"] = "bullmq.job.deduplication.key";
+ TelemetryAttributes2["JobOptions"] = "bullmq.job.options";
+ TelemetryAttributes2["JobProgress"] = "bullmq.job.progress";
+ TelemetryAttributes2["QueueDrainDelay"] = "bullmq.queue.drain.delay";
+ TelemetryAttributes2["QueueGrace"] = "bullmq.queue.grace";
+ TelemetryAttributes2["QueueCleanLimit"] = "bullmq.queue.clean.limit";
+ TelemetryAttributes2["QueueRateLimit"] = "bullmq.queue.rate.limit";
+ TelemetryAttributes2["JobType"] = "bullmq.job.type";
+ TelemetryAttributes2["QueueOptions"] = "bullmq.queue.options";
+ TelemetryAttributes2["QueueEventMaxLength"] = "bullmq.queue.event.max.length";
+ TelemetryAttributes2["QueueJobsState"] = "bullmq.queue.jobs.state";
+ TelemetryAttributes2["WorkerOptions"] = "bullmq.worker.options";
+ TelemetryAttributes2["WorkerName"] = "bullmq.worker.name";
+ TelemetryAttributes2["WorkerId"] = "bullmq.worker.id";
+ TelemetryAttributes2["WorkerRateLimit"] = "bullmq.worker.rate.limit";
+ TelemetryAttributes2["WorkerDoNotWaitActive"] = "bullmq.worker.do.not.wait.active";
+ TelemetryAttributes2["WorkerForceClose"] = "bullmq.worker.force.close";
+ TelemetryAttributes2["WorkerStalledJobs"] = "bullmq.worker.stalled.jobs";
+ TelemetryAttributes2["WorkerFailedJobs"] = "bullmq.worker.failed.jobs";
+ TelemetryAttributes2["WorkerJobsToExtendLocks"] = "bullmq.worker.jobs.to.extend.locks";
+ TelemetryAttributes2["JobFinishedTimestamp"] = "bullmq.job.finished.timestamp";
+ TelemetryAttributes2["JobAttemptFinishedTimestamp"] = "bullmq.job.attempt_finished_timestamp";
+ TelemetryAttributes2["JobProcessedTimestamp"] = "bullmq.job.processed.timestamp";
+ TelemetryAttributes2["JobResult"] = "bullmq.job.result";
+ TelemetryAttributes2["JobFailedReason"] = "bullmq.job.failed.reason";
+ TelemetryAttributes2["FlowName"] = "bullmq.flow.name";
+ TelemetryAttributes2["JobSchedulerId"] = "bullmq.job.scheduler.id";
+ TelemetryAttributes2["JobStatus"] = "bullmq.job.status";
+})(TelemetryAttributes || (TelemetryAttributes = {}));
+var MetricNames;
+(function(MetricNames2) {
+ MetricNames2["QueueJobsCount"] = "bullmq.queue.jobs";
+ MetricNames2["JobsCompleted"] = "bullmq.jobs.completed";
+ MetricNames2["JobsFailed"] = "bullmq.jobs.failed";
+ MetricNames2["JobsDelayed"] = "bullmq.jobs.delayed";
+ MetricNames2["JobsRetried"] = "bullmq.jobs.retried";
+ MetricNames2["JobsWaiting"] = "bullmq.jobs.waiting";
+ MetricNames2["JobsWaitingChildren"] = "bullmq.jobs.waiting_children";
+ MetricNames2["JobDuration"] = "bullmq.job.duration";
+})(MetricNames || (MetricNames = {}));
+var SpanKind;
+(function(SpanKind2) {
+ SpanKind2[SpanKind2["INTERNAL"] = 0] = "INTERNAL";
+ SpanKind2[SpanKind2["SERVER"] = 1] = "SERVER";
+ SpanKind2[SpanKind2["CLIENT"] = 2] = "CLIENT";
+ SpanKind2[SpanKind2["PRODUCER"] = 3] = "PRODUCER";
+ SpanKind2[SpanKind2["CONSUMER"] = 4] = "CONSUMER";
+})(SpanKind || (SpanKind = {}));
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/abort-controller.js
+var import_node_abort_controller = __toESM(require_node_abort_controller(), 1);
+var AbortControllerImpl;
+if (globalThis.AbortController) {
+ AbortControllerImpl = globalThis.AbortController;
+} else {
+ AbortControllerImpl = import_node_abort_controller.AbortController;
+}
+
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/utils/index.js
+var import_ioredis2 = __toESM(require_built3(), 1);
+var import_utils54 = __toESM(require_utils7(), 1);
+var semver = __toESM(require_semver2(), 1);
+var errorObject = { value: null };
+function tryCatch(fn, ctx, args) {
+ try {
+ return fn.apply(ctx, args);
+ } catch (e3) {
+ errorObject.value = e3;
+ return errorObject;
+ }
+}
+function lengthInUtf8Bytes(str) {
+ return Buffer.byteLength(str, "utf8");
+}
+function isEmpty(obj) {
+ for (const key in obj) {
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
+ return false;
+ }
+ }
+ return true;
+}
+function array2obj(arr) {
+ const obj = {};
+ for (let i2 = 0;i2 < arr.length; i2 += 2) {
+ obj[arr[i2]] = arr[i2 + 1];
+ }
+ return obj;
+}
+function objectToFlatArray(obj) {
+ const arr = [];
+ for (const key in obj) {
+ if (Object.prototype.hasOwnProperty.call(obj, key) && obj[key] !== undefined) {
+ arr[arr.length] = key;
+ arr[arr.length] = obj[key];
+ }
+ }
+ return arr;
+}
+function delay(ms, abortController) {
+ return new Promise((resolve) => {
+ let timeout;
+ const callback = () => {
+ abortController === null || abortController === undefined || abortController.signal.removeEventListener("abort", callback);
+ clearTimeout(timeout);
+ resolve();
+ };
+ timeout = setTimeout(callback, ms);
+ abortController === null || abortController === undefined || abortController.signal.addEventListener("abort", callback);
+ });
+}
+function increaseMaxListeners(emitter, count2) {
+ const maxListeners = emitter.getMaxListeners();
+ emitter.setMaxListeners(maxListeners + count2);
+}
+function invertObject(obj) {
+ return Object.entries(obj).reduce((result, [key, value]) => {
+ result[value] = key;
+ return result;
+ }, {});
+}
+var optsDecodeMap = {
+ de: "deduplication",
+ fpof: "failParentOnFailure",
+ cpof: "continueParentOnFailure",
+ idof: "ignoreDependencyOnFailure",
+ kl: "keepLogs",
+ rdof: "removeDependencyOnFailure"
+};
+var optsEncodeMap = Object.assign(Object.assign({}, invertObject(optsDecodeMap)), {
+ debounce: "de"
+});
+function isRedisInstance(obj) {
+ if (!obj) {
+ return false;
+ }
+ const redisApi = ["connect", "disconnect", "duplicate"];
+ return redisApi.every((name) => typeof obj[name] === "function");
+}
+function isRedisCluster(obj) {
+ return isRedisInstance(obj) && obj.isCluster;
+}
+function decreaseMaxListeners(emitter, count2) {
+ increaseMaxListeners(emitter, -count2);
+}
+function getParentKey(opts) {
+ if (opts) {
+ return `${opts.queue}:${opts.id}`;
+ }
+}
+var clientCommandMessageReg = /ERR unknown command ['`]\s*client\s*['`]/;
+var DELAY_TIME_5 = 5000;
+function isNotConnectionError(error) {
+ const { code, message: errorMessage } = error;
+ return errorMessage !== import_utils54.CONNECTION_CLOSED_ERROR_MSG && !errorMessage.includes("ECONNREFUSED") && code !== "ECONNREFUSED";
+}
+var isRedisVersionLowerThan = (currentVersion, minimumVersion, currentDatabaseType, desiredDatabaseType = "redis") => {
+ if (currentDatabaseType === desiredDatabaseType) {
+ const version3 = semver.valid(semver.coerce(currentVersion));
+ return semver.lt(version3, minimumVersion);
+ }
+ return false;
+};
+var parseObjectValues = (obj) => {
+ const accumulator = {};
+ for (const value of Object.entries(obj)) {
+ accumulator[value[0]] = JSON.parse(value[1]);
+ }
+ return accumulator;
+};
+var INFINITY = 1 / 0;
+var QUEUE_EVENT_SUFFIX = ":qe";
+function removeUndefinedFields(obj) {
+ const newObj = {};
+ for (const key in obj) {
+ if (obj[key] !== undefined) {
+ newObj[key] = obj[key];
+ }
+ }
+ return newObj;
+}
+async function trace(telemetry, spanKind, queueName, operation, destination, callback, srcPropagationMetadata) {
+ if (!telemetry) {
+ return callback();
+ } else {
+ const { tracer: tracer3, contextManager } = telemetry;
+ const currentContext = contextManager.active();
+ let parentContext;
+ if (srcPropagationMetadata) {
+ parentContext = contextManager.fromMetadata(currentContext, srcPropagationMetadata);
+ }
+ const spanName = destination ? `${operation} ${destination}` : operation;
+ const span = tracer3.startSpan(spanName, {
+ kind: spanKind
+ }, parentContext);
+ try {
+ span.setAttributes({
+ [TelemetryAttributes.QueueName]: queueName,
+ [TelemetryAttributes.QueueOperation]: operation
+ });
+ let messageContext;
+ let dstPropagationMetadata;
+ if (spanKind === SpanKind.CONSUMER && parentContext) {
+ messageContext = span.setSpanOnContext(parentContext);
+ } else {
+ messageContext = span.setSpanOnContext(currentContext);
+ }
+ if (callback.length == 2) {
+ dstPropagationMetadata = contextManager.getMetadata(messageContext);
+ }
+ return await contextManager.with(messageContext, () => callback(span, dstPropagationMetadata));
+ } catch (err) {
+ span.recordException(err);
+ throw err;
+ } finally {
+ span.end();
+ }
+ }
+}
+
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/child-processor.js
+var ChildStatus;
+(function(ChildStatus2) {
+ ChildStatus2[ChildStatus2["Idle"] = 0] = "Idle";
+ ChildStatus2[ChildStatus2["Started"] = 1] = "Started";
+ ChildStatus2[ChildStatus2["Terminating"] = 2] = "Terminating";
+ ChildStatus2[ChildStatus2["Errored"] = 3] = "Errored";
+})(ChildStatus || (ChildStatus = {}));
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/errors/unrecoverable-error.js
+var UNRECOVERABLE_ERROR = "bullmq:unrecoverable";
+
+class UnrecoverableError extends Error {
+ constructor(message = UNRECOVERABLE_ERROR) {
+ super(message);
+ this.name = this.constructor.name;
+ Object.setPrototypeOf(this, new.target.prototype);
+ }
+}
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/job.js
+import { debuglog } from "util";
+
+// node_modules/.pnpm/msgpackr@1.11.5/node_modules/msgpackr/unpack.js
+var decoder;
+try {
+ decoder = new TextDecoder;
+} catch (error) {}
+var src;
+var srcEnd;
+var position = 0;
+var EMPTY_ARRAY = [];
+var strings = EMPTY_ARRAY;
+var stringPosition = 0;
+var currentUnpackr = {};
+var currentStructures;
+var srcString;
+var srcStringStart = 0;
+var srcStringEnd = 0;
+var bundledStrings;
+var referenceMap;
+var currentExtensions = [];
+var dataView;
+var defaultOptions = {
+ useRecords: false,
+ mapsAsObjects: true
+};
+
+class C1Type {
+}
+var C1 = new C1Type;
+C1.name = "MessagePack 0xC1";
+var sequentialMode = false;
+var inlineObjectReadThreshold = 2;
+var readStruct;
+var onLoadedStructures;
+var onSaveState;
+try {
+ new Function("");
+} catch (error) {
+ inlineObjectReadThreshold = Infinity;
+}
+
+class Unpackr {
+ constructor(options) {
+ if (options) {
+ if (options.useRecords === false && options.mapsAsObjects === undefined)
+ options.mapsAsObjects = true;
+ if (options.sequential && options.trusted !== false) {
+ options.trusted = true;
+ if (!options.structures && options.useRecords != false) {
+ options.structures = [];
+ if (!options.maxSharedStructures)
+ options.maxSharedStructures = 0;
+ }
+ }
+ if (options.structures)
+ options.structures.sharedLength = options.structures.length;
+ else if (options.getStructures) {
+ (options.structures = []).uninitialized = true;
+ options.structures.sharedLength = 0;
+ }
+ if (options.int64AsNumber) {
+ options.int64AsType = "number";
+ }
+ }
+ Object.assign(this, options);
+ }
+ unpack(source, options) {
+ if (src) {
+ return saveState(() => {
+ clearSource();
+ return this ? this.unpack(source, options) : Unpackr.prototype.unpack.call(defaultOptions, source, options);
+ });
+ }
+ if (!source.buffer && source.constructor === ArrayBuffer)
+ source = typeof Buffer !== "undefined" ? Buffer.from(source) : new Uint8Array(source);
+ if (typeof options === "object") {
+ srcEnd = options.end || source.length;
+ position = options.start || 0;
+ } else {
+ position = 0;
+ srcEnd = options > -1 ? options : source.length;
+ }
+ stringPosition = 0;
+ srcStringEnd = 0;
+ srcString = null;
+ strings = EMPTY_ARRAY;
+ bundledStrings = null;
+ src = source;
+ try {
+ dataView = source.dataView || (source.dataView = new DataView(source.buffer, source.byteOffset, source.byteLength));
+ } catch (error) {
+ src = null;
+ if (source instanceof Uint8Array)
+ throw error;
+ throw new Error("Source must be a Uint8Array or Buffer but was a " + (source && typeof source == "object" ? source.constructor.name : typeof source));
+ }
+ if (this instanceof Unpackr) {
+ currentUnpackr = this;
+ if (this.structures) {
+ currentStructures = this.structures;
+ return checkedRead(options);
+ } else if (!currentStructures || currentStructures.length > 0) {
+ currentStructures = [];
+ }
+ } else {
+ currentUnpackr = defaultOptions;
+ if (!currentStructures || currentStructures.length > 0)
+ currentStructures = [];
+ }
+ return checkedRead(options);
+ }
+ unpackMultiple(source, forEach2) {
+ let values, lastPosition = 0;
+ try {
+ sequentialMode = true;
+ let size = source.length;
+ let value = this ? this.unpack(source, size) : defaultUnpackr.unpack(source, size);
+ if (forEach2) {
+ if (forEach2(value, lastPosition, position) === false)
+ return;
+ while (position < size) {
+ lastPosition = position;
+ if (forEach2(checkedRead(), lastPosition, position) === false) {
+ return;
+ }
+ }
+ } else {
+ values = [value];
+ while (position < size) {
+ lastPosition = position;
+ values.push(checkedRead());
+ }
+ return values;
+ }
+ } catch (error) {
+ error.lastPosition = lastPosition;
+ error.values = values;
+ throw error;
+ } finally {
+ sequentialMode = false;
+ clearSource();
+ }
+ }
+ _mergeStructures(loadedStructures, existingStructures) {
+ if (onLoadedStructures)
+ loadedStructures = onLoadedStructures.call(this, loadedStructures);
+ loadedStructures = loadedStructures || [];
+ if (Object.isFrozen(loadedStructures))
+ loadedStructures = loadedStructures.map((structure) => structure.slice(0));
+ for (let i2 = 0, l2 = loadedStructures.length;i2 < l2; i2++) {
+ let structure = loadedStructures[i2];
+ if (structure) {
+ structure.isShared = true;
+ if (i2 >= 32)
+ structure.highByte = i2 - 32 >> 5;
+ }
+ }
+ loadedStructures.sharedLength = loadedStructures.length;
+ for (let id in existingStructures || []) {
+ if (id >= 0) {
+ let structure = loadedStructures[id];
+ let existing = existingStructures[id];
+ if (existing) {
+ if (structure)
+ (loadedStructures.restoreStructures || (loadedStructures.restoreStructures = []))[id] = structure;
+ loadedStructures[id] = existing;
+ }
+ }
+ }
+ return this.structures = loadedStructures;
+ }
+ decode(source, options) {
+ return this.unpack(source, options);
+ }
+}
+function checkedRead(options) {
+ try {
+ if (!currentUnpackr.trusted && !sequentialMode) {
+ let sharedLength = currentStructures.sharedLength || 0;
+ if (sharedLength < currentStructures.length)
+ currentStructures.length = sharedLength;
+ }
+ let result;
+ if (currentUnpackr.randomAccessStructure && src[position] < 64 && src[position] >= 32 && readStruct) {
+ result = readStruct(src, position, srcEnd, currentUnpackr);
+ src = null;
+ if (!(options && options.lazy) && result)
+ result = result.toJSON();
+ position = srcEnd;
+ } else
+ result = read();
+ if (bundledStrings) {
+ position = bundledStrings.postBundlePosition;
+ bundledStrings = null;
+ }
+ if (sequentialMode)
+ currentStructures.restoreStructures = null;
+ if (position == srcEnd) {
+ if (currentStructures && currentStructures.restoreStructures)
+ restoreStructures();
+ currentStructures = null;
+ src = null;
+ if (referenceMap)
+ referenceMap = null;
+ } else if (position > srcEnd) {
+ throw new Error("Unexpected end of MessagePack data");
+ } else if (!sequentialMode) {
+ let jsonView;
+ try {
+ jsonView = JSON.stringify(result, (_, value) => typeof value === "bigint" ? `${value}n` : value).slice(0, 100);
+ } catch (error) {
+ jsonView = "(JSON view not available " + error + ")";
+ }
+ throw new Error("Data read, but end of buffer not reached " + jsonView);
+ }
+ return result;
+ } catch (error) {
+ if (currentStructures && currentStructures.restoreStructures)
+ restoreStructures();
+ clearSource();
+ if (error instanceof RangeError || error.message.startsWith("Unexpected end of buffer") || position > srcEnd) {
+ error.incomplete = true;
+ }
+ throw error;
+ }
+}
+function restoreStructures() {
+ for (let id in currentStructures.restoreStructures) {
+ currentStructures[id] = currentStructures.restoreStructures[id];
+ }
+ currentStructures.restoreStructures = null;
+}
+function read() {
+ let token = src[position++];
+ if (token < 160) {
+ if (token < 128) {
+ if (token < 64)
+ return token;
+ else {
+ let structure = currentStructures[token & 63] || currentUnpackr.getStructures && loadStructures()[token & 63];
+ if (structure) {
+ if (!structure.read) {
+ structure.read = createStructureReader(structure, token & 63);
+ }
+ return structure.read();
+ } else
+ return token;
+ }
+ } else if (token < 144) {
+ token -= 128;
+ if (currentUnpackr.mapsAsObjects) {
+ let object2 = {};
+ for (let i2 = 0;i2 < token; i2++) {
+ let key = readKey();
+ if (key === "__proto__")
+ key = "__proto_";
+ object2[key] = read();
+ }
+ return object2;
+ } else {
+ let map = new Map;
+ for (let i2 = 0;i2 < token; i2++) {
+ map.set(read(), read());
+ }
+ return map;
+ }
+ } else {
+ token -= 144;
+ let array2 = new Array(token);
+ for (let i2 = 0;i2 < token; i2++) {
+ array2[i2] = read();
+ }
+ if (currentUnpackr.freezeData)
+ return Object.freeze(array2);
+ return array2;
+ }
+ } else if (token < 192) {
+ let length = token - 160;
+ if (srcStringEnd >= position) {
+ return srcString.slice(position - srcStringStart, (position += length) - srcStringStart);
+ }
+ if (srcStringEnd == 0 && srcEnd < 140) {
+ let string2 = length < 16 ? shortStringInJS(length) : longStringInJS(length);
+ if (string2 != null)
+ return string2;
+ }
+ return readFixedString(length);
+ } else {
+ let value;
+ switch (token) {
+ case 192:
+ return null;
+ case 193:
+ if (bundledStrings) {
+ value = read();
+ if (value > 0)
+ return bundledStrings[1].slice(bundledStrings.position1, bundledStrings.position1 += value);
+ else
+ return bundledStrings[0].slice(bundledStrings.position0, bundledStrings.position0 -= value);
+ }
+ return C1;
+ case 194:
+ return false;
+ case 195:
+ return true;
+ case 196:
+ value = src[position++];
+ if (value === undefined)
+ throw new Error("Unexpected end of buffer");
+ return readBin(value);
+ case 197:
+ value = dataView.getUint16(position);
+ position += 2;
+ return readBin(value);
+ case 198:
+ value = dataView.getUint32(position);
+ position += 4;
+ return readBin(value);
+ case 199:
+ return readExt(src[position++]);
+ case 200:
+ value = dataView.getUint16(position);
+ position += 2;
+ return readExt(value);
+ case 201:
+ value = dataView.getUint32(position);
+ position += 4;
+ return readExt(value);
+ case 202:
+ value = dataView.getFloat32(position);
+ if (currentUnpackr.useFloat32 > 2) {
+ let multiplier = mult10[(src[position] & 127) << 1 | src[position + 1] >> 7];
+ position += 4;
+ return (multiplier * value + (value > 0 ? 0.5 : -0.5) >> 0) / multiplier;
+ }
+ position += 4;
+ return value;
+ case 203:
+ value = dataView.getFloat64(position);
+ position += 8;
+ return value;
+ case 204:
+ return src[position++];
+ case 205:
+ value = dataView.getUint16(position);
+ position += 2;
+ return value;
+ case 206:
+ value = dataView.getUint32(position);
+ position += 4;
+ return value;
+ case 207:
+ if (currentUnpackr.int64AsType === "number") {
+ value = dataView.getUint32(position) * 4294967296;
+ value += dataView.getUint32(position + 4);
+ } else if (currentUnpackr.int64AsType === "string") {
+ value = dataView.getBigUint64(position).toString();
+ } else if (currentUnpackr.int64AsType === "auto") {
+ value = dataView.getBigUint64(position);
+ if (value <= BigInt(2) << BigInt(52))
+ value = Number(value);
+ } else
+ value = dataView.getBigUint64(position);
+ position += 8;
+ return value;
+ case 208:
+ return dataView.getInt8(position++);
+ case 209:
+ value = dataView.getInt16(position);
+ position += 2;
+ return value;
+ case 210:
+ value = dataView.getInt32(position);
+ position += 4;
+ return value;
+ case 211:
+ if (currentUnpackr.int64AsType === "number") {
+ value = dataView.getInt32(position) * 4294967296;
+ value += dataView.getUint32(position + 4);
+ } else if (currentUnpackr.int64AsType === "string") {
+ value = dataView.getBigInt64(position).toString();
+ } else if (currentUnpackr.int64AsType === "auto") {
+ value = dataView.getBigInt64(position);
+ if (value >= BigInt(-2) << BigInt(52) && value <= BigInt(2) << BigInt(52))
+ value = Number(value);
+ } else
+ value = dataView.getBigInt64(position);
+ position += 8;
+ return value;
+ case 212:
+ value = src[position++];
+ if (value == 114) {
+ return recordDefinition(src[position++] & 63);
+ } else {
+ let extension = currentExtensions[value];
+ if (extension) {
+ if (extension.read) {
+ position++;
+ return extension.read(read());
+ } else if (extension.noBuffer) {
+ position++;
+ return extension();
+ } else
+ return extension(src.subarray(position, ++position));
+ } else
+ throw new Error("Unknown extension " + value);
+ }
+ case 213:
+ value = src[position];
+ if (value == 114) {
+ position++;
+ return recordDefinition(src[position++] & 63, src[position++]);
+ } else
+ return readExt(2);
+ case 214:
+ return readExt(4);
+ case 215:
+ return readExt(8);
+ case 216:
+ return readExt(16);
+ case 217:
+ value = src[position++];
+ if (srcStringEnd >= position) {
+ return srcString.slice(position - srcStringStart, (position += value) - srcStringStart);
+ }
+ return readString8(value);
+ case 218:
+ value = dataView.getUint16(position);
+ position += 2;
+ if (srcStringEnd >= position) {
+ return srcString.slice(position - srcStringStart, (position += value) - srcStringStart);
+ }
+ return readString16(value);
+ case 219:
+ value = dataView.getUint32(position);
+ position += 4;
+ if (srcStringEnd >= position) {
+ return srcString.slice(position - srcStringStart, (position += value) - srcStringStart);
+ }
+ return readString32(value);
+ case 220:
+ value = dataView.getUint16(position);
+ position += 2;
+ return readArray(value);
+ case 221:
+ value = dataView.getUint32(position);
+ position += 4;
+ return readArray(value);
+ case 222:
+ value = dataView.getUint16(position);
+ position += 2;
+ return readMap(value);
+ case 223:
+ value = dataView.getUint32(position);
+ position += 4;
+ return readMap(value);
+ default:
+ if (token >= 224)
+ return token - 256;
+ if (token === undefined) {
+ let error = new Error("Unexpected end of MessagePack data");
+ error.incomplete = true;
+ throw error;
+ }
+ throw new Error("Unknown MessagePack token " + token);
+ }
+ }
+}
+var validName = /^[a-zA-Z_$][a-zA-Z\d_$]*$/;
+function createStructureReader(structure, firstId) {
+ function readObject() {
+ if (readObject.count++ > inlineObjectReadThreshold) {
+ let readObject2 = structure.read = new Function("r", "return function(){return " + (currentUnpackr.freezeData ? "Object.freeze" : "") + "({" + structure.map((key) => key === "__proto__" ? "__proto_:r()" : validName.test(key) ? key + ":r()" : "[" + JSON.stringify(key) + "]:r()").join(",") + "})}")(read);
+ if (structure.highByte === 0)
+ structure.read = createSecondByteReader(firstId, structure.read);
+ return readObject2();
+ }
+ let object2 = {};
+ for (let i2 = 0, l2 = structure.length;i2 < l2; i2++) {
+ let key = structure[i2];
+ if (key === "__proto__")
+ key = "__proto_";
+ object2[key] = read();
+ }
+ if (currentUnpackr.freezeData)
+ return Object.freeze(object2);
+ return object2;
+ }
+ readObject.count = 0;
+ if (structure.highByte === 0) {
+ return createSecondByteReader(firstId, readObject);
+ }
+ return readObject;
+}
+var createSecondByteReader = (firstId, read0) => {
+ return function() {
+ let highByte = src[position++];
+ if (highByte === 0)
+ return read0();
+ let id = firstId < 32 ? -(firstId + (highByte << 5)) : firstId + (highByte << 5);
+ let structure = currentStructures[id] || loadStructures()[id];
+ if (!structure) {
+ throw new Error("Record id is not defined for " + id);
+ }
+ if (!structure.read)
+ structure.read = createStructureReader(structure, firstId);
+ return structure.read();
+ };
+};
+function loadStructures() {
+ let loadedStructures = saveState(() => {
+ src = null;
+ return currentUnpackr.getStructures();
+ });
+ return currentStructures = currentUnpackr._mergeStructures(loadedStructures, currentStructures);
+}
+var readFixedString = readStringJS;
+var readString8 = readStringJS;
+var readString16 = readStringJS;
+var readString32 = readStringJS;
+var isNativeAccelerationEnabled = false;
+function setExtractor(extractStrings) {
+ isNativeAccelerationEnabled = true;
+ readFixedString = readString(1);
+ readString8 = readString(2);
+ readString16 = readString(3);
+ readString32 = readString(5);
+ function readString(headerLength) {
+ return function readString2(length) {
+ let string2 = strings[stringPosition++];
+ if (string2 == null) {
+ if (bundledStrings)
+ return readStringJS(length);
+ let byteOffset = src.byteOffset;
+ let extraction = extractStrings(position - headerLength + byteOffset, srcEnd + byteOffset, src.buffer);
+ if (typeof extraction == "string") {
+ string2 = extraction;
+ strings = EMPTY_ARRAY;
+ } else {
+ strings = extraction;
+ stringPosition = 1;
+ srcStringEnd = 1;
+ string2 = strings[0];
+ if (string2 === undefined)
+ throw new Error("Unexpected end of buffer");
+ }
+ }
+ let srcStringLength = string2.length;
+ if (srcStringLength <= length) {
+ position += length;
+ return string2;
+ }
+ srcString = string2;
+ srcStringStart = position;
+ srcStringEnd = position + srcStringLength;
+ position += length;
+ return string2.slice(0, length);
+ };
+ }
+}
+function readStringJS(length) {
+ let result;
+ if (length < 16) {
+ if (result = shortStringInJS(length))
+ return result;
+ }
+ if (length > 64 && decoder)
+ return decoder.decode(src.subarray(position, position += length));
+ const end = position + length;
+ const units = [];
+ result = "";
+ while (position < end) {
+ const byte1 = src[position++];
+ if ((byte1 & 128) === 0) {
+ units.push(byte1);
+ } else if ((byte1 & 224) === 192) {
+ const byte2 = src[position++] & 63;
+ units.push((byte1 & 31) << 6 | byte2);
+ } else if ((byte1 & 240) === 224) {
+ const byte2 = src[position++] & 63;
+ const byte3 = src[position++] & 63;
+ units.push((byte1 & 31) << 12 | byte2 << 6 | byte3);
+ } else if ((byte1 & 248) === 240) {
+ const byte2 = src[position++] & 63;
+ const byte3 = src[position++] & 63;
+ const byte4 = src[position++] & 63;
+ let unit = (byte1 & 7) << 18 | byte2 << 12 | byte3 << 6 | byte4;
+ if (unit > 65535) {
+ unit -= 65536;
+ units.push(unit >>> 10 & 1023 | 55296);
+ unit = 56320 | unit & 1023;
+ }
+ units.push(unit);
+ } else {
+ units.push(byte1);
+ }
+ if (units.length >= 4096) {
+ result += fromCharCode.apply(String, units);
+ units.length = 0;
+ }
+ }
+ if (units.length > 0) {
+ result += fromCharCode.apply(String, units);
+ }
+ return result;
+}
+function readString(source, start, length) {
+ let existingSrc = src;
+ src = source;
+ position = start;
+ try {
+ return readStringJS(length);
+ } finally {
+ src = existingSrc;
+ }
+}
+function readArray(length) {
+ let array2 = new Array(length);
+ for (let i2 = 0;i2 < length; i2++) {
+ array2[i2] = read();
+ }
+ if (currentUnpackr.freezeData)
+ return Object.freeze(array2);
+ return array2;
+}
+function readMap(length) {
+ if (currentUnpackr.mapsAsObjects) {
+ let object2 = {};
+ for (let i2 = 0;i2 < length; i2++) {
+ let key = readKey();
+ if (key === "__proto__")
+ key = "__proto_";
+ object2[key] = read();
+ }
+ return object2;
+ } else {
+ let map = new Map;
+ for (let i2 = 0;i2 < length; i2++) {
+ map.set(read(), read());
+ }
+ return map;
+ }
+}
+var fromCharCode = String.fromCharCode;
+function longStringInJS(length) {
+ let start = position;
+ let bytes = new Array(length);
+ for (let i2 = 0;i2 < length; i2++) {
+ const byte = src[position++];
+ if ((byte & 128) > 0) {
+ position = start;
+ return;
+ }
+ bytes[i2] = byte;
+ }
+ return fromCharCode.apply(String, bytes);
+}
+function shortStringInJS(length) {
+ if (length < 4) {
+ if (length < 2) {
+ if (length === 0)
+ return "";
+ else {
+ let a2 = src[position++];
+ if ((a2 & 128) > 1) {
+ position -= 1;
+ return;
+ }
+ return fromCharCode(a2);
+ }
+ } else {
+ let a2 = src[position++];
+ let b2 = src[position++];
+ if ((a2 & 128) > 0 || (b2 & 128) > 0) {
+ position -= 2;
+ return;
+ }
+ if (length < 3)
+ return fromCharCode(a2, b2);
+ let c2 = src[position++];
+ if ((c2 & 128) > 0) {
+ position -= 3;
+ return;
+ }
+ return fromCharCode(a2, b2, c2);
+ }
+ } else {
+ let a2 = src[position++];
+ let b2 = src[position++];
+ let c2 = src[position++];
+ let d2 = src[position++];
+ if ((a2 & 128) > 0 || (b2 & 128) > 0 || (c2 & 128) > 0 || (d2 & 128) > 0) {
+ position -= 4;
+ return;
+ }
+ if (length < 6) {
+ if (length === 4)
+ return fromCharCode(a2, b2, c2, d2);
+ else {
+ let e3 = src[position++];
+ if ((e3 & 128) > 0) {
+ position -= 5;
+ return;
+ }
+ return fromCharCode(a2, b2, c2, d2, e3);
+ }
+ } else if (length < 8) {
+ let e3 = src[position++];
+ let f2 = src[position++];
+ if ((e3 & 128) > 0 || (f2 & 128) > 0) {
+ position -= 6;
+ return;
+ }
+ if (length < 7)
+ return fromCharCode(a2, b2, c2, d2, e3, f2);
+ let g2 = src[position++];
+ if ((g2 & 128) > 0) {
+ position -= 7;
+ return;
+ }
+ return fromCharCode(a2, b2, c2, d2, e3, f2, g2);
+ } else {
+ let e3 = src[position++];
+ let f2 = src[position++];
+ let g2 = src[position++];
+ let h2 = src[position++];
+ if ((e3 & 128) > 0 || (f2 & 128) > 0 || (g2 & 128) > 0 || (h2 & 128) > 0) {
+ position -= 8;
+ return;
+ }
+ if (length < 10) {
+ if (length === 8)
+ return fromCharCode(a2, b2, c2, d2, e3, f2, g2, h2);
+ else {
+ let i2 = src[position++];
+ if ((i2 & 128) > 0) {
+ position -= 9;
+ return;
+ }
+ return fromCharCode(a2, b2, c2, d2, e3, f2, g2, h2, i2);
+ }
+ } else if (length < 12) {
+ let i2 = src[position++];
+ let j2 = src[position++];
+ if ((i2 & 128) > 0 || (j2 & 128) > 0) {
+ position -= 10;
+ return;
+ }
+ if (length < 11)
+ return fromCharCode(a2, b2, c2, d2, e3, f2, g2, h2, i2, j2);
+ let k2 = src[position++];
+ if ((k2 & 128) > 0) {
+ position -= 11;
+ return;
+ }
+ return fromCharCode(a2, b2, c2, d2, e3, f2, g2, h2, i2, j2, k2);
+ } else {
+ let i2 = src[position++];
+ let j2 = src[position++];
+ let k2 = src[position++];
+ let l2 = src[position++];
+ if ((i2 & 128) > 0 || (j2 & 128) > 0 || (k2 & 128) > 0 || (l2 & 128) > 0) {
+ position -= 12;
+ return;
+ }
+ if (length < 14) {
+ if (length === 12)
+ return fromCharCode(a2, b2, c2, d2, e3, f2, g2, h2, i2, j2, k2, l2);
+ else {
+ let m2 = src[position++];
+ if ((m2 & 128) > 0) {
+ position -= 13;
+ return;
+ }
+ return fromCharCode(a2, b2, c2, d2, e3, f2, g2, h2, i2, j2, k2, l2, m2);
+ }
+ } else {
+ let m2 = src[position++];
+ let n2 = src[position++];
+ if ((m2 & 128) > 0 || (n2 & 128) > 0) {
+ position -= 14;
+ return;
+ }
+ if (length < 15)
+ return fromCharCode(a2, b2, c2, d2, e3, f2, g2, h2, i2, j2, k2, l2, m2, n2);
+ let o2 = src[position++];
+ if ((o2 & 128) > 0) {
+ position -= 15;
+ return;
+ }
+ return fromCharCode(a2, b2, c2, d2, e3, f2, g2, h2, i2, j2, k2, l2, m2, n2, o2);
+ }
+ }
+ }
+ }
+}
+function readOnlyJSString() {
+ let token = src[position++];
+ let length;
+ if (token < 192) {
+ length = token - 160;
+ } else {
+ switch (token) {
+ case 217:
+ length = src[position++];
+ break;
+ case 218:
+ length = dataView.getUint16(position);
+ position += 2;
+ break;
+ case 219:
+ length = dataView.getUint32(position);
+ position += 4;
+ break;
+ default:
+ throw new Error("Expected string");
+ }
+ }
+ return readStringJS(length);
+}
+function readBin(length) {
+ return currentUnpackr.copyBuffers ? Uint8Array.prototype.slice.call(src, position, position += length) : src.subarray(position, position += length);
+}
+function readExt(length) {
+ let type = src[position++];
+ if (currentExtensions[type]) {
+ let end;
+ return currentExtensions[type](src.subarray(position, end = position += length), (readPosition) => {
+ position = readPosition;
+ try {
+ return read();
+ } finally {
+ position = end;
+ }
+ });
+ } else
+ throw new Error("Unknown extension type " + type);
+}
+var keyCache = new Array(4096);
+function readKey() {
+ let length = src[position++];
+ if (length >= 160 && length < 192) {
+ length = length - 160;
+ if (srcStringEnd >= position)
+ return srcString.slice(position - srcStringStart, (position += length) - srcStringStart);
+ else if (!(srcStringEnd == 0 && srcEnd < 180))
+ return readFixedString(length);
+ } else {
+ position--;
+ return asSafeString(read());
+ }
+ let key = (length << 5 ^ (length > 1 ? dataView.getUint16(position) : length > 0 ? src[position] : 0)) & 4095;
+ let entry = keyCache[key];
+ let checkPosition = position;
+ let end = position + length - 3;
+ let chunk;
+ let i2 = 0;
+ if (entry && entry.bytes == length) {
+ while (checkPosition < end) {
+ chunk = dataView.getUint32(checkPosition);
+ if (chunk != entry[i2++]) {
+ checkPosition = 1879048192;
+ break;
+ }
+ checkPosition += 4;
+ }
+ end += 3;
+ while (checkPosition < end) {
+ chunk = src[checkPosition++];
+ if (chunk != entry[i2++]) {
+ checkPosition = 1879048192;
+ break;
+ }
+ }
+ if (checkPosition === end) {
+ position = checkPosition;
+ return entry.string;
+ }
+ end -= 3;
+ checkPosition = position;
+ }
+ entry = [];
+ keyCache[key] = entry;
+ entry.bytes = length;
+ while (checkPosition < end) {
+ chunk = dataView.getUint32(checkPosition);
+ entry.push(chunk);
+ checkPosition += 4;
+ }
+ end += 3;
+ while (checkPosition < end) {
+ chunk = src[checkPosition++];
+ entry.push(chunk);
+ }
+ let string2 = length < 16 ? shortStringInJS(length) : longStringInJS(length);
+ if (string2 != null)
+ return entry.string = string2;
+ return entry.string = readFixedString(length);
+}
+function asSafeString(property) {
+ if (typeof property === "string")
+ return property;
+ if (typeof property === "number" || typeof property === "boolean" || typeof property === "bigint")
+ return property.toString();
+ if (property == null)
+ return property + "";
+ if (currentUnpackr.allowArraysInMapKeys && Array.isArray(property) && property.flat().every((item) => ["string", "number", "boolean", "bigint"].includes(typeof item))) {
+ return property.flat().toString();
+ }
+ throw new Error(`Invalid property type for record: ${typeof property}`);
+}
+var recordDefinition = (id, highByte) => {
+ let structure = read().map(asSafeString);
+ let firstByte = id;
+ if (highByte !== undefined) {
+ id = id < 32 ? -((highByte << 5) + id) : (highByte << 5) + id;
+ structure.highByte = highByte;
+ }
+ let existingStructure = currentStructures[id];
+ if (existingStructure && (existingStructure.isShared || sequentialMode)) {
+ (currentStructures.restoreStructures || (currentStructures.restoreStructures = []))[id] = existingStructure;
+ }
+ currentStructures[id] = structure;
+ structure.read = createStructureReader(structure, firstByte);
+ return structure.read();
+};
+currentExtensions[0] = () => {};
+currentExtensions[0].noBuffer = true;
+currentExtensions[66] = (data) => {
+ let headLength = data.byteLength % 8 || 8;
+ let head = BigInt(data[0] & 128 ? data[0] - 256 : data[0]);
+ for (let i2 = 1;i2 < headLength; i2++) {
+ head <<= BigInt(8);
+ head += BigInt(data[i2]);
+ }
+ if (data.byteLength !== headLength) {
+ let view = new DataView(data.buffer, data.byteOffset, data.byteLength);
+ let decode = (start, end) => {
+ let length = end - start;
+ if (length <= 40) {
+ let out = view.getBigUint64(start);
+ for (let i2 = start + 8;i2 < end; i2 += 8) {
+ out <<= BigInt(64n);
+ out |= view.getBigUint64(i2);
+ }
+ return out;
+ }
+ let middle = start + (length >> 4 << 3);
+ let left = decode(start, middle);
+ let right = decode(middle, end);
+ return left << BigInt((end - middle) * 8) | right;
+ };
+ head = head << BigInt((view.byteLength - headLength) * 8) | decode(headLength, view.byteLength);
+ }
+ return head;
+};
+var errors = {
+ Error,
+ EvalError,
+ RangeError,
+ ReferenceError,
+ SyntaxError,
+ TypeError,
+ URIError,
+ AggregateError: typeof AggregateError === "function" ? AggregateError : null
+};
+currentExtensions[101] = () => {
+ let data = read();
+ if (!errors[data[0]]) {
+ let error = Error(data[1], { cause: data[2] });
+ error.name = data[0];
+ return error;
+ }
+ return errors[data[0]](data[1], { cause: data[2] });
+};
+currentExtensions[105] = (data) => {
+ if (currentUnpackr.structuredClone === false)
+ throw new Error("Structured clone extension is disabled");
+ let id = dataView.getUint32(position - 4);
+ if (!referenceMap)
+ referenceMap = new Map;
+ let token = src[position];
+ let target;
+ if (token >= 144 && token < 160 || token == 220 || token == 221)
+ target = [];
+ else if (token >= 128 && token < 144 || token == 222 || token == 223)
+ target = new Map;
+ else if ((token >= 199 && token <= 201 || token >= 212 && token <= 216) && src[position + 1] === 115)
+ target = new Set;
+ else
+ target = {};
+ let refEntry = { target };
+ referenceMap.set(id, refEntry);
+ let targetProperties = read();
+ if (!refEntry.used) {
+ return refEntry.target = targetProperties;
+ } else {
+ Object.assign(target, targetProperties);
+ }
+ if (target instanceof Map)
+ for (let [k2, v2] of targetProperties.entries())
+ target.set(k2, v2);
+ if (target instanceof Set)
+ for (let i2 of Array.from(targetProperties))
+ target.add(i2);
+ return target;
+};
+currentExtensions[112] = (data) => {
+ if (currentUnpackr.structuredClone === false)
+ throw new Error("Structured clone extension is disabled");
+ let id = dataView.getUint32(position - 4);
+ let refEntry = referenceMap.get(id);
+ refEntry.used = true;
+ return refEntry.target;
+};
+currentExtensions[115] = () => new Set(read());
+var typedArrays = ["Int8", "Uint8", "Uint8Clamped", "Int16", "Uint16", "Int32", "Uint32", "Float32", "Float64", "BigInt64", "BigUint64"].map((type) => type + "Array");
+var glbl = typeof globalThis === "object" ? globalThis : window;
+currentExtensions[116] = (data) => {
+ let typeCode = data[0];
+ let buffer = Uint8Array.prototype.slice.call(data, 1).buffer;
+ let typedArrayName = typedArrays[typeCode];
+ if (!typedArrayName) {
+ if (typeCode === 16)
+ return buffer;
+ if (typeCode === 17)
+ return new DataView(buffer);
+ throw new Error("Could not find typed array for code " + typeCode);
+ }
+ return new glbl[typedArrayName](buffer);
+};
+currentExtensions[120] = () => {
+ let data = read();
+ return new RegExp(data[0], data[1]);
+};
+var TEMP_BUNDLE = [];
+currentExtensions[98] = (data) => {
+ let dataSize = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
+ let dataPosition = position;
+ position += dataSize - data.length;
+ bundledStrings = TEMP_BUNDLE;
+ bundledStrings = [readOnlyJSString(), readOnlyJSString()];
+ bundledStrings.position0 = 0;
+ bundledStrings.position1 = 0;
+ bundledStrings.postBundlePosition = position;
+ position = dataPosition;
+ return read();
+};
+currentExtensions[255] = (data) => {
+ if (data.length == 4)
+ return new Date((data[0] * 16777216 + (data[1] << 16) + (data[2] << 8) + data[3]) * 1000);
+ else if (data.length == 8)
+ return new Date(((data[0] << 22) + (data[1] << 14) + (data[2] << 6) + (data[3] >> 2)) / 1e6 + ((data[3] & 3) * 4294967296 + data[4] * 16777216 + (data[5] << 16) + (data[6] << 8) + data[7]) * 1000);
+ else if (data.length == 12)
+ return new Date(((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1e6 + ((data[4] & 128 ? -281474976710656 : 0) + data[6] * 1099511627776 + data[7] * 4294967296 + data[8] * 16777216 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000);
+ else
+ return new Date("invalid");
+};
+function saveState(callback) {
+ if (onSaveState)
+ onSaveState();
+ let savedSrcEnd = srcEnd;
+ let savedPosition = position;
+ let savedStringPosition = stringPosition;
+ let savedSrcStringStart = srcStringStart;
+ let savedSrcStringEnd = srcStringEnd;
+ let savedSrcString = srcString;
+ let savedStrings = strings;
+ let savedReferenceMap = referenceMap;
+ let savedBundledStrings = bundledStrings;
+ let savedSrc = new Uint8Array(src.slice(0, srcEnd));
+ let savedStructures = currentStructures;
+ let savedStructuresContents = currentStructures.slice(0, currentStructures.length);
+ let savedPackr = currentUnpackr;
+ let savedSequentialMode = sequentialMode;
+ let value = callback();
+ srcEnd = savedSrcEnd;
+ position = savedPosition;
+ stringPosition = savedStringPosition;
+ srcStringStart = savedSrcStringStart;
+ srcStringEnd = savedSrcStringEnd;
+ srcString = savedSrcString;
+ strings = savedStrings;
+ referenceMap = savedReferenceMap;
+ bundledStrings = savedBundledStrings;
+ src = savedSrc;
+ sequentialMode = savedSequentialMode;
+ currentStructures = savedStructures;
+ currentStructures.splice(0, currentStructures.length, ...savedStructuresContents);
+ currentUnpackr = savedPackr;
+ dataView = new DataView(src.buffer, src.byteOffset, src.byteLength);
+ return value;
+}
+function clearSource() {
+ src = null;
+ referenceMap = null;
+ currentStructures = null;
+}
+var mult10 = new Array(147);
+for (let i2 = 0;i2 < 256; i2++) {
+ mult10[i2] = +("1e" + Math.floor(45.15 - i2 * 0.30103));
+}
+var defaultUnpackr = new Unpackr({ useRecords: false });
+var unpack = defaultUnpackr.unpack;
+var unpackMultiple = defaultUnpackr.unpackMultiple;
+var decode = defaultUnpackr.unpack;
+var f32Array = new Float32Array(1);
+var u8Array = new Uint8Array(f32Array.buffer, 0, 4);
+function setReadStruct(updatedReadStruct, loadedStructs, saveState2) {
+ readStruct = updatedReadStruct;
+ onLoadedStructures = loadedStructs;
+ onSaveState = saveState2;
+}
+// node_modules/.pnpm/msgpackr@1.11.5/node_modules/msgpackr/pack.js
+var textEncoder;
+try {
+ textEncoder = new TextEncoder;
+} catch (error) {}
+var extensions;
+var extensionClasses;
+var hasNodeBuffer = typeof Buffer !== "undefined";
+var ByteArrayAllocate = hasNodeBuffer ? function(length) {
+ return Buffer.allocUnsafeSlow(length);
+} : Uint8Array;
+var ByteArray = hasNodeBuffer ? Buffer : Uint8Array;
+var MAX_BUFFER_SIZE = hasNodeBuffer ? 4294967296 : 2144337920;
+var target;
+var keysTarget;
+var targetView;
+var position2 = 0;
+var safeEnd;
+var bundledStrings2 = null;
+var writeStructSlots;
+var MAX_BUNDLE_SIZE = 21760;
+var hasNonLatin = /[\u0080-\uFFFF]/;
+var RECORD_SYMBOL = Symbol("record-id");
+
+class Packr extends Unpackr {
+ constructor(options) {
+ super(options);
+ this.offset = 0;
+ let typeBuffer;
+ let start;
+ let hasSharedUpdate;
+ let structures;
+ let referenceMap2;
+ let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string2, position3) {
+ return target.utf8Write(string2, position3, target.byteLength - position3);
+ } : textEncoder && textEncoder.encodeInto ? function(string2, position3) {
+ return textEncoder.encodeInto(string2, target.subarray(position3)).written;
+ } : false;
+ let packr = this;
+ if (!options)
+ options = {};
+ let isSequential = options && options.sequential;
+ let hasSharedStructures = options.structures || options.saveStructures;
+ let maxSharedStructures = options.maxSharedStructures;
+ if (maxSharedStructures == null)
+ maxSharedStructures = hasSharedStructures ? 32 : 0;
+ if (maxSharedStructures > 8160)
+ throw new Error("Maximum maxSharedStructure is 8160");
+ if (options.structuredClone && options.moreTypes == undefined) {
+ this.moreTypes = true;
+ }
+ let maxOwnStructures = options.maxOwnStructures;
+ if (maxOwnStructures == null)
+ maxOwnStructures = hasSharedStructures ? 32 : 64;
+ if (!this.structures && options.useRecords != false)
+ this.structures = [];
+ let useTwoByteRecords = maxSharedStructures > 32 || maxOwnStructures + maxSharedStructures > 64;
+ let sharedLimitId = maxSharedStructures + 64;
+ let maxStructureId = maxSharedStructures + maxOwnStructures + 64;
+ if (maxStructureId > 8256) {
+ throw new Error("Maximum maxSharedStructure + maxOwnStructure is 8192");
+ }
+ let recordIdsToRemove = [];
+ let transitionsCount = 0;
+ let serializationsSinceTransitionRebuild = 0;
+ this.pack = this.encode = function(value, encodeOptions) {
+ if (!target) {
+ target = new ByteArrayAllocate(8192);
+ targetView = target.dataView || (target.dataView = new DataView(target.buffer, 0, 8192));
+ position2 = 0;
+ }
+ safeEnd = target.length - 10;
+ if (safeEnd - position2 < 2048) {
+ target = new ByteArrayAllocate(target.length);
+ targetView = target.dataView || (target.dataView = new DataView(target.buffer, 0, target.length));
+ safeEnd = target.length - 10;
+ position2 = 0;
+ } else
+ position2 = position2 + 7 & 2147483640;
+ start = position2;
+ if (encodeOptions & RESERVE_START_SPACE)
+ position2 += encodeOptions & 255;
+ referenceMap2 = packr.structuredClone ? new Map : null;
+ if (packr.bundleStrings && typeof value !== "string") {
+ bundledStrings2 = [];
+ bundledStrings2.size = Infinity;
+ } else
+ bundledStrings2 = null;
+ structures = packr.structures;
+ if (structures) {
+ if (structures.uninitialized)
+ structures = packr._mergeStructures(packr.getStructures());
+ let sharedLength = structures.sharedLength || 0;
+ if (sharedLength > maxSharedStructures) {
+ throw new Error("Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to " + structures.sharedLength);
+ }
+ if (!structures.transitions) {
+ structures.transitions = Object.create(null);
+ for (let i2 = 0;i2 < sharedLength; i2++) {
+ let keys = structures[i2];
+ if (!keys)
+ continue;
+ let nextTransition, transition = structures.transitions;
+ for (let j2 = 0, l2 = keys.length;j2 < l2; j2++) {
+ let key = keys[j2];
+ nextTransition = transition[key];
+ if (!nextTransition) {
+ nextTransition = transition[key] = Object.create(null);
+ }
+ transition = nextTransition;
+ }
+ transition[RECORD_SYMBOL] = i2 + 64;
+ }
+ this.lastNamedStructuresLength = sharedLength;
+ }
+ if (!isSequential) {
+ structures.nextId = sharedLength + 64;
+ }
+ }
+ if (hasSharedUpdate)
+ hasSharedUpdate = false;
+ let encodingError;
+ try {
+ if (packr.randomAccessStructure && value && value.constructor && value.constructor === Object)
+ writeStruct(value);
+ else
+ pack(value);
+ let lastBundle = bundledStrings2;
+ if (bundledStrings2)
+ writeBundles(start, pack, 0);
+ if (referenceMap2 && referenceMap2.idsToInsert) {
+ let idsToInsert = referenceMap2.idsToInsert.sort((a2, b2) => a2.offset > b2.offset ? 1 : -1);
+ let i2 = idsToInsert.length;
+ let incrementPosition = -1;
+ while (lastBundle && i2 > 0) {
+ let insertionPoint = idsToInsert[--i2].offset + start;
+ if (insertionPoint < lastBundle.stringsPosition + start && incrementPosition === -1)
+ incrementPosition = 0;
+ if (insertionPoint > lastBundle.position + start) {
+ if (incrementPosition >= 0)
+ incrementPosition += 6;
+ } else {
+ if (incrementPosition >= 0) {
+ targetView.setUint32(lastBundle.position + start, targetView.getUint32(lastBundle.position + start) + incrementPosition);
+ incrementPosition = -1;
+ }
+ lastBundle = lastBundle.previous;
+ i2++;
+ }
+ }
+ if (incrementPosition >= 0 && lastBundle) {
+ targetView.setUint32(lastBundle.position + start, targetView.getUint32(lastBundle.position + start) + incrementPosition);
+ }
+ position2 += idsToInsert.length * 6;
+ if (position2 > safeEnd)
+ makeRoom(position2);
+ packr.offset = position2;
+ let serialized = insertIds(target.subarray(start, position2), idsToInsert);
+ referenceMap2 = null;
+ return serialized;
+ }
+ packr.offset = position2;
+ if (encodeOptions & REUSE_BUFFER_MODE) {
+ target.start = start;
+ target.end = position2;
+ return target;
+ }
+ return target.subarray(start, position2);
+ } catch (error) {
+ encodingError = error;
+ throw error;
+ } finally {
+ if (structures) {
+ resetStructures();
+ if (hasSharedUpdate && packr.saveStructures) {
+ let sharedLength = structures.sharedLength || 0;
+ let returnBuffer = target.subarray(start, position2);
+ let newSharedData = prepareStructures(structures, packr);
+ if (!encodingError) {
+ if (packr.saveStructures(newSharedData, newSharedData.isCompatible) === false) {
+ return packr.pack(value, encodeOptions);
+ }
+ packr.lastNamedStructuresLength = sharedLength;
+ if (target.length > 1073741824)
+ target = null;
+ return returnBuffer;
+ }
+ }
+ }
+ if (target.length > 1073741824)
+ target = null;
+ if (encodeOptions & RESET_BUFFER_MODE)
+ position2 = start;
+ }
+ };
+ const resetStructures = () => {
+ if (serializationsSinceTransitionRebuild < 10)
+ serializationsSinceTransitionRebuild++;
+ let sharedLength = structures.sharedLength || 0;
+ if (structures.length > sharedLength && !isSequential)
+ structures.length = sharedLength;
+ if (transitionsCount > 1e4) {
+ structures.transitions = null;
+ serializationsSinceTransitionRebuild = 0;
+ transitionsCount = 0;
+ if (recordIdsToRemove.length > 0)
+ recordIdsToRemove = [];
+ } else if (recordIdsToRemove.length > 0 && !isSequential) {
+ for (let i2 = 0, l2 = recordIdsToRemove.length;i2 < l2; i2++) {
+ recordIdsToRemove[i2][RECORD_SYMBOL] = 0;
+ }
+ recordIdsToRemove = [];
+ }
+ };
+ const packArray = (value) => {
+ var length = value.length;
+ if (length < 16) {
+ target[position2++] = 144 | length;
+ } else if (length < 65536) {
+ target[position2++] = 220;
+ target[position2++] = length >> 8;
+ target[position2++] = length & 255;
+ } else {
+ target[position2++] = 221;
+ targetView.setUint32(position2, length);
+ position2 += 4;
+ }
+ for (let i2 = 0;i2 < length; i2++) {
+ pack(value[i2]);
+ }
+ };
+ const pack = (value) => {
+ if (position2 > safeEnd)
+ target = makeRoom(position2);
+ var type = typeof value;
+ var length;
+ if (type === "string") {
+ let strLength = value.length;
+ if (bundledStrings2 && strLength >= 4 && strLength < 4096) {
+ if ((bundledStrings2.size += strLength) > MAX_BUNDLE_SIZE) {
+ let extStart;
+ let maxBytes2 = (bundledStrings2[0] ? bundledStrings2[0].length * 3 + bundledStrings2[1].length : 0) + 10;
+ if (position2 + maxBytes2 > safeEnd)
+ target = makeRoom(position2 + maxBytes2);
+ let lastBundle;
+ if (bundledStrings2.position) {
+ lastBundle = bundledStrings2;
+ target[position2] = 200;
+ position2 += 3;
+ target[position2++] = 98;
+ extStart = position2 - start;
+ position2 += 4;
+ writeBundles(start, pack, 0);
+ targetView.setUint16(extStart + start - 3, position2 - start - extStart);
+ } else {
+ target[position2++] = 214;
+ target[position2++] = 98;
+ extStart = position2 - start;
+ position2 += 4;
+ }
+ bundledStrings2 = ["", ""];
+ bundledStrings2.previous = lastBundle;
+ bundledStrings2.size = 0;
+ bundledStrings2.position = extStart;
+ }
+ let twoByte = hasNonLatin.test(value);
+ bundledStrings2[twoByte ? 0 : 1] += value;
+ target[position2++] = 193;
+ pack(twoByte ? -strLength : strLength);
+ return;
+ }
+ let headerSize;
+ if (strLength < 32) {
+ headerSize = 1;
+ } else if (strLength < 256) {
+ headerSize = 2;
+ } else if (strLength < 65536) {
+ headerSize = 3;
+ } else {
+ headerSize = 5;
+ }
+ let maxBytes = strLength * 3;
+ if (position2 + maxBytes > safeEnd)
+ target = makeRoom(position2 + maxBytes);
+ if (strLength < 64 || !encodeUtf8) {
+ let i2, c1, c2, strPosition = position2 + headerSize;
+ for (i2 = 0;i2 < strLength; i2++) {
+ c1 = value.charCodeAt(i2);
+ if (c1 < 128) {
+ target[strPosition++] = c1;
+ } else if (c1 < 2048) {
+ target[strPosition++] = c1 >> 6 | 192;
+ target[strPosition++] = c1 & 63 | 128;
+ } else if ((c1 & 64512) === 55296 && ((c2 = value.charCodeAt(i2 + 1)) & 64512) === 56320) {
+ c1 = 65536 + ((c1 & 1023) << 10) + (c2 & 1023);
+ i2++;
+ target[strPosition++] = c1 >> 18 | 240;
+ target[strPosition++] = c1 >> 12 & 63 | 128;
+ target[strPosition++] = c1 >> 6 & 63 | 128;
+ target[strPosition++] = c1 & 63 | 128;
+ } else {
+ target[strPosition++] = c1 >> 12 | 224;
+ target[strPosition++] = c1 >> 6 & 63 | 128;
+ target[strPosition++] = c1 & 63 | 128;
+ }
+ }
+ length = strPosition - position2 - headerSize;
+ } else {
+ length = encodeUtf8(value, position2 + headerSize);
+ }
+ if (length < 32) {
+ target[position2++] = 160 | length;
+ } else if (length < 256) {
+ if (headerSize < 2) {
+ target.copyWithin(position2 + 2, position2 + 1, position2 + 1 + length);
+ }
+ target[position2++] = 217;
+ target[position2++] = length;
+ } else if (length < 65536) {
+ if (headerSize < 3) {
+ target.copyWithin(position2 + 3, position2 + 2, position2 + 2 + length);
+ }
+ target[position2++] = 218;
+ target[position2++] = length >> 8;
+ target[position2++] = length & 255;
+ } else {
+ if (headerSize < 5) {
+ target.copyWithin(position2 + 5, position2 + 3, position2 + 3 + length);
+ }
+ target[position2++] = 219;
+ targetView.setUint32(position2, length);
+ position2 += 4;
+ }
+ position2 += length;
+ } else if (type === "number") {
+ if (value >>> 0 === value) {
+ if (value < 32 || value < 128 && this.useRecords === false || value < 64 && !this.randomAccessStructure) {
+ target[position2++] = value;
+ } else if (value < 256) {
+ target[position2++] = 204;
+ target[position2++] = value;
+ } else if (value < 65536) {
+ target[position2++] = 205;
+ target[position2++] = value >> 8;
+ target[position2++] = value & 255;
+ } else {
+ target[position2++] = 206;
+ targetView.setUint32(position2, value);
+ position2 += 4;
+ }
+ } else if (value >> 0 === value) {
+ if (value >= -32) {
+ target[position2++] = 256 + value;
+ } else if (value >= -128) {
+ target[position2++] = 208;
+ target[position2++] = value + 256;
+ } else if (value >= -32768) {
+ target[position2++] = 209;
+ targetView.setInt16(position2, value);
+ position2 += 2;
+ } else {
+ target[position2++] = 210;
+ targetView.setInt32(position2, value);
+ position2 += 4;
+ }
+ } else {
+ let useFloat32;
+ if ((useFloat32 = this.useFloat32) > 0 && value < 4294967296 && value >= -2147483648) {
+ target[position2++] = 202;
+ targetView.setFloat32(position2, value);
+ let xShifted;
+ if (useFloat32 < 4 || (xShifted = value * mult10[(target[position2] & 127) << 1 | target[position2 + 1] >> 7]) >> 0 === xShifted) {
+ position2 += 4;
+ return;
+ } else
+ position2--;
+ }
+ target[position2++] = 203;
+ targetView.setFloat64(position2, value);
+ position2 += 8;
+ }
+ } else if (type === "object" || type === "function") {
+ if (!value)
+ target[position2++] = 192;
+ else {
+ if (referenceMap2) {
+ let referee = referenceMap2.get(value);
+ if (referee) {
+ if (!referee.id) {
+ let idsToInsert = referenceMap2.idsToInsert || (referenceMap2.idsToInsert = []);
+ referee.id = idsToInsert.push(referee);
+ }
+ target[position2++] = 214;
+ target[position2++] = 112;
+ targetView.setUint32(position2, referee.id);
+ position2 += 4;
+ return;
+ } else
+ referenceMap2.set(value, { offset: position2 - start });
+ }
+ let constructor = value.constructor;
+ if (constructor === Object) {
+ writeObject(value);
+ } else if (constructor === Array) {
+ packArray(value);
+ } else if (constructor === Map) {
+ if (this.mapAsEmptyObject)
+ target[position2++] = 128;
+ else {
+ length = value.size;
+ if (length < 16) {
+ target[position2++] = 128 | length;
+ } else if (length < 65536) {
+ target[position2++] = 222;
+ target[position2++] = length >> 8;
+ target[position2++] = length & 255;
+ } else {
+ target[position2++] = 223;
+ targetView.setUint32(position2, length);
+ position2 += 4;
+ }
+ for (let [key, entryValue] of value) {
+ pack(key);
+ pack(entryValue);
+ }
+ }
+ } else {
+ for (let i2 = 0, l2 = extensions.length;i2 < l2; i2++) {
+ let extensionClass = extensionClasses[i2];
+ if (value instanceof extensionClass) {
+ let extension = extensions[i2];
+ if (extension.write) {
+ if (extension.type) {
+ target[position2++] = 212;
+ target[position2++] = extension.type;
+ target[position2++] = 0;
+ }
+ let writeResult = extension.write.call(this, value);
+ if (writeResult === value) {
+ if (Array.isArray(value)) {
+ packArray(value);
+ } else {
+ writeObject(value);
+ }
+ } else {
+ pack(writeResult);
+ }
+ return;
+ }
+ let currentTarget = target;
+ let currentTargetView = targetView;
+ let currentPosition = position2;
+ target = null;
+ let result;
+ try {
+ result = extension.pack.call(this, value, (size) => {
+ target = currentTarget;
+ currentTarget = null;
+ position2 += size;
+ if (position2 > safeEnd)
+ makeRoom(position2);
+ return {
+ target,
+ targetView,
+ position: position2 - size
+ };
+ }, pack);
+ } finally {
+ if (currentTarget) {
+ target = currentTarget;
+ targetView = currentTargetView;
+ position2 = currentPosition;
+ safeEnd = target.length - 10;
+ }
+ }
+ if (result) {
+ if (result.length + position2 > safeEnd)
+ makeRoom(result.length + position2);
+ position2 = writeExtensionData(result, target, position2, extension.type);
+ }
+ return;
+ }
+ }
+ if (Array.isArray(value)) {
+ packArray(value);
+ } else {
+ if (value.toJSON) {
+ const json3 = value.toJSON();
+ if (json3 !== value)
+ return pack(json3);
+ }
+ if (type === "function")
+ return pack(this.writeFunction && this.writeFunction(value));
+ writeObject(value);
+ }
+ }
+ }
+ } else if (type === "boolean") {
+ target[position2++] = value ? 195 : 194;
+ } else if (type === "bigint") {
+ if (value < 9223372036854776000 && value >= -9223372036854776000) {
+ target[position2++] = 211;
+ targetView.setBigInt64(position2, value);
+ } else if (value < 18446744073709552000 && value > 0) {
+ target[position2++] = 207;
+ targetView.setBigUint64(position2, value);
+ } else {
+ if (this.largeBigIntToFloat) {
+ target[position2++] = 203;
+ targetView.setFloat64(position2, Number(value));
+ } else if (this.largeBigIntToString) {
+ return pack(value.toString());
+ } else if (this.useBigIntExtension || this.moreTypes) {
+ let empty = value < 0 ? BigInt(-1) : BigInt(0);
+ let array2;
+ if (value >> BigInt(65536) === empty) {
+ let mask = BigInt(18446744073709552000) - BigInt(1);
+ let chunks = [];
+ while (true) {
+ chunks.push(value & mask);
+ if (value >> BigInt(63) === empty)
+ break;
+ value >>= BigInt(64);
+ }
+ array2 = new Uint8Array(new BigUint64Array(chunks).buffer);
+ array2.reverse();
+ } else {
+ let invert = value < 0;
+ let string2 = (invert ? ~value : value).toString(16);
+ if (string2.length % 2) {
+ string2 = "0" + string2;
+ } else if (parseInt(string2.charAt(0), 16) >= 8) {
+ string2 = "00" + string2;
+ }
+ if (hasNodeBuffer) {
+ array2 = Buffer.from(string2, "hex");
+ } else {
+ array2 = new Uint8Array(string2.length / 2);
+ for (let i2 = 0;i2 < array2.length; i2++) {
+ array2[i2] = parseInt(string2.slice(i2 * 2, i2 * 2 + 2), 16);
+ }
+ }
+ if (invert) {
+ for (let i2 = 0;i2 < array2.length; i2++)
+ array2[i2] = ~array2[i2];
+ }
+ }
+ if (array2.length + position2 > safeEnd)
+ makeRoom(array2.length + position2);
+ position2 = writeExtensionData(array2, target, position2, 66);
+ return;
+ } else {
+ throw new RangeError(value + " was too large to fit in MessagePack 64-bit integer format, use" + " useBigIntExtension, or set largeBigIntToFloat to convert to float-64, or set" + " largeBigIntToString to convert to string");
+ }
+ }
+ position2 += 8;
+ } else if (type === "undefined") {
+ if (this.encodeUndefinedAsNil)
+ target[position2++] = 192;
+ else {
+ target[position2++] = 212;
+ target[position2++] = 0;
+ target[position2++] = 0;
+ }
+ } else {
+ throw new Error("Unknown type: " + type);
+ }
+ };
+ const writePlainObject = this.variableMapSize || this.coercibleKeyAsNumber || this.skipValues ? (object2) => {
+ let keys;
+ if (this.skipValues) {
+ keys = [];
+ for (let key2 in object2) {
+ if ((typeof object2.hasOwnProperty !== "function" || object2.hasOwnProperty(key2)) && !this.skipValues.includes(object2[key2]))
+ keys.push(key2);
+ }
+ } else {
+ keys = Object.keys(object2);
+ }
+ let length = keys.length;
+ if (length < 16) {
+ target[position2++] = 128 | length;
+ } else if (length < 65536) {
+ target[position2++] = 222;
+ target[position2++] = length >> 8;
+ target[position2++] = length & 255;
+ } else {
+ target[position2++] = 223;
+ targetView.setUint32(position2, length);
+ position2 += 4;
+ }
+ let key;
+ if (this.coercibleKeyAsNumber) {
+ for (let i2 = 0;i2 < length; i2++) {
+ key = keys[i2];
+ let num = Number(key);
+ pack(isNaN(num) ? key : num);
+ pack(object2[key]);
+ }
+ } else {
+ for (let i2 = 0;i2 < length; i2++) {
+ pack(key = keys[i2]);
+ pack(object2[key]);
+ }
+ }
+ } : (object2) => {
+ target[position2++] = 222;
+ let objectOffset = position2 - start;
+ position2 += 2;
+ let size = 0;
+ for (let key in object2) {
+ if (typeof object2.hasOwnProperty !== "function" || object2.hasOwnProperty(key)) {
+ pack(key);
+ pack(object2[key]);
+ size++;
+ }
+ }
+ if (size > 65535) {
+ throw new Error("Object is too large to serialize with fast 16-bit map size," + ' use the "variableMapSize" option to serialize this object');
+ }
+ target[objectOffset++ + start] = size >> 8;
+ target[objectOffset + start] = size & 255;
+ };
+ const writeRecord = this.useRecords === false ? writePlainObject : options.progressiveRecords && !useTwoByteRecords ? (object2) => {
+ let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
+ let objectOffset = position2++ - start;
+ let wroteKeys;
+ for (let key in object2) {
+ if (typeof object2.hasOwnProperty !== "function" || object2.hasOwnProperty(key)) {
+ nextTransition = transition[key];
+ if (nextTransition)
+ transition = nextTransition;
+ else {
+ let keys = Object.keys(object2);
+ let lastTransition = transition;
+ transition = structures.transitions;
+ let newTransitions = 0;
+ for (let i2 = 0, l2 = keys.length;i2 < l2; i2++) {
+ let key2 = keys[i2];
+ nextTransition = transition[key2];
+ if (!nextTransition) {
+ nextTransition = transition[key2] = Object.create(null);
+ newTransitions++;
+ }
+ transition = nextTransition;
+ }
+ if (objectOffset + start + 1 == position2) {
+ position2--;
+ newRecord(transition, keys, newTransitions);
+ } else
+ insertNewRecord(transition, keys, objectOffset, newTransitions);
+ wroteKeys = true;
+ transition = lastTransition[key];
+ }
+ pack(object2[key]);
+ }
+ }
+ if (!wroteKeys) {
+ let recordId = transition[RECORD_SYMBOL];
+ if (recordId)
+ target[objectOffset + start] = recordId;
+ else
+ insertNewRecord(transition, Object.keys(object2), objectOffset, 0);
+ }
+ } : (object2) => {
+ let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
+ let newTransitions = 0;
+ for (let key in object2)
+ if (typeof object2.hasOwnProperty !== "function" || object2.hasOwnProperty(key)) {
+ nextTransition = transition[key];
+ if (!nextTransition) {
+ nextTransition = transition[key] = Object.create(null);
+ newTransitions++;
+ }
+ transition = nextTransition;
+ }
+ let recordId = transition[RECORD_SYMBOL];
+ if (recordId) {
+ if (recordId >= 96 && useTwoByteRecords) {
+ target[position2++] = ((recordId -= 96) & 31) + 96;
+ target[position2++] = recordId >> 5;
+ } else
+ target[position2++] = recordId;
+ } else {
+ newRecord(transition, transition.__keys__ || Object.keys(object2), newTransitions);
+ }
+ for (let key in object2)
+ if (typeof object2.hasOwnProperty !== "function" || object2.hasOwnProperty(key)) {
+ pack(object2[key]);
+ }
+ };
+ const checkUseRecords = typeof this.useRecords == "function" && this.useRecords;
+ const writeObject = checkUseRecords ? (object2) => {
+ checkUseRecords(object2) ? writeRecord(object2) : writePlainObject(object2);
+ } : writeRecord;
+ const makeRoom = (end) => {
+ let newSize;
+ if (end > 16777216) {
+ if (end - start > MAX_BUFFER_SIZE)
+ throw new Error("Packed buffer would be larger than maximum buffer size");
+ newSize = Math.min(MAX_BUFFER_SIZE, Math.round(Math.max((end - start) * (end > 67108864 ? 1.25 : 2), 4194304) / 4096) * 4096);
+ } else
+ newSize = (Math.max(end - start << 2, target.length - 1) >> 12) + 1 << 12;
+ let newBuffer = new ByteArrayAllocate(newSize);
+ targetView = newBuffer.dataView || (newBuffer.dataView = new DataView(newBuffer.buffer, 0, newSize));
+ end = Math.min(end, target.length);
+ if (target.copy)
+ target.copy(newBuffer, 0, start, end);
+ else
+ newBuffer.set(target.slice(start, end));
+ position2 -= start;
+ start = 0;
+ safeEnd = newBuffer.length - 10;
+ return target = newBuffer;
+ };
+ const newRecord = (transition, keys, newTransitions) => {
+ let recordId = structures.nextId;
+ if (!recordId)
+ recordId = 64;
+ if (recordId < sharedLimitId && this.shouldShareStructure && !this.shouldShareStructure(keys)) {
+ recordId = structures.nextOwnId;
+ if (!(recordId < maxStructureId))
+ recordId = sharedLimitId;
+ structures.nextOwnId = recordId + 1;
+ } else {
+ if (recordId >= maxStructureId)
+ recordId = sharedLimitId;
+ structures.nextId = recordId + 1;
+ }
+ let highByte = keys.highByte = recordId >= 96 && useTwoByteRecords ? recordId - 96 >> 5 : -1;
+ transition[RECORD_SYMBOL] = recordId;
+ transition.__keys__ = keys;
+ structures[recordId - 64] = keys;
+ if (recordId < sharedLimitId) {
+ keys.isShared = true;
+ structures.sharedLength = recordId - 63;
+ hasSharedUpdate = true;
+ if (highByte >= 0) {
+ target[position2++] = (recordId & 31) + 96;
+ target[position2++] = highByte;
+ } else {
+ target[position2++] = recordId;
+ }
+ } else {
+ if (highByte >= 0) {
+ target[position2++] = 213;
+ target[position2++] = 114;
+ target[position2++] = (recordId & 31) + 96;
+ target[position2++] = highByte;
+ } else {
+ target[position2++] = 212;
+ target[position2++] = 114;
+ target[position2++] = recordId;
+ }
+ if (newTransitions)
+ transitionsCount += serializationsSinceTransitionRebuild * newTransitions;
+ if (recordIdsToRemove.length >= maxOwnStructures)
+ recordIdsToRemove.shift()[RECORD_SYMBOL] = 0;
+ recordIdsToRemove.push(transition);
+ pack(keys);
+ }
+ };
+ const insertNewRecord = (transition, keys, insertionOffset, newTransitions) => {
+ let mainTarget = target;
+ let mainPosition = position2;
+ let mainSafeEnd = safeEnd;
+ let mainStart = start;
+ target = keysTarget;
+ position2 = 0;
+ start = 0;
+ if (!target)
+ keysTarget = target = new ByteArrayAllocate(8192);
+ safeEnd = target.length - 10;
+ newRecord(transition, keys, newTransitions);
+ keysTarget = target;
+ let keysPosition = position2;
+ target = mainTarget;
+ position2 = mainPosition;
+ safeEnd = mainSafeEnd;
+ start = mainStart;
+ if (keysPosition > 1) {
+ let newEnd = position2 + keysPosition - 1;
+ if (newEnd > safeEnd)
+ makeRoom(newEnd);
+ let insertionPosition = insertionOffset + start;
+ target.copyWithin(insertionPosition + keysPosition, insertionPosition + 1, position2);
+ target.set(keysTarget.slice(0, keysPosition), insertionPosition);
+ position2 = newEnd;
+ } else {
+ target[insertionOffset + start] = keysTarget[0];
+ }
+ };
+ const writeStruct = (object2) => {
+ let newPosition = writeStructSlots(object2, target, start, position2, structures, makeRoom, (value, newPosition2, notifySharedUpdate) => {
+ if (notifySharedUpdate)
+ return hasSharedUpdate = true;
+ position2 = newPosition2;
+ let startTarget = target;
+ pack(value);
+ resetStructures();
+ if (startTarget !== target) {
+ return { position: position2, targetView, target };
+ }
+ return position2;
+ }, this);
+ if (newPosition === 0)
+ return writeObject(object2);
+ position2 = newPosition;
+ };
+ }
+ useBuffer(buffer) {
+ target = buffer;
+ target.dataView || (target.dataView = new DataView(target.buffer, target.byteOffset, target.byteLength));
+ targetView = target.dataView;
+ position2 = 0;
+ }
+ set position(value) {
+ position2 = value;
+ }
+ get position() {
+ return position2;
+ }
+ clearSharedData() {
+ if (this.structures)
+ this.structures = [];
+ if (this.typedStructs)
+ this.typedStructs = [];
+ }
+}
+extensionClasses = [Date, Set, Error, RegExp, ArrayBuffer, Object.getPrototypeOf(Uint8Array.prototype).constructor, DataView, C1Type];
+extensions = [{
+ pack(date4, allocateForWrite, pack) {
+ let seconds = date4.getTime() / 1000;
+ if ((this.useTimestamp32 || date4.getMilliseconds() === 0) && seconds >= 0 && seconds < 4294967296) {
+ let { target: target2, targetView: targetView2, position: position3 } = allocateForWrite(6);
+ target2[position3++] = 214;
+ target2[position3++] = 255;
+ targetView2.setUint32(position3, seconds);
+ } else if (seconds > 0 && seconds < 4294967296) {
+ let { target: target2, targetView: targetView2, position: position3 } = allocateForWrite(10);
+ target2[position3++] = 215;
+ target2[position3++] = 255;
+ targetView2.setUint32(position3, date4.getMilliseconds() * 4000000 + (seconds / 1000 / 4294967296 >> 0));
+ targetView2.setUint32(position3 + 4, seconds);
+ } else if (isNaN(seconds)) {
+ if (this.onInvalidDate) {
+ allocateForWrite(0);
+ return pack(this.onInvalidDate());
+ }
+ let { target: target2, targetView: targetView2, position: position3 } = allocateForWrite(3);
+ target2[position3++] = 212;
+ target2[position3++] = 255;
+ target2[position3++] = 255;
+ } else {
+ let { target: target2, targetView: targetView2, position: position3 } = allocateForWrite(15);
+ target2[position3++] = 199;
+ target2[position3++] = 12;
+ target2[position3++] = 255;
+ targetView2.setUint32(position3, date4.getMilliseconds() * 1e6);
+ targetView2.setBigInt64(position3 + 4, BigInt(Math.floor(seconds)));
+ }
+ }
+}, {
+ pack(set, allocateForWrite, pack) {
+ if (this.setAsEmptyObject) {
+ allocateForWrite(0);
+ return pack({});
+ }
+ let array2 = Array.from(set);
+ let { target: target2, position: position3 } = allocateForWrite(this.moreTypes ? 3 : 0);
+ if (this.moreTypes) {
+ target2[position3++] = 212;
+ target2[position3++] = 115;
+ target2[position3++] = 0;
+ }
+ pack(array2);
+ }
+}, {
+ pack(error, allocateForWrite, pack) {
+ let { target: target2, position: position3 } = allocateForWrite(this.moreTypes ? 3 : 0);
+ if (this.moreTypes) {
+ target2[position3++] = 212;
+ target2[position3++] = 101;
+ target2[position3++] = 0;
+ }
+ pack([error.name, error.message, error.cause]);
+ }
+}, {
+ pack(regex, allocateForWrite, pack) {
+ let { target: target2, position: position3 } = allocateForWrite(this.moreTypes ? 3 : 0);
+ if (this.moreTypes) {
+ target2[position3++] = 212;
+ target2[position3++] = 120;
+ target2[position3++] = 0;
+ }
+ pack([regex.source, regex.flags]);
+ }
+}, {
+ pack(arrayBuffer, allocateForWrite) {
+ if (this.moreTypes)
+ writeExtBuffer(arrayBuffer, 16, allocateForWrite);
+ else
+ writeBuffer(hasNodeBuffer ? Buffer.from(arrayBuffer) : new Uint8Array(arrayBuffer), allocateForWrite);
+ }
+}, {
+ pack(typedArray, allocateForWrite) {
+ let constructor = typedArray.constructor;
+ if (constructor !== ByteArray && this.moreTypes)
+ writeExtBuffer(typedArray, typedArrays.indexOf(constructor.name), allocateForWrite);
+ else
+ writeBuffer(typedArray, allocateForWrite);
+ }
+}, {
+ pack(arrayBuffer, allocateForWrite) {
+ if (this.moreTypes)
+ writeExtBuffer(arrayBuffer, 17, allocateForWrite);
+ else
+ writeBuffer(hasNodeBuffer ? Buffer.from(arrayBuffer) : new Uint8Array(arrayBuffer), allocateForWrite);
+ }
+}, {
+ pack(c1, allocateForWrite) {
+ let { target: target2, position: position3 } = allocateForWrite(1);
+ target2[position3] = 193;
+ }
+}];
+function writeExtBuffer(typedArray, type, allocateForWrite, encode) {
+ let length = typedArray.byteLength;
+ if (length + 1 < 256) {
+ var { target: target2, position: position3 } = allocateForWrite(4 + length);
+ target2[position3++] = 199;
+ target2[position3++] = length + 1;
+ } else if (length + 1 < 65536) {
+ var { target: target2, position: position3 } = allocateForWrite(5 + length);
+ target2[position3++] = 200;
+ target2[position3++] = length + 1 >> 8;
+ target2[position3++] = length + 1 & 255;
+ } else {
+ var { target: target2, position: position3, targetView: targetView2 } = allocateForWrite(7 + length);
+ target2[position3++] = 201;
+ targetView2.setUint32(position3, length + 1);
+ position3 += 4;
+ }
+ target2[position3++] = 116;
+ target2[position3++] = type;
+ if (!typedArray.buffer)
+ typedArray = new Uint8Array(typedArray);
+ target2.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength), position3);
+}
+function writeBuffer(buffer, allocateForWrite) {
+ let length = buffer.byteLength;
+ var target2, position3;
+ if (length < 256) {
+ var { target: target2, position: position3 } = allocateForWrite(length + 2);
+ target2[position3++] = 196;
+ target2[position3++] = length;
+ } else if (length < 65536) {
+ var { target: target2, position: position3 } = allocateForWrite(length + 3);
+ target2[position3++] = 197;
+ target2[position3++] = length >> 8;
+ target2[position3++] = length & 255;
+ } else {
+ var { target: target2, position: position3, targetView: targetView2 } = allocateForWrite(length + 5);
+ target2[position3++] = 198;
+ targetView2.setUint32(position3, length);
+ position3 += 4;
+ }
+ target2.set(buffer, position3);
+}
+function writeExtensionData(result, target2, position3, type) {
+ let length = result.length;
+ switch (length) {
+ case 1:
+ target2[position3++] = 212;
+ break;
+ case 2:
+ target2[position3++] = 213;
+ break;
+ case 4:
+ target2[position3++] = 214;
+ break;
+ case 8:
+ target2[position3++] = 215;
+ break;
+ case 16:
+ target2[position3++] = 216;
+ break;
+ default:
+ if (length < 256) {
+ target2[position3++] = 199;
+ target2[position3++] = length;
+ } else if (length < 65536) {
+ target2[position3++] = 200;
+ target2[position3++] = length >> 8;
+ target2[position3++] = length & 255;
+ } else {
+ target2[position3++] = 201;
+ target2[position3++] = length >> 24;
+ target2[position3++] = length >> 16 & 255;
+ target2[position3++] = length >> 8 & 255;
+ target2[position3++] = length & 255;
+ }
+ }
+ target2[position3++] = type;
+ target2.set(result, position3);
+ position3 += length;
+ return position3;
+}
+function insertIds(serialized, idsToInsert) {
+ let nextId;
+ let distanceToMove = idsToInsert.length * 6;
+ let lastEnd = serialized.length - distanceToMove;
+ while (nextId = idsToInsert.pop()) {
+ let offset = nextId.offset;
+ let id = nextId.id;
+ serialized.copyWithin(offset + distanceToMove, offset, lastEnd);
+ distanceToMove -= 6;
+ let position3 = offset + distanceToMove;
+ serialized[position3++] = 214;
+ serialized[position3++] = 105;
+ serialized[position3++] = id >> 24;
+ serialized[position3++] = id >> 16 & 255;
+ serialized[position3++] = id >> 8 & 255;
+ serialized[position3++] = id & 255;
+ lastEnd = offset;
+ }
+ return serialized;
+}
+function writeBundles(start, pack, incrementPosition) {
+ if (bundledStrings2.length > 0) {
+ targetView.setUint32(bundledStrings2.position + start, position2 + incrementPosition - bundledStrings2.position - start);
+ bundledStrings2.stringsPosition = position2 - start;
+ let writeStrings = bundledStrings2;
+ bundledStrings2 = null;
+ pack(writeStrings[0]);
+ pack(writeStrings[1]);
+ }
+}
+function prepareStructures(structures, packr) {
+ structures.isCompatible = (existingStructures) => {
+ let compatible = !existingStructures || (packr.lastNamedStructuresLength || 0) === existingStructures.length;
+ if (!compatible)
+ packr._mergeStructures(existingStructures);
+ return compatible;
+ };
+ return structures;
+}
+function setWriteStructSlots(writeSlots, makeStructures) {
+ writeStructSlots = writeSlots;
+ prepareStructures = makeStructures;
+}
+var defaultPackr = new Packr({ useRecords: false });
+var pack = defaultPackr.pack;
+var encode = defaultPackr.pack;
+var REUSE_BUFFER_MODE = 512;
+var RESET_BUFFER_MODE = 1024;
+var RESERVE_START_SPACE = 2048;
+// node_modules/.pnpm/msgpackr@1.11.5/node_modules/msgpackr/struct.js
+var ASCII = 3;
+var NUMBER = 0;
+var UTF8 = 2;
+var OBJECT_DATA = 1;
+var DATE = 16;
+var TYPE_NAMES = ["num", "object", "string", "ascii"];
+TYPE_NAMES[DATE] = "date";
+var float32Headers = [false, true, true, false, false, true, true, false];
+var evalSupported;
+try {
+ new Function("");
+ evalSupported = true;
+} catch (error) {}
+var updatedPosition;
+var hasNodeBuffer2 = typeof Buffer !== "undefined";
+var textEncoder2;
+var currentSource;
+try {
+ textEncoder2 = new TextEncoder;
+} catch (error) {}
+var encodeUtf8 = hasNodeBuffer2 ? function(target2, string2, position3) {
+ return target2.utf8Write(string2, position3, target2.byteLength - position3);
+} : textEncoder2 && textEncoder2.encodeInto ? function(target2, string2, position3) {
+ return textEncoder2.encodeInto(string2, target2.subarray(position3)).written;
+} : false;
+var TYPE = Symbol("type");
+var PARENT = Symbol("parent");
+setWriteStructSlots(writeStruct, prepareStructures2);
+function writeStruct(object2, target2, encodingStart, position3, structures, makeRoom, pack2, packr) {
+ let typedStructs = packr.typedStructs || (packr.typedStructs = []);
+ let targetView2 = target2.dataView;
+ let refsStartPosition = (typedStructs.lastStringStart || 100) + position3;
+ let safeEnd2 = target2.length - 10;
+ let start = position3;
+ if (position3 > safeEnd2) {
+ target2 = makeRoom(position3);
+ targetView2 = target2.dataView;
+ position3 -= encodingStart;
+ start -= encodingStart;
+ refsStartPosition -= encodingStart;
+ encodingStart = 0;
+ safeEnd2 = target2.length - 10;
+ }
+ let refOffset, refPosition = refsStartPosition;
+ let transition = typedStructs.transitions || (typedStructs.transitions = Object.create(null));
+ let nextId = typedStructs.nextId || typedStructs.length;
+ let headerSize = nextId < 15 ? 1 : nextId < 240 ? 2 : nextId < 61440 ? 3 : nextId < 15728640 ? 4 : 0;
+ if (headerSize === 0)
+ return 0;
+ position3 += headerSize;
+ let queuedReferences = [];
+ let usedAscii0;
+ let keyIndex = 0;
+ for (let key in object2) {
+ let value = object2[key];
+ let nextTransition = transition[key];
+ if (!nextTransition) {
+ transition[key] = nextTransition = {
+ key,
+ parent: transition,
+ enumerationOffset: 0,
+ ascii0: null,
+ ascii8: null,
+ num8: null,
+ string16: null,
+ object16: null,
+ num32: null,
+ float64: null,
+ date64: null
+ };
+ }
+ if (position3 > safeEnd2) {
+ target2 = makeRoom(position3);
+ targetView2 = target2.dataView;
+ position3 -= encodingStart;
+ start -= encodingStart;
+ refsStartPosition -= encodingStart;
+ refPosition -= encodingStart;
+ encodingStart = 0;
+ safeEnd2 = target2.length - 10;
+ }
+ switch (typeof value) {
+ case "number":
+ let number2 = value;
+ if (nextId < 200 || !nextTransition.num64) {
+ if (number2 >> 0 === number2 && number2 < 536870912 && number2 > -520093696) {
+ if (number2 < 246 && number2 >= 0 && (nextTransition.num8 && !(nextId > 200 && nextTransition.num32) || number2 < 32 && !nextTransition.num32)) {
+ transition = nextTransition.num8 || createTypeTransition(nextTransition, NUMBER, 1);
+ target2[position3++] = number2;
+ } else {
+ transition = nextTransition.num32 || createTypeTransition(nextTransition, NUMBER, 4);
+ targetView2.setUint32(position3, number2, true);
+ position3 += 4;
+ }
+ break;
+ } else if (number2 < 4294967296 && number2 >= -2147483648) {
+ targetView2.setFloat32(position3, number2, true);
+ if (float32Headers[target2[position3 + 3] >>> 5]) {
+ let xShifted;
+ if ((xShifted = number2 * mult10[(target2[position3 + 3] & 127) << 1 | target2[position3 + 2] >> 7]) >> 0 === xShifted) {
+ transition = nextTransition.num32 || createTypeTransition(nextTransition, NUMBER, 4);
+ position3 += 4;
+ break;
+ }
+ }
+ }
+ }
+ transition = nextTransition.num64 || createTypeTransition(nextTransition, NUMBER, 8);
+ targetView2.setFloat64(position3, number2, true);
+ position3 += 8;
+ break;
+ case "string":
+ let strLength = value.length;
+ refOffset = refPosition - refsStartPosition;
+ if ((strLength << 2) + refPosition > safeEnd2) {
+ target2 = makeRoom((strLength << 2) + refPosition);
+ targetView2 = target2.dataView;
+ position3 -= encodingStart;
+ start -= encodingStart;
+ refsStartPosition -= encodingStart;
+ refPosition -= encodingStart;
+ encodingStart = 0;
+ safeEnd2 = target2.length - 10;
+ }
+ if (strLength > 65280 + refOffset >> 2) {
+ queuedReferences.push(key, value, position3 - start);
+ break;
+ }
+ let isNotAscii;
+ let strStart = refPosition;
+ if (strLength < 64) {
+ let i2, c1, c2;
+ for (i2 = 0;i2 < strLength; i2++) {
+ c1 = value.charCodeAt(i2);
+ if (c1 < 128) {
+ target2[refPosition++] = c1;
+ } else if (c1 < 2048) {
+ isNotAscii = true;
+ target2[refPosition++] = c1 >> 6 | 192;
+ target2[refPosition++] = c1 & 63 | 128;
+ } else if ((c1 & 64512) === 55296 && ((c2 = value.charCodeAt(i2 + 1)) & 64512) === 56320) {
+ isNotAscii = true;
+ c1 = 65536 + ((c1 & 1023) << 10) + (c2 & 1023);
+ i2++;
+ target2[refPosition++] = c1 >> 18 | 240;
+ target2[refPosition++] = c1 >> 12 & 63 | 128;
+ target2[refPosition++] = c1 >> 6 & 63 | 128;
+ target2[refPosition++] = c1 & 63 | 128;
+ } else {
+ isNotAscii = true;
+ target2[refPosition++] = c1 >> 12 | 224;
+ target2[refPosition++] = c1 >> 6 & 63 | 128;
+ target2[refPosition++] = c1 & 63 | 128;
+ }
+ }
+ } else {
+ refPosition += encodeUtf8(target2, value, refPosition);
+ isNotAscii = refPosition - strStart > strLength;
+ }
+ if (refOffset < 160 || refOffset < 246 && (nextTransition.ascii8 || nextTransition.string8)) {
+ if (isNotAscii) {
+ if (!(transition = nextTransition.string8)) {
+ if (typedStructs.length > 10 && (transition = nextTransition.ascii8)) {
+ transition.__type = UTF8;
+ nextTransition.ascii8 = null;
+ nextTransition.string8 = transition;
+ pack2(null, 0, true);
+ } else {
+ transition = createTypeTransition(nextTransition, UTF8, 1);
+ }
+ }
+ } else if (refOffset === 0 && !usedAscii0) {
+ usedAscii0 = true;
+ transition = nextTransition.ascii0 || createTypeTransition(nextTransition, ASCII, 0);
+ break;
+ } else if (!(transition = nextTransition.ascii8) && !(typedStructs.length > 10 && (transition = nextTransition.string8)))
+ transition = createTypeTransition(nextTransition, ASCII, 1);
+ target2[position3++] = refOffset;
+ } else {
+ transition = nextTransition.string16 || createTypeTransition(nextTransition, UTF8, 2);
+ targetView2.setUint16(position3, refOffset, true);
+ position3 += 2;
+ }
+ break;
+ case "object":
+ if (value) {
+ if (value.constructor === Date) {
+ transition = nextTransition.date64 || createTypeTransition(nextTransition, DATE, 8);
+ targetView2.setFloat64(position3, value.getTime(), true);
+ position3 += 8;
+ } else {
+ queuedReferences.push(key, value, keyIndex);
+ }
+ break;
+ } else {
+ nextTransition = anyType(nextTransition, position3, targetView2, -10);
+ if (nextTransition) {
+ transition = nextTransition;
+ position3 = updatedPosition;
+ } else
+ queuedReferences.push(key, value, keyIndex);
+ }
+ break;
+ case "boolean":
+ transition = nextTransition.num8 || nextTransition.ascii8 || createTypeTransition(nextTransition, NUMBER, 1);
+ target2[position3++] = value ? 249 : 248;
+ break;
+ case "undefined":
+ nextTransition = anyType(nextTransition, position3, targetView2, -9);
+ if (nextTransition) {
+ transition = nextTransition;
+ position3 = updatedPosition;
+ } else
+ queuedReferences.push(key, value, keyIndex);
+ break;
+ default:
+ queuedReferences.push(key, value, keyIndex);
+ }
+ keyIndex++;
+ }
+ for (let i2 = 0, l2 = queuedReferences.length;i2 < l2; ) {
+ let key = queuedReferences[i2++];
+ let value = queuedReferences[i2++];
+ let propertyIndex = queuedReferences[i2++];
+ let nextTransition = transition[key];
+ if (!nextTransition) {
+ transition[key] = nextTransition = {
+ key,
+ parent: transition,
+ enumerationOffset: propertyIndex - keyIndex,
+ ascii0: null,
+ ascii8: null,
+ num8: null,
+ string16: null,
+ object16: null,
+ num32: null,
+ float64: null
+ };
+ }
+ let newPosition;
+ if (value) {
+ let size;
+ refOffset = refPosition - refsStartPosition;
+ if (refOffset < 65280) {
+ transition = nextTransition.object16;
+ if (transition)
+ size = 2;
+ else if (transition = nextTransition.object32)
+ size = 4;
+ else {
+ transition = createTypeTransition(nextTransition, OBJECT_DATA, 2);
+ size = 2;
+ }
+ } else {
+ transition = nextTransition.object32 || createTypeTransition(nextTransition, OBJECT_DATA, 4);
+ size = 4;
+ }
+ newPosition = pack2(value, refPosition);
+ if (typeof newPosition === "object") {
+ refPosition = newPosition.position;
+ targetView2 = newPosition.targetView;
+ target2 = newPosition.target;
+ refsStartPosition -= encodingStart;
+ position3 -= encodingStart;
+ start -= encodingStart;
+ encodingStart = 0;
+ } else
+ refPosition = newPosition;
+ if (size === 2) {
+ targetView2.setUint16(position3, refOffset, true);
+ position3 += 2;
+ } else {
+ targetView2.setUint32(position3, refOffset, true);
+ position3 += 4;
+ }
+ } else {
+ transition = nextTransition.object16 || createTypeTransition(nextTransition, OBJECT_DATA, 2);
+ targetView2.setInt16(position3, value === null ? -10 : -9, true);
+ position3 += 2;
+ }
+ keyIndex++;
+ }
+ let recordId = transition[RECORD_SYMBOL];
+ if (recordId == null) {
+ recordId = packr.typedStructs.length;
+ let structure = [];
+ let nextTransition = transition;
+ let key, type;
+ while ((type = nextTransition.__type) !== undefined) {
+ let size = nextTransition.__size;
+ nextTransition = nextTransition.__parent;
+ key = nextTransition.key;
+ let property = [type, size, key];
+ if (nextTransition.enumerationOffset)
+ property.push(nextTransition.enumerationOffset);
+ structure.push(property);
+ nextTransition = nextTransition.parent;
+ }
+ structure.reverse();
+ transition[RECORD_SYMBOL] = recordId;
+ packr.typedStructs[recordId] = structure;
+ pack2(null, 0, true);
+ }
+ switch (headerSize) {
+ case 1:
+ if (recordId >= 16)
+ return 0;
+ target2[start] = recordId + 32;
+ break;
+ case 2:
+ if (recordId >= 256)
+ return 0;
+ target2[start] = 56;
+ target2[start + 1] = recordId;
+ break;
+ case 3:
+ if (recordId >= 65536)
+ return 0;
+ target2[start] = 57;
+ targetView2.setUint16(start + 1, recordId, true);
+ break;
+ case 4:
+ if (recordId >= 16777216)
+ return 0;
+ targetView2.setUint32(start, (recordId << 8) + 58, true);
+ break;
+ }
+ if (position3 < refsStartPosition) {
+ if (refsStartPosition === refPosition)
+ return position3;
+ target2.copyWithin(position3, refsStartPosition, refPosition);
+ refPosition += position3 - refsStartPosition;
+ typedStructs.lastStringStart = position3 - start;
+ } else if (position3 > refsStartPosition) {
+ if (refsStartPosition === refPosition)
+ return position3;
+ typedStructs.lastStringStart = position3 - start;
+ return writeStruct(object2, target2, encodingStart, start, structures, makeRoom, pack2, packr);
+ }
+ return refPosition;
+}
+function anyType(transition, position3, targetView2, value) {
+ let nextTransition;
+ if (nextTransition = transition.ascii8 || transition.num8) {
+ targetView2.setInt8(position3, value, true);
+ updatedPosition = position3 + 1;
+ return nextTransition;
+ }
+ if (nextTransition = transition.string16 || transition.object16) {
+ targetView2.setInt16(position3, value, true);
+ updatedPosition = position3 + 2;
+ return nextTransition;
+ }
+ if (nextTransition = transition.num32) {
+ targetView2.setUint32(position3, 3758096640 + value, true);
+ updatedPosition = position3 + 4;
+ return nextTransition;
+ }
+ if (nextTransition = transition.num64) {
+ targetView2.setFloat64(position3, NaN, true);
+ targetView2.setInt8(position3, value);
+ updatedPosition = position3 + 8;
+ return nextTransition;
+ }
+ updatedPosition = position3;
+ return;
+}
+function createTypeTransition(transition, type, size) {
+ let typeName = TYPE_NAMES[type] + (size << 3);
+ let newTransition = transition[typeName] || (transition[typeName] = Object.create(null));
+ newTransition.__type = type;
+ newTransition.__size = size;
+ newTransition.__parent = transition;
+ return newTransition;
+}
+function onLoadedStructures2(sharedData) {
+ if (!(sharedData instanceof Map))
+ return sharedData;
+ let typed = sharedData.get("typed") || [];
+ if (Object.isFrozen(typed))
+ typed = typed.map((structure) => structure.slice(0));
+ let named = sharedData.get("named");
+ let transitions = Object.create(null);
+ for (let i2 = 0, l2 = typed.length;i2 < l2; i2++) {
+ let structure = typed[i2];
+ let transition = transitions;
+ for (let [type, size, key] of structure) {
+ let nextTransition = transition[key];
+ if (!nextTransition) {
+ transition[key] = nextTransition = {
+ key,
+ parent: transition,
+ enumerationOffset: 0,
+ ascii0: null,
+ ascii8: null,
+ num8: null,
+ string16: null,
+ object16: null,
+ num32: null,
+ float64: null,
+ date64: null
+ };
+ }
+ transition = createTypeTransition(nextTransition, type, size);
+ }
+ transition[RECORD_SYMBOL] = i2;
+ }
+ typed.transitions = transitions;
+ this.typedStructs = typed;
+ this.lastTypedStructuresLength = typed.length;
+ return named;
+}
+var sourceSymbol = Symbol.for("source");
+function readStruct2(src2, position3, srcEnd2, unpackr) {
+ let recordId = src2[position3++] - 32;
+ if (recordId >= 24) {
+ switch (recordId) {
+ case 24:
+ recordId = src2[position3++];
+ break;
+ case 25:
+ recordId = src2[position3++] + (src2[position3++] << 8);
+ break;
+ case 26:
+ recordId = src2[position3++] + (src2[position3++] << 8) + (src2[position3++] << 16);
+ break;
+ case 27:
+ recordId = src2[position3++] + (src2[position3++] << 8) + (src2[position3++] << 16) + (src2[position3++] << 24);
+ break;
+ }
+ }
+ let structure = unpackr.typedStructs && unpackr.typedStructs[recordId];
+ if (!structure) {
+ src2 = Uint8Array.prototype.slice.call(src2, position3, srcEnd2);
+ srcEnd2 -= position3;
+ position3 = 0;
+ if (!unpackr.getStructures)
+ throw new Error(`Reference to shared structure ${recordId} without getStructures method`);
+ unpackr._mergeStructures(unpackr.getStructures());
+ if (!unpackr.typedStructs)
+ throw new Error("Could not find any shared typed structures");
+ unpackr.lastTypedStructuresLength = unpackr.typedStructs.length;
+ structure = unpackr.typedStructs[recordId];
+ if (!structure)
+ throw new Error("Could not find typed structure " + recordId);
+ }
+ var construct2 = structure.construct;
+ var fullConstruct = structure.fullConstruct;
+ if (!construct2) {
+ construct2 = structure.construct = function LazyObject() {};
+ fullConstruct = structure.fullConstruct = function LoadedObject() {};
+ fullConstruct.prototype = unpackr.structPrototype || {};
+ var prototype = construct2.prototype = unpackr.structPrototype ? Object.create(unpackr.structPrototype) : {};
+ let properties = [];
+ let currentOffset = 0;
+ let lastRefProperty;
+ for (let i2 = 0, l2 = structure.length;i2 < l2; i2++) {
+ let definition = structure[i2];
+ let [type, size, key, enumerationOffset] = definition;
+ if (key === "__proto__")
+ key = "__proto_";
+ let property = {
+ key,
+ offset: currentOffset
+ };
+ if (enumerationOffset)
+ properties.splice(i2 + enumerationOffset, 0, property);
+ else
+ properties.push(property);
+ let getRef;
+ switch (size) {
+ case 0:
+ getRef = () => 0;
+ break;
+ case 1:
+ getRef = (source, position4) => {
+ let ref = source.bytes[position4 + property.offset];
+ return ref >= 246 ? toConstant(ref) : ref;
+ };
+ break;
+ case 2:
+ getRef = (source, position4) => {
+ let src3 = source.bytes;
+ let dataView2 = src3.dataView || (src3.dataView = new DataView(src3.buffer, src3.byteOffset, src3.byteLength));
+ let ref = dataView2.getUint16(position4 + property.offset, true);
+ return ref >= 65280 ? toConstant(ref & 255) : ref;
+ };
+ break;
+ case 4:
+ getRef = (source, position4) => {
+ let src3 = source.bytes;
+ let dataView2 = src3.dataView || (src3.dataView = new DataView(src3.buffer, src3.byteOffset, src3.byteLength));
+ let ref = dataView2.getUint32(position4 + property.offset, true);
+ return ref >= 4294967040 ? toConstant(ref & 255) : ref;
+ };
+ break;
+ }
+ property.getRef = getRef;
+ currentOffset += size;
+ let get;
+ switch (type) {
+ case ASCII:
+ if (lastRefProperty && !lastRefProperty.next)
+ lastRefProperty.next = property;
+ lastRefProperty = property;
+ property.multiGetCount = 0;
+ get = function(source) {
+ let src3 = source.bytes;
+ let position4 = source.position;
+ let refStart = currentOffset + position4;
+ let ref = getRef(source, position4);
+ if (typeof ref !== "number")
+ return ref;
+ let end, next = property.next;
+ while (next) {
+ end = next.getRef(source, position4);
+ if (typeof end === "number")
+ break;
+ else
+ end = null;
+ next = next.next;
+ }
+ if (end == null)
+ end = source.bytesEnd - refStart;
+ if (source.srcString) {
+ return source.srcString.slice(ref, end);
+ }
+ return readString(src3, ref + refStart, end - ref);
+ };
+ break;
+ case UTF8:
+ case OBJECT_DATA:
+ if (lastRefProperty && !lastRefProperty.next)
+ lastRefProperty.next = property;
+ lastRefProperty = property;
+ get = function(source) {
+ let position4 = source.position;
+ let refStart = currentOffset + position4;
+ let ref = getRef(source, position4);
+ if (typeof ref !== "number")
+ return ref;
+ let src3 = source.bytes;
+ let end, next = property.next;
+ while (next) {
+ end = next.getRef(source, position4);
+ if (typeof end === "number")
+ break;
+ else
+ end = null;
+ next = next.next;
+ }
+ if (end == null)
+ end = source.bytesEnd - refStart;
+ if (type === UTF8) {
+ return src3.toString("utf8", ref + refStart, end + refStart);
+ } else {
+ currentSource = source;
+ try {
+ return unpackr.unpack(src3, { start: ref + refStart, end: end + refStart });
+ } finally {
+ currentSource = null;
+ }
+ }
+ };
+ break;
+ case NUMBER:
+ switch (size) {
+ case 4:
+ get = function(source) {
+ let src3 = source.bytes;
+ let dataView2 = src3.dataView || (src3.dataView = new DataView(src3.buffer, src3.byteOffset, src3.byteLength));
+ let position4 = source.position + property.offset;
+ let value = dataView2.getInt32(position4, true);
+ if (value < 536870912) {
+ if (value > -520093696)
+ return value;
+ if (value > -536870912)
+ return toConstant(value & 255);
+ }
+ let fValue = dataView2.getFloat32(position4, true);
+ let multiplier = mult10[(src3[position4 + 3] & 127) << 1 | src3[position4 + 2] >> 7];
+ return (multiplier * fValue + (fValue > 0 ? 0.5 : -0.5) >> 0) / multiplier;
+ };
+ break;
+ case 8:
+ get = function(source) {
+ let src3 = source.bytes;
+ let dataView2 = src3.dataView || (src3.dataView = new DataView(src3.buffer, src3.byteOffset, src3.byteLength));
+ let value = dataView2.getFloat64(source.position + property.offset, true);
+ if (isNaN(value)) {
+ let byte = src3[source.position + property.offset];
+ if (byte >= 246)
+ return toConstant(byte);
+ }
+ return value;
+ };
+ break;
+ case 1:
+ get = function(source) {
+ let src3 = source.bytes;
+ let value = src3[source.position + property.offset];
+ return value < 246 ? value : toConstant(value);
+ };
+ break;
+ }
+ break;
+ case DATE:
+ get = function(source) {
+ let src3 = source.bytes;
+ let dataView2 = src3.dataView || (src3.dataView = new DataView(src3.buffer, src3.byteOffset, src3.byteLength));
+ return new Date(dataView2.getFloat64(source.position + property.offset, true));
+ };
+ break;
+ }
+ property.get = get;
+ }
+ if (evalSupported) {
+ let objectLiteralProperties = [];
+ let args = [];
+ let i2 = 0;
+ let hasInheritedProperties;
+ for (let property of properties) {
+ if (unpackr.alwaysLazyProperty && unpackr.alwaysLazyProperty(property.key)) {
+ hasInheritedProperties = true;
+ continue;
+ }
+ Object.defineProperty(prototype, property.key, { get: withSource(property.get), enumerable: true });
+ let valueFunction = "v" + i2++;
+ args.push(valueFunction);
+ objectLiteralProperties.push("o[" + JSON.stringify(property.key) + "]=" + valueFunction + "(s)");
+ }
+ if (hasInheritedProperties) {
+ objectLiteralProperties.push("__proto__:this");
+ }
+ let toObject = new Function(...args, "var c=this;return function(s){var o=new c();" + objectLiteralProperties.join(";") + ";return o;}").apply(fullConstruct, properties.map((prop) => prop.get));
+ Object.defineProperty(prototype, "toJSON", {
+ value(omitUnderscoredProperties) {
+ return toObject.call(this, this[sourceSymbol]);
+ }
+ });
+ } else {
+ Object.defineProperty(prototype, "toJSON", {
+ value(omitUnderscoredProperties) {
+ let resolved = {};
+ for (let i2 = 0, l2 = properties.length;i2 < l2; i2++) {
+ let key = properties[i2].key;
+ resolved[key] = this[key];
+ }
+ return resolved;
+ }
+ });
+ }
+ }
+ var instance = new construct2;
+ instance[sourceSymbol] = {
+ bytes: src2,
+ position: position3,
+ srcString: "",
+ bytesEnd: srcEnd2
+ };
+ return instance;
+}
+function toConstant(code) {
+ switch (code) {
+ case 246:
+ return null;
+ case 247:
+ return;
+ case 248:
+ return false;
+ case 249:
+ return true;
+ }
+ throw new Error("Unknown constant");
+}
+function withSource(get) {
+ return function() {
+ return get(this[sourceSymbol]);
+ };
+}
+function saveState2() {
+ if (currentSource) {
+ currentSource.bytes = Uint8Array.prototype.slice.call(currentSource.bytes, currentSource.position, currentSource.bytesEnd);
+ currentSource.position = 0;
+ currentSource.bytesEnd = currentSource.bytes.length;
+ }
+}
+function prepareStructures2(structures, packr) {
+ if (packr.typedStructs) {
+ let structMap = new Map;
+ structMap.set("named", structures);
+ structMap.set("typed", packr.typedStructs);
+ structures = structMap;
+ }
+ let lastTypedStructuresLength = packr.lastTypedStructuresLength || 0;
+ structures.isCompatible = (existing) => {
+ let compatible = true;
+ if (existing instanceof Map) {
+ let named = existing.get("named") || [];
+ if (named.length !== (packr.lastNamedStructuresLength || 0))
+ compatible = false;
+ let typed = existing.get("typed") || [];
+ if (typed.length !== lastTypedStructuresLength)
+ compatible = false;
+ } else if (existing instanceof Array || Array.isArray(existing)) {
+ if (existing.length !== (packr.lastNamedStructuresLength || 0))
+ compatible = false;
+ }
+ if (!compatible)
+ packr._mergeStructures(existing);
+ return compatible;
+ };
+ packr.lastTypedStructuresLength = packr.typedStructs && packr.typedStructs.length;
+ return structures;
+}
+setReadStruct(readStruct2, onLoadedStructures2, saveState2);
+// node_modules/.pnpm/msgpackr@1.11.5/node_modules/msgpackr/node-index.js
+var nativeAccelerationDisabled = process.env.MSGPACKR_NATIVE_ACCELERATION_DISABLED !== undefined && process.env.MSGPACKR_NATIVE_ACCELERATION_DISABLED.toLowerCase() === "true";
+if (!nativeAccelerationDisabled) {
+ let extractor;
+ try {
+ if (true)
+ extractor = require_msgpackr_extract();
+ else
+ ;
+ if (extractor)
+ setExtractor(extractor.extractStrings);
+ } catch (error) {}
+}
+
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/version.js
+var version3 = "5.76.1";
+
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/scripts.js
+var packer = new Packr({
+ useRecords: false,
+ encodeUndefinedAsNil: true
+});
+var pack2 = packer.pack;
+
+class Scripts {
+ constructor(queue) {
+ this.queue = queue;
+ this.version = version3;
+ const queueKeys = this.queue.keys;
+ this.moveToFinishedKeys = [
+ queueKeys.wait,
+ queueKeys.active,
+ queueKeys.prioritized,
+ queueKeys.events,
+ queueKeys.stalled,
+ queueKeys.limiter,
+ queueKeys.delayed,
+ queueKeys.paused,
+ queueKeys.meta,
+ queueKeys.pc,
+ undefined,
+ undefined,
+ undefined,
+ undefined
+ ];
+ }
+ execCommand(client, commandName, args) {
+ const commandNameWithVersion = `${commandName}:${this.version}`;
+ return client[commandNameWithVersion](args);
+ }
+ async isJobInList(listKey, jobId) {
+ const client = await this.queue.client;
+ let result;
+ if (isRedisVersionLowerThan(this.queue.redisVersion, "6.0.6", this.queue.databaseType)) {
+ result = await this.execCommand(client, "isJobInList", [listKey, jobId]);
+ } else {
+ result = await client.lpos(listKey, jobId);
+ }
+ return Number.isInteger(result);
+ }
+ addDelayedJobArgs(job, encodedOpts, args) {
+ const queueKeys = this.queue.keys;
+ const keys = [
+ queueKeys.marker,
+ queueKeys.meta,
+ queueKeys.id,
+ queueKeys.delayed,
+ queueKeys.completed,
+ queueKeys.events
+ ];
+ keys.push(pack2(args), job.data, encodedOpts);
+ return keys;
+ }
+ addDelayedJob(client, job, encodedOpts, args) {
+ const argsList = this.addDelayedJobArgs(job, encodedOpts, args);
+ return this.execCommand(client, "addDelayedJob", argsList);
+ }
+ addPrioritizedJobArgs(job, encodedOpts, args) {
+ const queueKeys = this.queue.keys;
+ const keys = [
+ queueKeys.marker,
+ queueKeys.meta,
+ queueKeys.id,
+ queueKeys.prioritized,
+ queueKeys.delayed,
+ queueKeys.completed,
+ queueKeys.active,
+ queueKeys.events,
+ queueKeys.pc
+ ];
+ keys.push(pack2(args), job.data, encodedOpts);
+ return keys;
+ }
+ addPrioritizedJob(client, job, encodedOpts, args) {
+ const argsList = this.addPrioritizedJobArgs(job, encodedOpts, args);
+ return this.execCommand(client, "addPrioritizedJob", argsList);
+ }
+ addParentJobArgs(job, encodedOpts, args) {
+ const queueKeys = this.queue.keys;
+ const keys = [
+ queueKeys.meta,
+ queueKeys.id,
+ queueKeys.delayed,
+ queueKeys["waiting-children"],
+ queueKeys.completed,
+ queueKeys.events
+ ];
+ keys.push(pack2(args), job.data, encodedOpts);
+ return keys;
+ }
+ addParentJob(client, job, encodedOpts, args) {
+ const argsList = this.addParentJobArgs(job, encodedOpts, args);
+ return this.execCommand(client, "addParentJob", argsList);
+ }
+ addStandardJobArgs(job, encodedOpts, args) {
+ const queueKeys = this.queue.keys;
+ const keys = [
+ queueKeys.wait,
+ queueKeys.paused,
+ queueKeys.meta,
+ queueKeys.id,
+ queueKeys.completed,
+ queueKeys.delayed,
+ queueKeys.active,
+ queueKeys.events,
+ queueKeys.marker
+ ];
+ keys.push(pack2(args), job.data, encodedOpts);
+ return keys;
+ }
+ addStandardJob(client, job, encodedOpts, args) {
+ const argsList = this.addStandardJobArgs(job, encodedOpts, args);
+ return this.execCommand(client, "addStandardJob", argsList);
+ }
+ async addJob(client, job, opts, jobId, parentKeyOpts = {}) {
+ const queueKeys = this.queue.keys;
+ const parent = job.parent;
+ const args = [
+ queueKeys[""],
+ typeof jobId !== "undefined" ? jobId : "",
+ job.name,
+ job.timestamp,
+ job.parentKey || null,
+ parentKeyOpts.parentDependenciesKey || null,
+ parent,
+ job.repeatJobKey,
+ job.deduplicationId ? `${queueKeys.de}:${job.deduplicationId}` : null
+ ];
+ let encodedOpts;
+ if (opts.repeat) {
+ const repeat = Object.assign({}, opts.repeat);
+ if (repeat.startDate) {
+ repeat.startDate = +new Date(repeat.startDate);
+ }
+ if (repeat.endDate) {
+ repeat.endDate = +new Date(repeat.endDate);
+ }
+ encodedOpts = pack2(Object.assign(Object.assign({}, opts), { repeat }));
+ } else {
+ encodedOpts = pack2(opts);
+ }
+ let result;
+ if (parentKeyOpts.addToWaitingChildren) {
+ result = await this.addParentJob(client, job, encodedOpts, args);
+ } else if (typeof opts.delay == "number" && opts.delay > 0) {
+ result = await this.addDelayedJob(client, job, encodedOpts, args);
+ } else if (opts.priority) {
+ result = await this.addPrioritizedJob(client, job, encodedOpts, args);
+ } else {
+ result = await this.addStandardJob(client, job, encodedOpts, args);
+ }
+ if (result < 0) {
+ throw this.finishedErrors({
+ code: result,
+ parentKey: parentKeyOpts.parentKey,
+ command: "addJob"
+ });
+ }
+ return result;
+ }
+ pauseArgs(pause) {
+ let src2 = "wait", dst = "paused";
+ if (!pause) {
+ src2 = "paused";
+ dst = "wait";
+ }
+ const keys = [src2, dst, "meta", "prioritized"].map((name) => this.queue.toKey(name));
+ keys.push(this.queue.keys.events, this.queue.keys.delayed, this.queue.keys.marker);
+ const args = [pause ? "paused" : "resumed"];
+ return keys.concat(args);
+ }
+ async pause(pause) {
+ const client = await this.queue.client;
+ const args = this.pauseArgs(pause);
+ return this.execCommand(client, "pause", args);
+ }
+ addRepeatableJobArgs(customKey, nextMillis, opts, legacyCustomKey) {
+ const queueKeys = this.queue.keys;
+ const keys = [
+ queueKeys.repeat,
+ queueKeys.delayed
+ ];
+ const args = [
+ nextMillis,
+ pack2(opts),
+ legacyCustomKey,
+ customKey,
+ queueKeys[""]
+ ];
+ return keys.concat(args);
+ }
+ async addRepeatableJob(customKey, nextMillis, opts, legacyCustomKey) {
+ const client = await this.queue.client;
+ const args = this.addRepeatableJobArgs(customKey, nextMillis, opts, legacyCustomKey);
+ return this.execCommand(client, "addRepeatableJob", args);
+ }
+ async removeDeduplicationKey(deduplicationId, jobId) {
+ const client = await this.queue.client;
+ const queueKeys = this.queue.keys;
+ const keys = [`${queueKeys.de}:${deduplicationId}`];
+ const args = [jobId];
+ return this.execCommand(client, "removeDeduplicationKey", keys.concat(args));
+ }
+ async addJobScheduler(jobSchedulerId, nextMillis, templateData, templateOpts, opts, delayedJobOpts, producerId) {
+ const client = await this.queue.client;
+ const queueKeys = this.queue.keys;
+ const keys = [
+ queueKeys.repeat,
+ queueKeys.delayed,
+ queueKeys.wait,
+ queueKeys.paused,
+ queueKeys.meta,
+ queueKeys.prioritized,
+ queueKeys.marker,
+ queueKeys.id,
+ queueKeys.events,
+ queueKeys.pc,
+ queueKeys.active
+ ];
+ const args = [
+ nextMillis,
+ pack2(opts),
+ jobSchedulerId,
+ templateData,
+ pack2(templateOpts),
+ pack2(delayedJobOpts),
+ Date.now(),
+ queueKeys[""],
+ producerId ? this.queue.toKey(producerId) : ""
+ ];
+ const result = await this.execCommand(client, "addJobScheduler", keys.concat(args));
+ if (typeof result === "number" && result < 0) {
+ throw this.finishedErrors({
+ code: result,
+ command: "addJobScheduler"
+ });
+ }
+ return result;
+ }
+ async updateRepeatableJobMillis(client, customKey, nextMillis, legacyCustomKey) {
+ const args = [
+ this.queue.keys.repeat,
+ nextMillis,
+ customKey,
+ legacyCustomKey
+ ];
+ return this.execCommand(client, "updateRepeatableJobMillis", args);
+ }
+ async updateJobSchedulerNextMillis(jobSchedulerId, nextMillis, templateData, delayedJobOpts, producerId) {
+ const client = await this.queue.client;
+ const queueKeys = this.queue.keys;
+ const keys = [
+ queueKeys.repeat,
+ queueKeys.delayed,
+ queueKeys.wait,
+ queueKeys.paused,
+ queueKeys.meta,
+ queueKeys.prioritized,
+ queueKeys.marker,
+ queueKeys.id,
+ queueKeys.events,
+ queueKeys.pc,
+ producerId ? this.queue.toKey(producerId) : "",
+ queueKeys.active
+ ];
+ const args = [
+ nextMillis,
+ jobSchedulerId,
+ templateData,
+ pack2(delayedJobOpts),
+ Date.now(),
+ queueKeys[""],
+ producerId
+ ];
+ return this.execCommand(client, "updateJobScheduler", keys.concat(args));
+ }
+ removeRepeatableArgs(legacyRepeatJobId, repeatConcatOptions, repeatJobKey) {
+ const queueKeys = this.queue.keys;
+ const keys = [queueKeys.repeat, queueKeys.delayed, queueKeys.events];
+ const args = [
+ legacyRepeatJobId,
+ this.getRepeatConcatOptions(repeatConcatOptions, repeatJobKey),
+ repeatJobKey,
+ queueKeys[""]
+ ];
+ return keys.concat(args);
+ }
+ getRepeatConcatOptions(repeatConcatOptions, repeatJobKey) {
+ if (repeatJobKey && repeatJobKey.split(":").length > 2) {
+ return repeatJobKey;
+ }
+ return repeatConcatOptions;
+ }
+ async removeRepeatable(legacyRepeatJobId, repeatConcatOptions, repeatJobKey) {
+ const client = await this.queue.client;
+ const args = this.removeRepeatableArgs(legacyRepeatJobId, repeatConcatOptions, repeatJobKey);
+ return this.execCommand(client, "removeRepeatable", args);
+ }
+ async removeJobScheduler(jobSchedulerId) {
+ const client = await this.queue.client;
+ const queueKeys = this.queue.keys;
+ const keys = [queueKeys.repeat, queueKeys.delayed, queueKeys.events];
+ const args = [jobSchedulerId, queueKeys[""]];
+ return this.execCommand(client, "removeJobScheduler", keys.concat(args));
+ }
+ removeArgs(jobId, removeChildren) {
+ const keys = [jobId, "repeat"].map((name) => this.queue.toKey(name));
+ const args = [jobId, removeChildren ? 1 : 0, this.queue.toKey("")];
+ return keys.concat(args);
+ }
+ async remove(jobId, removeChildren) {
+ const client = await this.queue.client;
+ const args = this.removeArgs(jobId, removeChildren);
+ const result = await this.execCommand(client, "removeJob", args);
+ if (result < 0) {
+ throw this.finishedErrors({
+ code: result,
+ jobId,
+ command: "removeJob"
+ });
+ }
+ return result;
+ }
+ async removeUnprocessedChildren(jobId) {
+ const client = await this.queue.client;
+ const args = [
+ this.queue.toKey(jobId),
+ this.queue.keys.meta,
+ this.queue.toKey(""),
+ jobId
+ ];
+ await this.execCommand(client, "removeUnprocessedChildren", args);
+ }
+ async extendLock(jobId, token, duration, client) {
+ client = client || await this.queue.client;
+ const args = [
+ this.queue.toKey(jobId) + ":lock",
+ this.queue.keys.stalled,
+ token,
+ duration,
+ jobId
+ ];
+ return this.execCommand(client, "extendLock", args);
+ }
+ async extendLocks(jobIds, tokens, duration) {
+ const client = await this.queue.client;
+ const args = [
+ this.queue.keys.stalled,
+ this.queue.toKey(""),
+ pack2(tokens),
+ pack2(jobIds),
+ duration
+ ];
+ return this.execCommand(client, "extendLocks", args);
+ }
+ async updateData(job, data) {
+ const client = await this.queue.client;
+ const keys = [this.queue.toKey(job.id)];
+ const dataJson = JSON.stringify(data);
+ const result = await this.execCommand(client, "updateData", keys.concat([dataJson]));
+ if (result < 0) {
+ throw this.finishedErrors({
+ code: result,
+ jobId: job.id,
+ command: "updateData"
+ });
+ }
+ }
+ async updateProgress(jobId, progress) {
+ const client = await this.queue.client;
+ const keys = [
+ this.queue.toKey(jobId),
+ this.queue.keys.events,
+ this.queue.keys.meta
+ ];
+ const progressJson = JSON.stringify(progress);
+ const result = await this.execCommand(client, "updateProgress", keys.concat([jobId, progressJson]));
+ if (result < 0) {
+ throw this.finishedErrors({
+ code: result,
+ jobId,
+ command: "updateProgress"
+ });
+ }
+ }
+ async addLog(jobId, logRow, keepLogs) {
+ const client = await this.queue.client;
+ const keys = [
+ this.queue.toKey(jobId),
+ this.queue.toKey(jobId) + ":logs"
+ ];
+ const result = await this.execCommand(client, "addLog", keys.concat([jobId, logRow, keepLogs ? keepLogs : ""]));
+ if (result < 0) {
+ throw this.finishedErrors({
+ code: result,
+ jobId,
+ command: "addLog"
+ });
+ }
+ return result;
+ }
+ moveToFinishedArgs(job, val, propVal, shouldRemove, target2, token, timestamp3, fetchNext = true, fieldsToUpdate) {
+ var _a, _b, _c2, _d2, _e2, _f, _g;
+ const queueKeys = this.queue.keys;
+ const opts = this.queue.opts;
+ const workerKeepJobs = target2 === "completed" ? opts.removeOnComplete : opts.removeOnFail;
+ const metricsKey = this.queue.toKey(`metrics:${target2}`);
+ const keys = this.moveToFinishedKeys;
+ keys[10] = queueKeys[target2];
+ keys[11] = this.queue.toKey((_a = job.id) !== null && _a !== undefined ? _a : "");
+ keys[12] = metricsKey;
+ keys[13] = this.queue.keys.marker;
+ const keepJobs = this.getKeepJobs(shouldRemove, workerKeepJobs);
+ const args = [
+ job.id,
+ timestamp3,
+ propVal,
+ typeof val === "undefined" ? "null" : val,
+ target2,
+ !fetchNext || this.queue.closing ? 0 : 1,
+ queueKeys[""],
+ pack2({
+ token,
+ name: opts.name,
+ keepJobs,
+ limiter: opts.limiter,
+ lockDuration: opts.lockDuration,
+ attempts: job.opts.attempts,
+ maxMetricsSize: ((_b = opts.metrics) === null || _b === undefined ? undefined : _b.maxDataPoints) ? (_c2 = opts.metrics) === null || _c2 === undefined ? undefined : _c2.maxDataPoints : "",
+ fpof: !!((_d2 = job.opts) === null || _d2 === undefined ? undefined : _d2.failParentOnFailure),
+ cpof: !!((_e2 = job.opts) === null || _e2 === undefined ? undefined : _e2.continueParentOnFailure),
+ idof: !!((_f = job.opts) === null || _f === undefined ? undefined : _f.ignoreDependencyOnFailure),
+ rdof: !!((_g = job.opts) === null || _g === undefined ? undefined : _g.removeDependencyOnFailure)
+ }),
+ fieldsToUpdate ? pack2(objectToFlatArray(fieldsToUpdate)) : undefined
+ ];
+ return keys.concat(args);
+ }
+ getKeepJobs(shouldRemove, workerKeepJobs) {
+ if (typeof shouldRemove === "undefined") {
+ return workerKeepJobs || { count: shouldRemove ? 0 : -1 };
+ }
+ return typeof shouldRemove === "object" ? shouldRemove : typeof shouldRemove === "number" ? { count: shouldRemove } : { count: shouldRemove ? 0 : -1 };
+ }
+ async moveToFinished(jobId, args) {
+ const client = await this.queue.client;
+ const result = await this.execCommand(client, "moveToFinished", args);
+ if (result < 0) {
+ throw this.finishedErrors({
+ code: result,
+ jobId,
+ command: "moveToFinished",
+ state: "active"
+ });
+ } else {
+ if (typeof result !== "undefined") {
+ return raw2NextJobData(result);
+ }
+ }
+ }
+ drainArgs(delayed) {
+ const queueKeys = this.queue.keys;
+ const keys = [
+ queueKeys.wait,
+ queueKeys.paused,
+ queueKeys.delayed,
+ queueKeys.prioritized,
+ queueKeys.repeat
+ ];
+ const args = [queueKeys[""], delayed ? "1" : "0"];
+ return keys.concat(args);
+ }
+ async drain(delayed) {
+ const client = await this.queue.client;
+ const args = this.drainArgs(delayed);
+ return this.execCommand(client, "drain", args);
+ }
+ removeChildDependencyArgs(jobId, parentKey) {
+ const queueKeys = this.queue.keys;
+ const keys = [queueKeys[""]];
+ const args = [this.queue.toKey(jobId), parentKey];
+ return keys.concat(args);
+ }
+ async removeChildDependency(jobId, parentKey) {
+ const client = await this.queue.client;
+ const args = this.removeChildDependencyArgs(jobId, parentKey);
+ const result = await this.execCommand(client, "removeChildDependency", args);
+ switch (result) {
+ case 0:
+ return true;
+ case 1:
+ return false;
+ default:
+ throw this.finishedErrors({
+ code: result,
+ jobId,
+ parentKey,
+ command: "removeChildDependency"
+ });
+ }
+ }
+ getRangesArgs(types6, start, end, asc2) {
+ const queueKeys = this.queue.keys;
+ const transformedTypes = types6.map((type) => {
+ return type === "waiting" ? "wait" : type;
+ });
+ const keys = [queueKeys[""]];
+ const args = [start, end, asc2 ? "1" : "0", ...transformedTypes];
+ return keys.concat(args);
+ }
+ async getRanges(types6, start = 0, end = 1, asc2 = false) {
+ const client = await this.queue.client;
+ const args = this.getRangesArgs(types6, start, end, asc2);
+ return await this.execCommand(client, "getRanges", args);
+ }
+ getCountsArgs(types6) {
+ const queueKeys = this.queue.keys;
+ const transformedTypes = types6.map((type) => {
+ return type === "waiting" ? "wait" : type;
+ });
+ const keys = [queueKeys[""]];
+ const args = [...transformedTypes];
+ return keys.concat(args);
+ }
+ async getCounts(types6) {
+ const client = await this.queue.client;
+ const args = this.getCountsArgs(types6);
+ return await this.execCommand(client, "getCounts", args);
+ }
+ getCountsPerPriorityArgs(priorities) {
+ const keys = [
+ this.queue.keys.wait,
+ this.queue.keys.paused,
+ this.queue.keys.meta,
+ this.queue.keys.prioritized
+ ];
+ const args = priorities;
+ return keys.concat(args);
+ }
+ async getCountsPerPriority(priorities) {
+ const client = await this.queue.client;
+ const args = this.getCountsPerPriorityArgs(priorities);
+ return await this.execCommand(client, "getCountsPerPriority", args);
+ }
+ getDependencyCountsArgs(jobId, types6) {
+ const keys = [
+ `${jobId}:processed`,
+ `${jobId}:dependencies`,
+ `${jobId}:failed`,
+ `${jobId}:unsuccessful`
+ ].map((name) => {
+ return this.queue.toKey(name);
+ });
+ const args = types6;
+ return keys.concat(args);
+ }
+ async getDependencyCounts(jobId, types6) {
+ const client = await this.queue.client;
+ const args = this.getDependencyCountsArgs(jobId, types6);
+ return await this.execCommand(client, "getDependencyCounts", args);
+ }
+ moveToCompletedArgs(job, returnvalue, removeOnComplete, token, fetchNext = false) {
+ const timestamp3 = Date.now();
+ return this.moveToFinishedArgs(job, returnvalue, "returnvalue", removeOnComplete, "completed", token, timestamp3, fetchNext);
+ }
+ moveToFailedArgs(job, failedReason, removeOnFailed, token, fetchNext = false, fieldsToUpdate) {
+ const timestamp3 = Date.now();
+ return this.moveToFinishedArgs(job, failedReason, "failedReason", removeOnFailed, "failed", token, timestamp3, fetchNext, fieldsToUpdate);
+ }
+ async isFinished(jobId, returnValue = false) {
+ const client = await this.queue.client;
+ const keys = ["completed", "failed", jobId].map((key) => {
+ return this.queue.toKey(key);
+ });
+ return this.execCommand(client, "isFinished", keys.concat([jobId, returnValue ? "1" : ""]));
+ }
+ async getState(jobId) {
+ const client = await this.queue.client;
+ const keys = [
+ "completed",
+ "failed",
+ "delayed",
+ "active",
+ "wait",
+ "paused",
+ "waiting-children",
+ "prioritized"
+ ].map((key) => {
+ return this.queue.toKey(key);
+ });
+ if (isRedisVersionLowerThan(this.queue.redisVersion, "6.0.6", this.queue.databaseType)) {
+ return this.execCommand(client, "getState", keys.concat([jobId]));
+ }
+ return this.execCommand(client, "getStateV2", keys.concat([jobId]));
+ }
+ async changeDelay(jobId, delay2) {
+ const client = await this.queue.client;
+ const args = this.changeDelayArgs(jobId, delay2);
+ const result = await this.execCommand(client, "changeDelay", args);
+ if (result < 0) {
+ throw this.finishedErrors({
+ code: result,
+ jobId,
+ command: "changeDelay",
+ state: "delayed"
+ });
+ }
+ }
+ changeDelayArgs(jobId, delay2) {
+ const timestamp3 = Date.now();
+ const keys = [
+ this.queue.keys.delayed,
+ this.queue.keys.meta,
+ this.queue.keys.marker,
+ this.queue.keys.events
+ ];
+ return keys.concat([
+ delay2,
+ JSON.stringify(timestamp3),
+ jobId,
+ this.queue.toKey(jobId)
+ ]);
+ }
+ async changePriority(jobId, priority = 0, lifo = false) {
+ const client = await this.queue.client;
+ const args = this.changePriorityArgs(jobId, priority, lifo);
+ const result = await this.execCommand(client, "changePriority", args);
+ if (result < 0) {
+ throw this.finishedErrors({
+ code: result,
+ jobId,
+ command: "changePriority"
+ });
+ }
+ }
+ changePriorityArgs(jobId, priority = 0, lifo = false) {
+ const keys = [
+ this.queue.keys.wait,
+ this.queue.keys.paused,
+ this.queue.keys.meta,
+ this.queue.keys.prioritized,
+ this.queue.keys.active,
+ this.queue.keys.pc,
+ this.queue.keys.marker
+ ];
+ return keys.concat([priority, this.queue.toKey(""), jobId, lifo ? 1 : 0]);
+ }
+ moveToDelayedArgs(jobId, timestamp3, token, delay2, opts = {}) {
+ const queueKeys = this.queue.keys;
+ const workerOpts = this.queue.opts;
+ const keys = [
+ queueKeys.marker,
+ queueKeys.active,
+ queueKeys.prioritized,
+ queueKeys.delayed,
+ this.queue.toKey(jobId),
+ queueKeys.events,
+ queueKeys.meta,
+ queueKeys.stalled,
+ queueKeys.wait,
+ queueKeys.limiter,
+ queueKeys.paused,
+ queueKeys.pc
+ ];
+ const fetchNext = opts.fetchNext && !this.queue.closing ? 1 : 0;
+ return keys.concat([
+ this.queue.keys[""],
+ timestamp3,
+ jobId,
+ token,
+ delay2,
+ opts.skipAttempt ? "1" : "0",
+ opts.fieldsToUpdate ? pack2(objectToFlatArray(opts.fieldsToUpdate)) : undefined,
+ fetchNext,
+ fetchNext ? pack2({
+ token,
+ lockDuration: workerOpts.lockDuration,
+ limiter: workerOpts.limiter,
+ name: workerOpts.name
+ }) : undefined
+ ]);
+ }
+ moveToWaitingChildrenArgs(jobId, token, opts) {
+ const timestamp3 = Date.now();
+ const childKey = getParentKey(opts.child);
+ const keys = [
+ "active",
+ "waiting-children",
+ jobId,
+ `${jobId}:dependencies`,
+ `${jobId}:unsuccessful`,
+ "stalled",
+ "events"
+ ].map((name) => {
+ return this.queue.toKey(name);
+ });
+ return keys.concat([
+ token,
+ childKey !== null && childKey !== undefined ? childKey : "",
+ JSON.stringify(timestamp3),
+ jobId,
+ this.queue.toKey("")
+ ]);
+ }
+ isMaxedArgs() {
+ const queueKeys = this.queue.keys;
+ const keys = [queueKeys.meta, queueKeys.active];
+ return keys;
+ }
+ async isMaxed() {
+ const client = await this.queue.client;
+ const args = this.isMaxedArgs();
+ return !!await this.execCommand(client, "isMaxed", args);
+ }
+ async moveToDelayed(jobId, timestamp3, delay2, token = "0", opts = {}) {
+ const client = await this.queue.client;
+ const args = this.moveToDelayedArgs(jobId, timestamp3, token, delay2, opts);
+ const result = await this.execCommand(client, "moveToDelayed", args);
+ if (result < 0) {
+ throw this.finishedErrors({
+ code: result,
+ jobId,
+ command: "moveToDelayed",
+ state: "active"
+ });
+ } else if (typeof result !== "undefined") {
+ return raw2NextJobData(result);
+ }
+ }
+ async moveToWaitingChildren(jobId, token, opts = {}) {
+ const client = await this.queue.client;
+ const args = this.moveToWaitingChildrenArgs(jobId, token, opts);
+ const result = await this.execCommand(client, "moveToWaitingChildren", args);
+ switch (result) {
+ case 0:
+ return true;
+ case 1:
+ return false;
+ default:
+ throw this.finishedErrors({
+ code: result,
+ jobId,
+ command: "moveToWaitingChildren",
+ state: "active"
+ });
+ }
+ }
+ getRateLimitTtlArgs(maxJobs) {
+ const keys = [
+ this.queue.keys.limiter,
+ this.queue.keys.meta
+ ];
+ return keys.concat([maxJobs !== null && maxJobs !== undefined ? maxJobs : "0"]);
+ }
+ async getRateLimitTtl(maxJobs) {
+ const client = await this.queue.client;
+ const args = this.getRateLimitTtlArgs(maxJobs);
+ return this.execCommand(client, "getRateLimitTtl", args);
+ }
+ async cleanJobsInSet(set, timestamp3, limit = 0) {
+ const client = await this.queue.client;
+ return this.execCommand(client, "cleanJobsInSet", [
+ this.queue.toKey(set),
+ this.queue.toKey("events"),
+ this.queue.toKey("repeat"),
+ this.queue.toKey(""),
+ timestamp3,
+ limit,
+ set
+ ]);
+ }
+ getJobSchedulerArgs(id) {
+ const keys = [this.queue.keys.repeat];
+ return keys.concat([id]);
+ }
+ async getJobScheduler(id) {
+ const client = await this.queue.client;
+ const args = this.getJobSchedulerArgs(id);
+ return this.execCommand(client, "getJobScheduler", args);
+ }
+ retryJobArgs(jobId, lifo, token, opts = {}) {
+ const keys = [
+ this.queue.keys.active,
+ this.queue.keys.wait,
+ this.queue.keys.paused,
+ this.queue.toKey(jobId),
+ this.queue.keys.meta,
+ this.queue.keys.events,
+ this.queue.keys.delayed,
+ this.queue.keys.prioritized,
+ this.queue.keys.pc,
+ this.queue.keys.marker,
+ this.queue.keys.stalled
+ ];
+ const pushCmd = (lifo ? "R" : "L") + "PUSH";
+ return keys.concat([
+ this.queue.toKey(""),
+ Date.now(),
+ pushCmd,
+ jobId,
+ token,
+ opts.fieldsToUpdate ? pack2(objectToFlatArray(opts.fieldsToUpdate)) : undefined
+ ]);
+ }
+ async retryJob(jobId, lifo, token = "0", opts = {}) {
+ const client = await this.queue.client;
+ const args = this.retryJobArgs(jobId, lifo, token, opts);
+ const result = await this.execCommand(client, "retryJob", args);
+ if (result < 0) {
+ throw this.finishedErrors({
+ code: result,
+ jobId,
+ command: "retryJob",
+ state: "active"
+ });
+ }
+ }
+ moveJobsToWaitArgs(state, count2, timestamp3) {
+ const keys = [
+ this.queue.toKey(""),
+ this.queue.keys.events,
+ this.queue.toKey(state),
+ this.queue.toKey("wait"),
+ this.queue.toKey("paused"),
+ this.queue.keys.meta,
+ this.queue.keys.active,
+ this.queue.keys.marker
+ ];
+ const args = [count2, timestamp3, state];
+ return keys.concat(args);
+ }
+ async retryJobs(state = "failed", count2 = 1000, timestamp3 = new Date().getTime()) {
+ const client = await this.queue.client;
+ const args = this.moveJobsToWaitArgs(state, count2, timestamp3);
+ return this.execCommand(client, "moveJobsToWait", args);
+ }
+ async promoteJobs(count2 = 1000) {
+ const client = await this.queue.client;
+ const args = this.moveJobsToWaitArgs("delayed", count2, Number.MAX_VALUE);
+ return this.execCommand(client, "moveJobsToWait", args);
+ }
+ async reprocessJob(job, state, opts = {}) {
+ const client = await this.queue.client;
+ const keys = [
+ this.queue.toKey(job.id),
+ this.queue.keys.events,
+ this.queue.toKey(state),
+ this.queue.keys.wait,
+ this.queue.keys.meta,
+ this.queue.keys.paused,
+ this.queue.keys.active,
+ this.queue.keys.marker
+ ];
+ const args = [
+ job.id,
+ (job.opts.lifo ? "R" : "L") + "PUSH",
+ state === "failed" ? "failedReason" : "returnvalue",
+ state,
+ opts.resetAttemptsMade ? "1" : "0",
+ opts.resetAttemptsStarted ? "1" : "0"
+ ];
+ const result = await this.execCommand(client, "reprocessJob", keys.concat(args));
+ switch (result) {
+ case 1:
+ return;
+ default:
+ throw this.finishedErrors({
+ code: result,
+ jobId: job.id,
+ command: "reprocessJob",
+ state
+ });
+ }
+ }
+ async getMetrics(type, start = 0, end = -1) {
+ const client = await this.queue.client;
+ const keys = [
+ this.queue.toKey(`metrics:${type}`),
+ this.queue.toKey(`metrics:${type}:data`)
+ ];
+ const args = [start, end];
+ const result = await this.execCommand(client, "getMetrics", keys.concat(args));
+ return result;
+ }
+ async moveToActive(client, token, name) {
+ const opts = this.queue.opts;
+ const queueKeys = this.queue.keys;
+ const keys = [
+ queueKeys.wait,
+ queueKeys.active,
+ queueKeys.prioritized,
+ queueKeys.events,
+ queueKeys.stalled,
+ queueKeys.limiter,
+ queueKeys.delayed,
+ queueKeys.paused,
+ queueKeys.meta,
+ queueKeys.pc,
+ queueKeys.marker
+ ];
+ const args = [
+ queueKeys[""],
+ Date.now(),
+ pack2({
+ token,
+ lockDuration: opts.lockDuration,
+ limiter: opts.limiter,
+ name
+ })
+ ];
+ const result = await this.execCommand(client, "moveToActive", keys.concat(args));
+ return raw2NextJobData(result);
+ }
+ async promote(jobId) {
+ const client = await this.queue.client;
+ const keys = [
+ this.queue.keys.delayed,
+ this.queue.keys.wait,
+ this.queue.keys.paused,
+ this.queue.keys.meta,
+ this.queue.keys.prioritized,
+ this.queue.keys.active,
+ this.queue.keys.pc,
+ this.queue.keys.events,
+ this.queue.keys.marker
+ ];
+ const args = [this.queue.toKey(""), jobId];
+ const code = await this.execCommand(client, "promote", keys.concat(args));
+ if (code < 0) {
+ throw this.finishedErrors({
+ code,
+ jobId,
+ command: "promote",
+ state: "delayed"
+ });
+ }
+ }
+ moveStalledJobsToWaitArgs() {
+ const opts = this.queue.opts;
+ const keys = [
+ this.queue.keys.stalled,
+ this.queue.keys.wait,
+ this.queue.keys.active,
+ this.queue.keys["stalled-check"],
+ this.queue.keys.meta,
+ this.queue.keys.paused,
+ this.queue.keys.marker,
+ this.queue.keys.events
+ ];
+ const args = [
+ opts.maxStalledCount,
+ this.queue.toKey(""),
+ Date.now(),
+ opts.stalledInterval
+ ];
+ return keys.concat(args);
+ }
+ async moveStalledJobsToWait() {
+ const client = await this.queue.client;
+ const args = this.moveStalledJobsToWaitArgs();
+ return this.execCommand(client, "moveStalledJobsToWait", args);
+ }
+ async moveJobFromActiveToWait(jobId, token = "0") {
+ const client = await this.queue.client;
+ const keys = [
+ this.queue.keys.active,
+ this.queue.keys.wait,
+ this.queue.keys.stalled,
+ this.queue.keys.paused,
+ this.queue.keys.meta,
+ this.queue.keys.limiter,
+ this.queue.keys.prioritized,
+ this.queue.keys.marker,
+ this.queue.keys.events
+ ];
+ const args = [jobId, token, this.queue.toKey(jobId)];
+ const result = await this.execCommand(client, "moveJobFromActiveToWait", keys.concat(args));
+ if (result < 0) {
+ throw this.finishedErrors({
+ code: result,
+ jobId,
+ command: "moveJobFromActiveToWait",
+ state: "active"
+ });
+ }
+ return result;
+ }
+ async obliterate(opts) {
+ const client = await this.queue.client;
+ const keys = [
+ this.queue.keys.meta,
+ this.queue.toKey("")
+ ];
+ const args = [opts.count, opts.force ? "force" : null];
+ const result = await this.execCommand(client, "obliterate", keys.concat(args));
+ if (result < 0) {
+ switch (result) {
+ case -1:
+ throw new Error("Cannot obliterate non-paused queue");
+ case -2:
+ throw new Error("Cannot obliterate queue with active jobs");
+ }
+ }
+ return result;
+ }
+ async paginate(key, opts) {
+ const client = await this.queue.client;
+ const keys = [key];
+ const maxIterations = 5;
+ const pageSize = opts.end >= 0 ? opts.end - opts.start + 1 : Infinity;
+ let cursor = "0", offset = 0, items, total, rawJobs, page = [], jobs = [];
+ do {
+ const args = [
+ opts.start + page.length,
+ opts.end,
+ cursor,
+ offset,
+ maxIterations
+ ];
+ if (opts.fetchJobs) {
+ args.push(1);
+ }
+ [cursor, offset, items, total, rawJobs] = await this.execCommand(client, "paginate", keys.concat(args));
+ page = page.concat(items);
+ if (rawJobs && rawJobs.length) {
+ jobs = jobs.concat(rawJobs.map(array2obj));
+ }
+ } while (cursor != "0" && page.length < pageSize);
+ if (page.length && Array.isArray(page[0])) {
+ const result = [];
+ for (let index3 = 0;index3 < page.length; index3++) {
+ const [id, value] = page[index3];
+ try {
+ result.push({ id, v: JSON.parse(value) });
+ } catch (err) {
+ result.push({ id, err: err.message });
+ }
+ }
+ return {
+ cursor,
+ items: result,
+ total,
+ jobs
+ };
+ } else {
+ return {
+ cursor,
+ items: page.map((item) => ({ id: item })),
+ total,
+ jobs
+ };
+ }
+ }
+ finishedErrors({ code, jobId, parentKey, command, state }) {
+ let error;
+ switch (code) {
+ case ErrorCode.JobNotExist:
+ error = new Error(`Missing key for job ${jobId}. ${command}`);
+ break;
+ case ErrorCode.JobLockNotExist:
+ error = new Error(`Missing lock for job ${jobId}. ${command}`);
+ break;
+ case ErrorCode.JobNotInState:
+ error = new Error(`Job ${jobId} is not in the ${state} state. ${command}`);
+ break;
+ case ErrorCode.JobPendingChildren:
+ error = new Error(`Job ${jobId} has pending dependencies. ${command}`);
+ break;
+ case ErrorCode.ParentJobNotExist:
+ error = new Error(`Missing key for parent job ${parentKey}. ${command}`);
+ break;
+ case ErrorCode.JobLockMismatch:
+ error = new Error(`Lock mismatch for job ${jobId}. Cmd ${command} from ${state}`);
+ break;
+ case ErrorCode.ParentJobCannotBeReplaced:
+ error = new Error(`The parent job ${parentKey} cannot be replaced. ${command}`);
+ break;
+ case ErrorCode.JobBelongsToJobScheduler:
+ error = new Error(`Job ${jobId} belongs to a job scheduler and cannot be removed directly. ${command}`);
+ break;
+ case ErrorCode.JobHasFailedChildren:
+ error = new UnrecoverableError(`Cannot complete job ${jobId} because it has at least one failed child. ${command}`);
+ break;
+ case ErrorCode.SchedulerJobIdCollision:
+ error = new Error(`Cannot create job scheduler iteration - job ID already exists. ${command}`);
+ break;
+ case ErrorCode.SchedulerJobSlotsBusy:
+ error = new Error(`Cannot create job scheduler iteration - current and next time slots already have jobs. ${command}`);
+ break;
+ default:
+ error = new Error(`Unknown code ${code} error for ${jobId}. ${command}`);
+ }
+ error.code = code;
+ return error;
+ }
+ async removeOrphanedJobs(candidateJobIds, stateKeySuffixes, jobSubKeySuffixes) {
+ const client = await this.queue.client;
+ const args = [
+ this.queue.toKey(""),
+ stateKeySuffixes.length,
+ ...stateKeySuffixes,
+ jobSubKeySuffixes.length,
+ ...jobSubKeySuffixes,
+ ...candidateJobIds
+ ];
+ return this.execCommand(client, "removeOrphanedJobs", args);
+ }
}
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/package.json
-var package_default = {
- name: "@aws-sdk/client-s3",
- description: "AWS SDK for JavaScript S3 Client for Node.js, Browser and React Native",
- version: "3.1032.0",
- scripts: {
- build: "concurrently 'yarn:build:types' 'yarn:build:es' && yarn build:cjs",
- "build:cjs": "node ../../scripts/compilation/inline client-s3",
- "build:es": "tsc -p tsconfig.es.json",
- "build:include:deps": 'yarn g:turbo run build -F="$npm_package_name"',
- "build:types": "tsc -p tsconfig.types.json",
- "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4",
- clean: "premove dist-cjs dist-es dist-types tsconfig.cjs.tsbuildinfo tsconfig.es.tsbuildinfo tsconfig.types.tsbuildinfo",
- "extract:docs": "api-extractor run --local",
- "generate:client": "node ../../scripts/generate-clients/single-service --solo s3",
- test: "yarn g:vitest run",
- "test:browser": "node ./test/browser-build/esbuild && yarn g:vitest run -c vitest.config.browser.mts",
- "test:browser:watch": "node ./test/browser-build/esbuild && yarn g:vitest watch -c vitest.config.browser.mts",
- "test:e2e": "yarn g:vitest run -c vitest.config.e2e.mts && yarn test:browser",
- "test:e2e:watch": "yarn g:vitest watch -c vitest.config.e2e.mts",
- "test:index": "tsc --noEmit ./test/index-types.ts && node ./test/index-objects.spec.mjs",
- "test:integration": "yarn g:vitest run -c vitest.config.integ.mts",
- "test:integration:watch": "yarn g:vitest watch -c vitest.config.integ.mts",
- "test:watch": "yarn g:vitest watch"
- },
- main: "./dist-cjs/index.js",
- types: "./dist-types/index.d.ts",
- module: "./dist-es/index.js",
- sideEffects: false,
- dependencies: {
- "@aws-crypto/sha1-browser": "5.2.0",
- "@aws-crypto/sha256-browser": "5.2.0",
- "@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "^3.974.1",
- "@aws-sdk/credential-provider-node": "^3.972.32",
- "@aws-sdk/middleware-bucket-endpoint": "^3.972.10",
- "@aws-sdk/middleware-expect-continue": "^3.972.10",
- "@aws-sdk/middleware-flexible-checksums": "^3.974.9",
- "@aws-sdk/middleware-host-header": "^3.972.10",
- "@aws-sdk/middleware-location-constraint": "^3.972.10",
- "@aws-sdk/middleware-logger": "^3.972.10",
- "@aws-sdk/middleware-recursion-detection": "^3.972.11",
- "@aws-sdk/middleware-sdk-s3": "^3.972.30",
- "@aws-sdk/middleware-ssec": "^3.972.10",
- "@aws-sdk/middleware-user-agent": "^3.972.31",
- "@aws-sdk/region-config-resolver": "^3.972.12",
- "@aws-sdk/signature-v4-multi-region": "^3.996.18",
- "@aws-sdk/types": "^3.973.8",
- "@aws-sdk/util-endpoints": "^3.996.7",
- "@aws-sdk/util-user-agent-browser": "^3.972.10",
- "@aws-sdk/util-user-agent-node": "^3.973.17",
- "@smithy/config-resolver": "^4.4.16",
- "@smithy/core": "^3.23.15",
- "@smithy/eventstream-serde-browser": "^4.2.14",
- "@smithy/eventstream-serde-config-resolver": "^4.3.14",
- "@smithy/eventstream-serde-node": "^4.2.14",
- "@smithy/fetch-http-handler": "^5.3.17",
- "@smithy/hash-blob-browser": "^4.2.15",
- "@smithy/hash-node": "^4.2.14",
- "@smithy/hash-stream-node": "^4.2.14",
- "@smithy/invalid-dependency": "^4.2.14",
- "@smithy/md5-js": "^4.2.14",
- "@smithy/middleware-content-length": "^4.2.14",
- "@smithy/middleware-endpoint": "^4.4.30",
- "@smithy/middleware-retry": "^4.5.3",
- "@smithy/middleware-serde": "^4.2.18",
- "@smithy/middleware-stack": "^4.2.14",
- "@smithy/node-config-provider": "^4.3.14",
- "@smithy/node-http-handler": "^4.5.3",
- "@smithy/protocol-http": "^5.3.14",
- "@smithy/smithy-client": "^4.12.11",
- "@smithy/types": "^4.14.1",
- "@smithy/url-parser": "^4.2.14",
- "@smithy/util-base64": "^4.3.2",
- "@smithy/util-body-length-browser": "^4.2.2",
- "@smithy/util-body-length-node": "^4.2.3",
- "@smithy/util-defaults-mode-browser": "^4.3.47",
- "@smithy/util-defaults-mode-node": "^4.2.52",
- "@smithy/util-endpoints": "^3.4.1",
- "@smithy/util-middleware": "^4.2.14",
- "@smithy/util-retry": "^4.3.2",
- "@smithy/util-stream": "^4.5.23",
- "@smithy/util-utf8": "^4.2.2",
- "@smithy/util-waiter": "^4.2.16",
- tslib: "^2.6.2"
- },
- devDependencies: {
- "@aws-sdk/signature-v4-crt": "3.1032.0",
- "@smithy/snapshot-testing": "^2.0.6",
- "@tsconfig/node20": "20.1.8",
- "@types/node": "^20.14.8",
- concurrently: "7.0.0",
- "downlevel-dts": "0.10.1",
- premove: "4.0.0",
- typescript: "~5.8.3",
- vitest: "^4.0.17"
- },
- engines: {
- node: ">=20.0.0"
- },
- typesVersions: {
- "<4.5": {
- "dist-types/*": [
- "dist-types/ts3.4/*"
- ]
+function raw2NextJobData(raw) {
+ if (raw) {
+ const result = [null, raw[1], raw[2], raw[3]];
+ if (raw[0]) {
+ result[0] = array2obj(raw[0]);
+ }
+ return result;
+ }
+ return [];
+}
+
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/utils/create-scripts.js
+var createScripts = (queue) => {
+ return new Scripts({
+ keys: queue.keys,
+ client: queue.client,
+ get redisVersion() {
+ return queue.redisVersion;
+ },
+ toKey: queue.toKey,
+ opts: queue.opts,
+ closing: queue.closing,
+ databaseType: queue.databaseType
+ });
+};
+
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/job.js
+var logger = debuglog("bull");
+var PRIORITY_LIMIT = 2 ** 21;
+
+class Job {
+ constructor(queue, name, data, opts = {}, id) {
+ this.queue = queue;
+ this.name = name;
+ this.data = data;
+ this.opts = opts;
+ this.id = id;
+ this.progress = 0;
+ this.returnvalue = null;
+ this.stacktrace = null;
+ this.delay = 0;
+ this.priority = 0;
+ this.attemptsStarted = 0;
+ this.attemptsMade = 0;
+ this.stalledCounter = 0;
+ const _a = this.opts, { repeatJobKey } = _a, restOpts = __rest(_a, ["repeatJobKey"]);
+ this.opts = Object.assign({
+ attempts: 0
+ }, restOpts);
+ this.delay = this.opts.delay;
+ this.priority = this.opts.priority || 0;
+ this.repeatJobKey = repeatJobKey;
+ this.timestamp = opts.timestamp ? opts.timestamp : Date.now();
+ this.opts.backoff = Backoffs.normalize(opts.backoff);
+ this.parentKey = getParentKey(opts.parent);
+ if (opts.parent) {
+ this.parent = { id: opts.parent.id, queueKey: opts.parent.queue };
+ if (opts.failParentOnFailure) {
+ this.parent.fpof = true;
+ }
+ if (opts.removeDependencyOnFailure) {
+ this.parent.rdof = true;
+ }
+ if (opts.ignoreDependencyOnFailure) {
+ this.parent.idof = true;
+ }
+ if (opts.continueParentOnFailure) {
+ this.parent.cpof = true;
+ }
+ }
+ this.debounceId = opts.debounce ? opts.debounce.id : undefined;
+ this.deduplicationId = opts.deduplication ? opts.deduplication.id : this.debounceId;
+ this.toKey = queue.toKey.bind(queue);
+ this.createScripts();
+ this.queueQualifiedName = queue.qualifiedName;
+ }
+ static async create(queue, name, data, opts) {
+ const client = await queue.client;
+ const job = new this(queue, name, data, opts, opts && opts.jobId);
+ job.id = await job.addJob(client, {
+ parentKey: job.parentKey,
+ parentDependenciesKey: job.parentKey ? `${job.parentKey}:dependencies` : ""
+ });
+ return job;
+ }
+ static async createBulk(queue, jobs) {
+ const client = await queue.client;
+ const jobInstances = jobs.map((job) => {
+ var _a;
+ return new this(queue, job.name, job.data, job.opts, (_a = job.opts) === null || _a === undefined ? undefined : _a.jobId);
+ });
+ const pipeline = client.pipeline();
+ for (const job of jobInstances) {
+ job.addJob(pipeline, {
+ parentKey: job.parentKey,
+ parentDependenciesKey: job.parentKey ? `${job.parentKey}:dependencies` : ""
+ });
+ }
+ const results = await pipeline.exec();
+ for (let index3 = 0;index3 < results.length; ++index3) {
+ const [err, id] = results[index3];
+ if (err) {
+ throw err;
+ }
+ jobInstances[index3].id = id;
+ }
+ return jobInstances;
+ }
+ static fromJSON(queue, json3, jobId) {
+ const data = JSON.parse(json3.data || "{}");
+ const opts = Job.optsFromJSON(json3.opts);
+ const job = new this(queue, json3.name, data, opts, json3.id || jobId);
+ job.progress = JSON.parse(json3.progress || "0");
+ job.delay = parseInt(json3.delay);
+ job.priority = parseInt(json3.priority);
+ job.timestamp = parseInt(json3.timestamp);
+ if (json3.finishedOn) {
+ job.finishedOn = parseInt(json3.finishedOn);
+ }
+ if (json3.processedOn) {
+ job.processedOn = parseInt(json3.processedOn);
+ }
+ if (json3.rjk) {
+ job.repeatJobKey = json3.rjk;
+ }
+ if (json3.deid) {
+ job.debounceId = json3.deid;
+ job.deduplicationId = json3.deid;
+ }
+ if (json3.failedReason) {
+ job.failedReason = json3.failedReason;
+ }
+ job.attemptsStarted = parseInt(json3.ats || "0");
+ job.attemptsMade = parseInt(json3.attemptsMade || json3.atm || "0");
+ job.stalledCounter = parseInt(json3.stc || "0");
+ if (json3.defa) {
+ job.deferredFailure = json3.defa;
+ }
+ job.stacktrace = getTraces(json3.stacktrace);
+ if (typeof json3.returnvalue === "string") {
+ job.returnvalue = getReturnValue(json3.returnvalue);
+ }
+ if (json3.parentKey) {
+ job.parentKey = json3.parentKey;
+ }
+ if (json3.parent) {
+ job.parent = JSON.parse(json3.parent);
+ }
+ if (json3.pb) {
+ job.processedBy = json3.pb;
+ }
+ if (json3.nrjid) {
+ job.nextRepeatableJobId = json3.nrjid;
+ }
+ return job;
+ }
+ createScripts() {
+ this.scripts = createScripts(this.queue);
+ }
+ static optsFromJSON(rawOpts, optsDecode = optsDecodeMap) {
+ const opts = JSON.parse(rawOpts || "{}");
+ const optionEntries = Object.entries(opts);
+ const options = {};
+ for (const item of optionEntries) {
+ const [attributeName, value] = item;
+ if (optsDecode[attributeName]) {
+ options[optsDecode[attributeName]] = value;
+ } else {
+ if (attributeName === "tm") {
+ options.telemetry = Object.assign(Object.assign({}, options.telemetry), { metadata: value });
+ } else if (attributeName === "omc") {
+ options.telemetry = Object.assign(Object.assign({}, options.telemetry), { omitContext: value });
+ } else {
+ options[attributeName] = value;
+ }
+ }
+ }
+ return options;
+ }
+ static async fromId(queue, jobId) {
+ if (jobId) {
+ const client = await queue.client;
+ const jobData = await client.hgetall(queue.toKey(jobId));
+ return isEmpty(jobData) ? undefined : this.fromJSON(queue, jobData, jobId);
+ }
+ }
+ static addJobLog(queue, jobId, logRow, keepLogs) {
+ const scripts = queue.scripts;
+ return scripts.addLog(jobId, logRow, keepLogs);
+ }
+ toJSON() {
+ const _a = this, { queue, scripts } = _a, withoutQueueAndScripts = __rest(_a, ["queue", "scripts"]);
+ return withoutQueueAndScripts;
+ }
+ asJSON() {
+ return removeUndefinedFields({
+ id: this.id,
+ name: this.name,
+ data: JSON.stringify(typeof this.data === "undefined" ? {} : this.data),
+ opts: Job.optsAsJSON(this.opts),
+ parent: this.parent ? Object.assign({}, this.parent) : undefined,
+ parentKey: this.parentKey,
+ progress: this.progress,
+ attemptsMade: this.attemptsMade,
+ attemptsStarted: this.attemptsStarted,
+ stalledCounter: this.stalledCounter,
+ finishedOn: this.finishedOn,
+ processedOn: this.processedOn,
+ timestamp: this.timestamp,
+ failedReason: JSON.stringify(this.failedReason),
+ stacktrace: JSON.stringify(this.stacktrace),
+ debounceId: this.debounceId,
+ deduplicationId: this.deduplicationId,
+ repeatJobKey: this.repeatJobKey,
+ returnvalue: JSON.stringify(this.returnvalue),
+ nrjid: this.nextRepeatableJobId
+ });
+ }
+ static optsAsJSON(opts = {}, optsEncode = optsEncodeMap) {
+ const optionEntries = Object.entries(opts);
+ const options = {};
+ for (const [attributeName, value] of optionEntries) {
+ if (typeof value === "undefined") {
+ continue;
+ }
+ if (attributeName in optsEncode) {
+ const compressableAttribute = attributeName;
+ const key = optsEncode[compressableAttribute];
+ options[key] = value;
+ } else {
+ if (attributeName === "telemetry") {
+ if (value.metadata !== undefined) {
+ options.tm = value.metadata;
+ }
+ if (value.omitContext !== undefined) {
+ options.omc = value.omitContext;
+ }
+ } else {
+ options[attributeName] = value;
+ }
+ }
+ }
+ return options;
+ }
+ asJSONSandbox() {
+ return Object.assign(Object.assign({}, this.asJSON()), { queueName: this.queueName, queueQualifiedName: this.queueQualifiedName, prefix: this.prefix });
+ }
+ updateData(data) {
+ this.data = data;
+ return this.scripts.updateData(this, data);
+ }
+ async updateProgress(progress) {
+ this.progress = progress;
+ await this.scripts.updateProgress(this.id, progress);
+ this.queue.emit("progress", this, progress);
+ }
+ async log(logRow) {
+ return Job.addJobLog(this.queue, this.id, logRow, this.opts.keepLogs);
+ }
+ async removeChildDependency() {
+ const childDependencyIsRemoved = await this.scripts.removeChildDependency(this.id, this.parentKey);
+ if (childDependencyIsRemoved) {
+ this.parent = undefined;
+ this.parentKey = undefined;
+ return true;
+ }
+ return false;
+ }
+ async clearLogs(keepLogs) {
+ const client = await this.queue.client;
+ const logsKey = this.toKey(this.id) + ":logs";
+ if (keepLogs) {
+ await client.ltrim(logsKey, -keepLogs, -1);
+ } else {
+ await client.del(logsKey);
+ }
+ }
+ async remove({ removeChildren = true } = {}) {
+ await this.queue.waitUntilReady();
+ const queue = this.queue;
+ const job = this;
+ const removed = await this.scripts.remove(job.id, removeChildren);
+ if (removed) {
+ queue.emit("removed", job);
+ } else {
+ throw new Error(`Job ${this.id} could not be removed because it is locked by another worker`);
+ }
+ }
+ async removeUnprocessedChildren() {
+ const jobId = this.id;
+ await this.scripts.removeUnprocessedChildren(jobId);
+ }
+ extendLock(token, duration) {
+ return this.scripts.extendLock(this.id, token, duration);
+ }
+ async moveToCompleted(returnValue, token, fetchNext = true) {
+ return this.queue.trace(SpanKind.INTERNAL, "complete", this.queue.name, async (span) => {
+ this.setSpanJobAttributes(span);
+ await this.queue.waitUntilReady();
+ this.returnvalue = returnValue || undefined;
+ const stringifiedReturnValue = tryCatch(JSON.stringify, JSON, [
+ returnValue
+ ]);
+ if (stringifiedReturnValue === errorObject) {
+ throw errorObject.value;
+ }
+ const args = this.scripts.moveToCompletedArgs(this, stringifiedReturnValue, this.opts.removeOnComplete, token, fetchNext);
+ const result = await this.scripts.moveToFinished(this.id, args);
+ this.finishedOn = args[this.scripts.moveToFinishedKeys.length + 1];
+ this.attemptsMade += 1;
+ this.recordJobMetrics("completed");
+ return result;
+ });
+ }
+ async moveToWait(token) {
+ const result = await this.scripts.moveJobFromActiveToWait(this.id, token);
+ this.recordJobMetrics("waiting");
+ return result;
+ }
+ async shouldRetryJob(err) {
+ if (this.attemptsMade + 1 < this.opts.attempts && !this.discarded && !(err instanceof UnrecoverableError || err.name == "UnrecoverableError")) {
+ const opts = this.queue.opts;
+ const delay2 = await Backoffs.calculate(this.opts.backoff, this.attemptsMade + 1, err, this, opts.settings && opts.settings.backoffStrategy);
+ return [delay2 == -1 ? false : true, delay2 == -1 ? 0 : delay2];
+ } else {
+ return [false, 0];
+ }
+ }
+ async moveToFailed(err, token, fetchNext = false) {
+ this.failedReason = err === null || err === undefined ? undefined : err.message;
+ const [shouldRetry, retryDelay] = await this.shouldRetryJob(err);
+ return this.queue.trace(SpanKind.INTERNAL, this.getSpanOperation(shouldRetry, retryDelay), this.queue.name, async (span, dstPropagationMetadata) => {
+ var _a, _b;
+ this.setSpanJobAttributes(span);
+ let tm;
+ if (!((_b = (_a = this.opts) === null || _a === undefined ? undefined : _a.telemetry) === null || _b === undefined ? undefined : _b.omitContext) && dstPropagationMetadata) {
+ tm = dstPropagationMetadata;
+ }
+ let result;
+ this.updateStacktrace(err);
+ const fieldsToUpdate = {
+ failedReason: this.failedReason,
+ stacktrace: JSON.stringify(this.stacktrace),
+ tm
+ };
+ let finishedOn;
+ if (shouldRetry) {
+ if (retryDelay) {
+ result = await this.scripts.moveToDelayed(this.id, Date.now(), retryDelay, token, { fieldsToUpdate, fetchNext });
+ this.recordJobMetrics("delayed");
+ } else {
+ result = await this.scripts.retryJob(this.id, this.opts.lifo, token, {
+ fieldsToUpdate
+ });
+ this.recordJobMetrics("retried");
+ }
+ } else {
+ const args = this.scripts.moveToFailedArgs(this, this.failedReason, this.opts.removeOnFail, token, fetchNext, fieldsToUpdate);
+ result = await this.scripts.moveToFinished(this.id, args);
+ finishedOn = args[this.scripts.moveToFinishedKeys.length + 1];
+ this.recordJobMetrics("failed");
+ }
+ if (finishedOn && typeof finishedOn === "number") {
+ this.finishedOn = finishedOn;
+ }
+ if (retryDelay && typeof retryDelay === "number") {
+ this.delay = retryDelay;
+ }
+ this.attemptsMade += 1;
+ return result;
+ });
+ }
+ getSpanOperation(shouldRetry, retryDelay) {
+ if (shouldRetry) {
+ if (retryDelay) {
+ return "delay";
+ }
+ return "retry";
+ }
+ return "fail";
+ }
+ recordJobMetrics(status) {
+ var _a, _b;
+ const meter = (_b = (_a = this.queue.opts) === null || _a === undefined ? undefined : _a.telemetry) === null || _b === undefined ? undefined : _b.meter;
+ if (!meter) {
+ return;
+ }
+ const attributes = {
+ [TelemetryAttributes.QueueName]: this.queue.name,
+ [TelemetryAttributes.JobName]: this.name,
+ [TelemetryAttributes.JobStatus]: status
+ };
+ const statusToCounterName = {
+ completed: MetricNames.JobsCompleted,
+ failed: MetricNames.JobsFailed,
+ delayed: MetricNames.JobsDelayed,
+ retried: MetricNames.JobsRetried,
+ waiting: MetricNames.JobsWaiting,
+ "waiting-children": MetricNames.JobsWaitingChildren
+ };
+ const counterName = statusToCounterName[status];
+ const counter = meter.createCounter(counterName, {
+ description: `Number of jobs ${status}`,
+ unit: "1"
+ });
+ counter.add(1, attributes);
+ if (this.processedOn) {
+ const duration = Date.now() - this.processedOn;
+ const histogram = meter.createHistogram(MetricNames.JobDuration, {
+ description: "Job processing duration",
+ unit: "ms"
+ });
+ histogram.record(duration, attributes);
+ }
+ }
+ isCompleted() {
+ return this.isInZSet("completed");
+ }
+ isFailed() {
+ return this.isInZSet("failed");
+ }
+ isDelayed() {
+ return this.isInZSet("delayed");
+ }
+ isWaitingChildren() {
+ return this.isInZSet("waiting-children");
+ }
+ isActive() {
+ return this.isInList("active");
+ }
+ async isWaiting() {
+ return await this.isInList("wait") || await this.isInList("paused");
+ }
+ get queueName() {
+ return this.queue.name;
+ }
+ get prefix() {
+ return this.queue.opts.prefix;
+ }
+ getState() {
+ return this.scripts.getState(this.id);
+ }
+ async changeDelay(delay2) {
+ await this.scripts.changeDelay(this.id, delay2);
+ this.delay = delay2;
+ }
+ async changePriority(opts) {
+ await this.scripts.changePriority(this.id, opts.priority, opts.lifo);
+ this.priority = opts.priority || 0;
+ }
+ async getChildrenValues() {
+ const client = await this.queue.client;
+ const result = await client.hgetall(this.toKey(`${this.id}:processed`));
+ if (result) {
+ return parseObjectValues(result);
+ }
+ }
+ async getIgnoredChildrenFailures() {
+ const client = await this.queue.client;
+ return client.hgetall(this.toKey(`${this.id}:failed`));
+ }
+ async getFailedChildrenValues() {
+ const client = await this.queue.client;
+ return client.hgetall(this.toKey(`${this.id}:failed`));
+ }
+ async getDependencies(opts = {}) {
+ const client = await this.queue.client;
+ const multi = client.multi();
+ if (!opts.processed && !opts.unprocessed && !opts.ignored && !opts.failed) {
+ multi.hgetall(this.toKey(`${this.id}:processed`));
+ multi.smembers(this.toKey(`${this.id}:dependencies`));
+ multi.hgetall(this.toKey(`${this.id}:failed`));
+ multi.zrange(this.toKey(`${this.id}:unsuccessful`), 0, -1);
+ const [[err1, processed], [err2, unprocessed], [err3, ignored], [err4, failed]] = await multi.exec();
+ return {
+ processed: parseObjectValues(processed),
+ unprocessed,
+ failed,
+ ignored
+ };
+ } else {
+ const defaultOpts = {
+ cursor: 0,
+ count: 20
+ };
+ const childrenResultOrder = [];
+ if (opts.processed) {
+ childrenResultOrder.push("processed");
+ const processedOpts = Object.assign(Object.assign({}, defaultOpts), opts.processed);
+ multi.hscan(this.toKey(`${this.id}:processed`), processedOpts.cursor, "COUNT", processedOpts.count);
+ }
+ if (opts.unprocessed) {
+ childrenResultOrder.push("unprocessed");
+ const unprocessedOpts = Object.assign(Object.assign({}, defaultOpts), opts.unprocessed);
+ multi.sscan(this.toKey(`${this.id}:dependencies`), unprocessedOpts.cursor, "COUNT", unprocessedOpts.count);
+ }
+ if (opts.ignored) {
+ childrenResultOrder.push("ignored");
+ const ignoredOpts = Object.assign(Object.assign({}, defaultOpts), opts.ignored);
+ multi.hscan(this.toKey(`${this.id}:failed`), ignoredOpts.cursor, "COUNT", ignoredOpts.count);
+ }
+ let failedCursor;
+ if (opts.failed) {
+ childrenResultOrder.push("failed");
+ const failedOpts = Object.assign(Object.assign({}, defaultOpts), opts.failed);
+ failedCursor = failedOpts.cursor + failedOpts.count;
+ multi.zrange(this.toKey(`${this.id}:unsuccessful`), failedOpts.cursor, failedOpts.count - 1);
+ }
+ const results = await multi.exec();
+ let processedCursor, processed, unprocessedCursor, unprocessed, failed, ignoredCursor, ignored;
+ childrenResultOrder.forEach((key, index3) => {
+ switch (key) {
+ case "processed": {
+ processedCursor = results[index3][1][0];
+ const rawProcessed = results[index3][1][1];
+ const transformedProcessed = {};
+ for (let ind = 0;ind < rawProcessed.length; ++ind) {
+ if (ind % 2) {
+ transformedProcessed[rawProcessed[ind - 1]] = JSON.parse(rawProcessed[ind]);
+ }
+ }
+ processed = transformedProcessed;
+ break;
+ }
+ case "failed": {
+ failed = results[index3][1];
+ break;
+ }
+ case "ignored": {
+ ignoredCursor = results[index3][1][0];
+ const rawIgnored = results[index3][1][1];
+ const transformedIgnored = {};
+ for (let ind = 0;ind < rawIgnored.length; ++ind) {
+ if (ind % 2) {
+ transformedIgnored[rawIgnored[ind - 1]] = rawIgnored[ind];
+ }
+ }
+ ignored = transformedIgnored;
+ break;
+ }
+ case "unprocessed": {
+ unprocessedCursor = results[index3][1][0];
+ unprocessed = results[index3][1][1];
+ break;
+ }
+ }
+ });
+ return Object.assign(Object.assign(Object.assign(Object.assign({}, processedCursor ? {
+ processed,
+ nextProcessedCursor: Number(processedCursor)
+ } : {}), ignoredCursor ? {
+ ignored,
+ nextIgnoredCursor: Number(ignoredCursor)
+ } : {}), failedCursor ? {
+ failed,
+ nextFailedCursor: failedCursor
+ } : {}), unprocessedCursor ? { unprocessed, nextUnprocessedCursor: Number(unprocessedCursor) } : {});
+ }
+ }
+ async getDependenciesCount(opts = {}) {
+ const types6 = [];
+ Object.entries(opts).forEach(([key, value]) => {
+ if (value) {
+ types6.push(key);
+ }
+ });
+ const finalTypes = types6.length ? types6 : ["processed", "unprocessed", "ignored", "failed"];
+ const responses = await this.scripts.getDependencyCounts(this.id, finalTypes);
+ const counts = {};
+ responses.forEach((res, index3) => {
+ counts[`${finalTypes[index3]}`] = res || 0;
+ });
+ return counts;
+ }
+ async waitUntilFinished(queueEvents, ttl) {
+ await this.queue.waitUntilReady();
+ const jobId = this.id;
+ return new Promise(async (resolve, reject) => {
+ let timeout;
+ if (ttl) {
+ timeout = setTimeout(() => onFailed(`Job wait ${this.name} timed out before finishing, no finish notification arrived after ${ttl}ms (id=${jobId})`), ttl);
+ }
+ function onCompleted(args) {
+ removeListeners();
+ resolve(args.returnvalue);
+ }
+ function onFailed(args) {
+ removeListeners();
+ reject(new Error(args.failedReason || args));
+ }
+ const completedEvent = `completed:${jobId}`;
+ const failedEvent = `failed:${jobId}`;
+ queueEvents.on(completedEvent, onCompleted);
+ queueEvents.on(failedEvent, onFailed);
+ this.queue.on("closing", onFailed);
+ const removeListeners = () => {
+ clearInterval(timeout);
+ queueEvents.removeListener(completedEvent, onCompleted);
+ queueEvents.removeListener(failedEvent, onFailed);
+ this.queue.removeListener("closing", onFailed);
+ };
+ await queueEvents.waitUntilReady();
+ const [status, result] = await this.scripts.isFinished(jobId, true);
+ const finished = status != 0;
+ if (finished) {
+ if (status == -1 || status == 2) {
+ onFailed({ failedReason: result });
+ } else {
+ onCompleted({ returnvalue: getReturnValue(result) });
+ }
+ }
+ });
+ }
+ async moveToDelayed(timestamp3, token) {
+ const now = Date.now();
+ const delay2 = timestamp3 - now;
+ const finalDelay = delay2 > 0 ? delay2 : 0;
+ await this.scripts.moveToDelayed(this.id, now, finalDelay, token, {
+ skipAttempt: true
+ });
+ this.delay = finalDelay;
+ this.recordJobMetrics("delayed");
+ }
+ async moveToWaitingChildren(token, opts = {}) {
+ const movedToWaitingChildren = await this.scripts.moveToWaitingChildren(this.id, token, opts);
+ if (movedToWaitingChildren) {
+ this.recordJobMetrics("waiting-children");
+ }
+ return movedToWaitingChildren;
+ }
+ async promote() {
+ const jobId = this.id;
+ await this.scripts.promote(jobId);
+ this.delay = 0;
+ }
+ async retry(state = "failed", opts = {}) {
+ await this.scripts.reprocessJob(this, state, opts);
+ this.failedReason = null;
+ this.finishedOn = null;
+ this.processedOn = null;
+ this.returnvalue = null;
+ if (opts.resetAttemptsMade) {
+ this.attemptsMade = 0;
+ }
+ if (opts.resetAttemptsStarted) {
+ this.attemptsStarted = 0;
+ }
+ }
+ discard() {
+ this.discarded = true;
+ }
+ async isInZSet(set) {
+ const client = await this.queue.client;
+ const score = await client.zscore(this.queue.toKey(set), this.id);
+ return score !== null;
+ }
+ async isInList(list) {
+ return this.scripts.isJobInList(this.queue.toKey(list), this.id);
+ }
+ addJob(client, parentOpts) {
+ const jobData = this.asJSON();
+ this.validateOptions(jobData);
+ return this.scripts.addJob(client, jobData, jobData.opts, this.id, parentOpts);
+ }
+ async removeDeduplicationKey() {
+ if (this.deduplicationId) {
+ const result = await this.scripts.removeDeduplicationKey(this.deduplicationId, this.id);
+ return result > 0;
+ }
+ return false;
+ }
+ validateOptions(jobData) {
+ var _a, _b, _c2, _d2, _e2, _f, _g, _h2;
+ const exclusiveOptions = [
+ "removeDependencyOnFailure",
+ "failParentOnFailure",
+ "continueParentOnFailure",
+ "ignoreDependencyOnFailure"
+ ];
+ const exceedLimit = this.opts.sizeLimit && lengthInUtf8Bytes(jobData.data) > this.opts.sizeLimit;
+ if (exceedLimit) {
+ throw new Error(`The size of job ${this.name} exceeds the limit ${this.opts.sizeLimit} bytes`);
+ }
+ if (this.opts.delay && this.opts.repeat && !((_a = this.opts.repeat) === null || _a === undefined ? undefined : _a.count)) {
+ throw new Error(`Delay and repeat options cannot be used together`);
+ }
+ const enabledExclusiveOptions = exclusiveOptions.filter((opt) => this.opts[opt]);
+ if (enabledExclusiveOptions.length > 1) {
+ const optionsList = enabledExclusiveOptions.join(", ");
+ throw new Error(`The following options cannot be used together: ${optionsList}`);
+ }
+ if ((_b = this.opts) === null || _b === undefined ? undefined : _b.jobId) {
+ if (`${parseInt(this.opts.jobId, 10)}` === ((_c2 = this.opts) === null || _c2 === undefined ? undefined : _c2.jobId)) {
+ throw new Error("Custom Id cannot be integers");
+ }
+ if (((_d2 = this.opts) === null || _d2 === undefined ? undefined : _d2.jobId.includes(":")) && ((_f = (_e2 = this.opts) === null || _e2 === undefined ? undefined : _e2.jobId) === null || _f === undefined ? undefined : _f.split(":").length) !== 3) {
+ throw new Error("Custom Id cannot contain :");
+ }
+ }
+ if (this.opts.priority) {
+ if (Math.trunc(this.opts.priority) !== this.opts.priority) {
+ throw new Error(`Priority should not be float`);
+ }
+ if (this.opts.priority > PRIORITY_LIMIT) {
+ throw new Error(`Priority should be between 0 and ${PRIORITY_LIMIT}`);
+ }
+ }
+ if (this.opts.deduplication) {
+ if (!((_g = this.opts.deduplication) === null || _g === undefined ? undefined : _g.id)) {
+ throw new Error("Deduplication id must be provided");
+ }
+ if (this.parentKey) {
+ throw new Error("Deduplication and parent options cannot be used together");
+ }
+ }
+ if (this.opts.debounce) {
+ if (!((_h2 = this.opts.debounce) === null || _h2 === undefined ? undefined : _h2.id)) {
+ throw new Error("Debounce id must be provided");
+ }
+ if (this.parentKey) {
+ throw new Error("Debounce and parent options cannot be used together");
+ }
+ }
+ if (typeof this.opts.backoff === "object" && typeof this.opts.backoff.jitter === "number") {
+ if (this.opts.backoff.jitter < 0 || this.opts.backoff.jitter > 1) {
+ throw new Error(`Jitter should be between 0 and 1`);
+ }
+ }
+ }
+ updateStacktrace(err) {
+ this.stacktrace = this.stacktrace || [];
+ if (err === null || err === undefined ? undefined : err.stack) {
+ this.stacktrace.push(err.stack);
+ if (this.opts.stackTraceLimit === 0) {
+ this.stacktrace = [];
+ } else if (this.opts.stackTraceLimit) {
+ this.stacktrace = this.stacktrace.slice(-this.opts.stackTraceLimit);
+ }
+ }
+ }
+ setSpanJobAttributes(span) {
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.JobName]: this.name,
+ [TelemetryAttributes.JobId]: this.id
+ });
+ }
+}
+function getTraces(stacktrace) {
+ if (!stacktrace) {
+ return [];
+ }
+ const traces = tryCatch(JSON.parse, JSON, [stacktrace]);
+ if (traces === errorObject || !(traces instanceof Array)) {
+ return [];
+ } else {
+ return traces;
+ }
+}
+function getReturnValue(_value) {
+ const value = tryCatch(JSON.parse, JSON, [_value]);
+ if (value !== errorObject) {
+ return value;
+ } else {
+ logger("corrupted returnvalue: " + _value, value);
+ }
+}
+
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/queue-keys.js
+class QueueKeys {
+ constructor(prefix = "bull") {
+ this.prefix = prefix;
+ }
+ getKeys(name) {
+ const keys = {};
+ [
+ "",
+ "active",
+ "wait",
+ "waiting-children",
+ "paused",
+ "id",
+ "delayed",
+ "prioritized",
+ "stalled-check",
+ "completed",
+ "failed",
+ "stalled",
+ "repeat",
+ "limiter",
+ "meta",
+ "events",
+ "pc",
+ "marker",
+ "de"
+ ].forEach((key) => {
+ keys[key] = this.toKey(name, key);
+ });
+ return keys;
+ }
+ toKey(name, type) {
+ return `${this.getQueueQualifiedName(name)}:${type}`;
+ }
+ getQueueQualifiedName(name) {
+ return `${this.prefix}:${name}`;
+ }
+}
+
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/redis-connection.js
+var import_ioredis3 = __toESM(require_built3(), 1);
+var import_utils58 = __toESM(require_utils7(), 1);
+import { EventEmitter } from "events";
+
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/index.js
+var exports_scripts = {};
+__export(exports_scripts, {
+ updateRepeatableJobMillis: () => updateRepeatableJobMillis,
+ updateProgress: () => updateProgress,
+ updateJobScheduler: () => updateJobScheduler,
+ updateData: () => updateData,
+ saveStacktrace: () => saveStacktrace,
+ retryJob: () => retryJob,
+ reprocessJob: () => reprocessJob,
+ removeUnprocessedChildren: () => removeUnprocessedChildren,
+ removeRepeatable: () => removeRepeatable,
+ removeOrphanedJobs: () => removeOrphanedJobs,
+ removeJobScheduler: () => removeJobScheduler,
+ removeJob: () => removeJob,
+ removeDeduplicationKey: () => removeDeduplicationKey,
+ removeChildDependency: () => removeChildDependency,
+ releaseLock: () => releaseLock,
+ promote: () => promote,
+ pause: () => pause,
+ paginate: () => paginate,
+ obliterate: () => obliterate,
+ moveToWaitingChildren: () => moveToWaitingChildren,
+ moveToFinished: () => moveToFinished,
+ moveToDelayed: () => moveToDelayed,
+ moveToActive: () => moveToActive,
+ moveStalledJobsToWait: () => moveStalledJobsToWait,
+ moveJobsToWait: () => moveJobsToWait,
+ moveJobFromActiveToWait: () => moveJobFromActiveToWait,
+ isMaxed: () => isMaxed,
+ isJobInList: () => isJobInList,
+ isFinished: () => isFinished,
+ getStateV2: () => getStateV2,
+ getState: () => getState,
+ getRateLimitTtl: () => getRateLimitTtl,
+ getRanges: () => getRanges,
+ getMetrics: () => getMetrics,
+ getJobScheduler: () => getJobScheduler,
+ getDependencyCounts: () => getDependencyCounts,
+ getCountsPerPriority: () => getCountsPerPriority,
+ getCounts: () => getCounts,
+ extendLocks: () => extendLocks,
+ extendLock: () => extendLock,
+ drain: () => drain,
+ cleanJobsInSet: () => cleanJobsInSet,
+ changePriority: () => changePriority,
+ changeDelay: () => changeDelay,
+ addStandardJob: () => addStandardJob,
+ addRepeatableJob: () => addRepeatableJob,
+ addPrioritizedJob: () => addPrioritizedJob,
+ addParentJob: () => addParentJob,
+ addLog: () => addLog,
+ addJobScheduler: () => addJobScheduler,
+ addDelayedJob: () => addDelayedJob
+});
+
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/addDelayedJob-6.js
+var content = `--[[
+ Adds a delayed job to the queue by doing the following:
+ - Increases the job counter if needed.
+ - Creates a new job key with the job data.
+ - computes timestamp.
+ - adds to delayed zset.
+ - Emits a global event 'delayed' if the job is delayed.
+ Input:
+ KEYS[1] 'marker',
+ KEYS[2] 'meta'
+ KEYS[3] 'id'
+ KEYS[4] 'delayed'
+ KEYS[5] 'completed'
+ KEYS[6] events stream key
+ ARGV[1] msgpacked arguments array
+ [1] key prefix,
+ [2] custom id (use custom instead of one generated automatically)
+ [3] name
+ [4] timestamp
+ [5] parentKey?
+ [6] parent dependencies key.
+ [7] parent? {id, queueKey}
+ [8] repeat job key
+ [9] deduplication key
+ ARGV[2] Json stringified job data
+ ARGV[3] msgpacked options
+ Output:
+ jobId - OK
+ -5 - Missing parent key
+]]
+local metaKey = KEYS[2]
+local idKey = KEYS[3]
+local delayedKey = KEYS[4]
+local completedKey = KEYS[5]
+local eventsKey = KEYS[6]
+local jobId
+local jobIdKey
+local rcall = redis.call
+local args = cmsgpack.unpack(ARGV[1])
+local data = ARGV[2]
+local parentKey = args[5]
+local parent = args[7]
+local repeatJobKey = args[8]
+local deduplicationKey = args[9]
+local parentData
+-- Includes
+--[[
+ Adds a delayed job to the queue by doing the following:
+ - Creates a new job key with the job data.
+ - adds to delayed zset.
+ - Emits a global event 'delayed' if the job is delayed.
+]]
+-- Includes
+--[[
+ Add delay marker if needed.
+]]
+-- Includes
+--[[
+ Function to return the next delayed job timestamp.
+]]
+local function getNextDelayedTimestamp(delayedKey)
+ local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
+ if #result then
+ local nextTimestamp = tonumber(result[2])
+ if nextTimestamp ~= nil then
+ return nextTimestamp / 0x1000
+ end
+ end
+end
+local function addDelayMarkerIfNeeded(markerKey, delayedKey)
+ local nextTimestamp = getNextDelayedTimestamp(delayedKey)
+ if nextTimestamp ~= nil then
+ -- Replace the score of the marker with the newest known
+ -- next timestamp.
+ rcall("ZADD", markerKey, nextTimestamp, "1")
+ end
+end
+--[[
+ Bake in the job id first 12 bits into the timestamp
+ to guarantee correct execution order of delayed jobs
+ (up to 4096 jobs per given timestamp or 4096 jobs apart per timestamp)
+ WARNING: Jobs that are so far apart that they wrap around will cause FIFO to fail
+]]
+local function getDelayedScore(delayedKey, timestamp, delay)
+ local delayedTimestamp = (delay > 0 and (tonumber(timestamp) + delay)) or tonumber(timestamp)
+ local minScore = delayedTimestamp * 0x1000
+ local maxScore = (delayedTimestamp + 1 ) * 0x1000 - 1
+ local result = rcall("ZREVRANGEBYSCORE", delayedKey, maxScore,
+ minScore, "WITHSCORES","LIMIT", 0, 1)
+ if #result then
+ local currentMaxScore = tonumber(result[2])
+ if currentMaxScore ~= nil then
+ if currentMaxScore >= maxScore then
+ return maxScore, delayedTimestamp
+ else
+ return currentMaxScore + 1, delayedTimestamp
+ end
+ end
+ end
+ return minScore, delayedTimestamp
+end
+local function addDelayedJob(jobId, delayedKey, eventsKey, timestamp,
+ maxEvents, markerKey, delay)
+ local score, delayedTimestamp = getDelayedScore(delayedKey, timestamp, tonumber(delay))
+ rcall("ZADD", delayedKey, score, jobId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "delayed",
+ "jobId", jobId, "delay", delayedTimestamp)
+ -- mark that a delayed job is available
+ addDelayMarkerIfNeeded(markerKey, delayedKey)
+end
+--[[
+ Function to debounce a job.
+]]
+-- Includes
+--[[
+ Function to deduplicate a job.
+]]
+--[[
+ Function to set the deduplication key for a job.
+ Uses TTL from deduplication opts if provided.
+]]
+local function setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ local ttl = deduplicationOpts and deduplicationOpts['ttl']
+ if ttl and ttl > 0 then
+ rcall('SET', deduplicationKey, jobId, 'PX', ttl)
+ else
+ rcall('SET', deduplicationKey, jobId)
+ end
+end
+--[[
+ Function to store a deduplicated next job if the existing job is active
+ and keepLastIfActive is set. When the active job finishes, the stored
+ proto-job is used to create a real job in the queue.
+ Returns true if the proto-job was stored, false otherwise.
+]]
+--[[
+ Function to check if an item belongs to a list.
+]]
+local function checkItemInList(list, item)
+ for _, v in pairs(list) do
+ if v == item then
+ return 1
+ end
+ end
+ return nil
+end
+local function storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ if deduplicationOpts['keepLastIfActive'] and currentDebounceJobId then
+ local activeKey = prefix .. "active"
+ local activeItems = rcall('LRANGE', activeKey, 0, -1)
+ if checkItemInList(activeItems, currentDebounceJobId) then
+ local deduplicationNextKey = prefix .. "dn:" .. deduplicationId
+ local fields = {'name', jobName, 'data', jobData, 'opts', cjson.encode(fullOpts)}
+ if parentKey then
+ fields[#fields+1] = 'pk'
+ fields[#fields+1] = parentKey
+ end
+ if parentData then
+ fields[#fields+1] = 'pd'
+ fields[#fields+1] = parentData
+ end
+ if parentDependenciesKey then
+ fields[#fields+1] = 'pdk'
+ fields[#fields+1] = parentDependenciesKey
+ end
+ if repeatJobKey then
+ fields[#fields+1] = 'rjk'
+ fields[#fields+1] = repeatJobKey
+ end
+ rcall('HSET', deduplicationNextKey, unpack(fields))
+ -- Ensure the dedup key does not expire while the job is active,
+ -- so subsequent adds always hit the dedup path and never bypass
+ -- the active-check because of a TTL expiry.
+ local deduplicationKey = prefix .. "de:" .. deduplicationId
+ rcall('PERSIST', deduplicationKey)
+ -- TODO remove debounced event in next breaking change
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced", "jobId",
+ currentDebounceJobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ currentDebounceJobId, "deduplicationId", deduplicationId, "deduplicatedJobId", jobId)
+ return true
+ end
+ end
+ return false
+end
+local function deduplicateJobWithoutReplace(deduplicationId, deduplicationOpts, jobId, deduplicationKey,
+ eventsKey, maxEvents, prefix, jobName, jobData, fullOpts,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ local ttl = deduplicationOpts['ttl']
+ local deduplicationKeyExists
+ if ttl and ttl > 0 then
+ if deduplicationOpts['extend'] then
+ local currentDebounceJobId = rcall('GET', deduplicationKey)
+ if currentDebounceJobId then
+ if storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey) then
+ return currentDebounceJobId
+ end
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, currentDebounceJobId)
+ else
+ setDeduplicationKey(deduplicationKey, currentDebounceJobId, deduplicationOpts)
+ end
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced",
+ "jobId", currentDebounceJobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ currentDebounceJobId, "deduplicationId", deduplicationId, "deduplicatedJobId", jobId)
+ return currentDebounceJobId
+ else
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, jobId)
+ else
+ setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ end
+ return
+ end
+ else
+ if deduplicationOpts['keepLastIfActive'] then
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'NX')
+ else
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'PX', ttl, 'NX')
+ end
+ end
+ else
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'NX')
+ end
+ if deduplicationKeyExists then
+ local currentDebounceJobId = rcall('GET', deduplicationKey)
+ if storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey) then
+ return currentDebounceJobId
+ end
+ -- TODO remove debounced event in next breaking change
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced", "jobId",
+ currentDebounceJobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ currentDebounceJobId, "deduplicationId", deduplicationId, "deduplicatedJobId", jobId)
+ return currentDebounceJobId
+ end
+end
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+local function removeDelayedJob(delayedKey, deduplicationKey, eventsKey, maxEvents, currentDeduplicatedJobId,
+ jobId, deduplicationId, prefix)
+ if rcall("ZREM", delayedKey, currentDeduplicatedJobId) > 0 then
+ removeJobKeys(prefix .. currentDeduplicatedJobId)
+ rcall("XADD", eventsKey, "*", "event", "removed", "jobId", currentDeduplicatedJobId,
+ "prev", "delayed")
+ -- TODO remove debounced event in next breaking change
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced", "jobId",
+ jobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ jobId, "deduplicationId", deduplicationId, "deduplicatedJobId", currentDeduplicatedJobId)
+ return true
+ end
+ return false
+end
+local function deduplicateJob(deduplicationOpts, jobId, delayedKey, deduplicationKey, eventsKey, maxEvents,
+ prefix, jobName, jobData, fullOpts, parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ local deduplicationId = deduplicationOpts and deduplicationOpts['id']
+ if deduplicationId then
+ if deduplicationOpts['replace'] then
+ local currentDebounceJobId = rcall('GET', deduplicationKey)
+ if currentDebounceJobId then
+ local isRemoved = removeDelayedJob(delayedKey, deduplicationKey, eventsKey, maxEvents,
+ currentDebounceJobId, jobId, deduplicationId, prefix)
+ if isRemoved then
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, jobId)
+ else
+ local ttl = deduplicationOpts['ttl']
+ if not deduplicationOpts['extend'] and ttl and ttl > 0 then
+ rcall('SET', deduplicationKey, jobId, 'KEEPTTL')
+ else
+ setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ end
+ end
+ return
+ else
+ storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ return currentDebounceJobId
+ end
+ else
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, jobId)
+ else
+ setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ end
+ return
+ end
+ else
+ return deduplicateJobWithoutReplace(deduplicationId, deduplicationOpts,
+ jobId, deduplicationKey, eventsKey, maxEvents, prefix, jobName, jobData, fullOpts,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ end
+ end
+end
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+--[[
+ Function to handle the case when job is duplicated.
+]]
+-- Includes
+--[[
+ This function is used to update the parent's dependencies if the job
+ is already completed and about to be ignored. The parent must get its
+ dependencies updated to avoid the parent job being stuck forever in
+ the waiting-children state.
+]]
+-- Includes
+--[[
+ Validate and move or add dependencies to parent.
+]]
+-- Includes
+--[[
+ Validate and move parent to a wait status (waiting, delayed or prioritized)
+ if no pending dependencies.
+]]
+-- Includes
+--[[
+ Validate and move parent to a wait status (waiting, delayed or prioritized) if needed.
+]]
+-- Includes
+--[[
+ Move parent to a wait status (wait, prioritized or delayed)
+]]
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to add job considering priority.
+]]
+-- Includes
+--[[
+ Function to get priority score.
+]]
+local function getPriorityScore(priority, priorityCounterKey)
+ local prioCounter = rcall("INCR", priorityCounterKey)
+ return priority * 0x100000000 + prioCounter % 0x100000000
+end
+local function addJobWithPriority(markerKey, prioritizedKey, priority, jobId, priorityCounterKey,
+ isPausedOrMaxed)
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to check if queue is paused or maxed
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function isQueuePausedOrMaxed(queueMetaKey, activeKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency")
+ if queueAttributes[1] then
+ return true
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ return activeCount >= tonumber(queueAttributes[2])
+ end
+ end
+ return false
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+local function moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
+ local parentWaitKey = parentQueueKey .. ":wait"
+ local parentPausedKey = parentQueueKey .. ":paused"
+ local parentActiveKey = parentQueueKey .. ":active"
+ local parentMetaKey = parentQueueKey .. ":meta"
+ local parentMarkerKey = parentQueueKey .. ":marker"
+ local jobAttributes = rcall("HMGET", parentKey, "priority", "delay")
+ local priority = tonumber(jobAttributes[1]) or 0
+ local delay = tonumber(jobAttributes[2]) or 0
+ if delay > 0 then
+ local delayedTimestamp = tonumber(timestamp) + delay
+ local score = delayedTimestamp * 0x1000
+ local parentDelayedKey = parentQueueKey .. ":delayed"
+ rcall("ZADD", parentDelayedKey, score, parentId)
+ rcall("XADD", parentQueueKey .. ":events", "*", "event", "delayed", "jobId", parentId, "delay",
+ delayedTimestamp)
+ addDelayMarkerIfNeeded(parentMarkerKey, parentDelayedKey)
+ else
+ if priority == 0 then
+ local parentTarget, isParentPausedOrMaxed = getTargetQueueList(parentMetaKey, parentActiveKey,
+ parentWaitKey, parentPausedKey)
+ addJobInTargetList(parentTarget, parentMarkerKey, "RPUSH", isParentPausedOrMaxed, parentId)
+ else
+ local isPausedOrMaxed = isQueuePausedOrMaxed(parentMetaKey, parentActiveKey)
+ addJobWithPriority(parentMarkerKey, parentQueueKey .. ":prioritized", priority, parentId,
+ parentQueueKey .. ":pc", isPausedOrMaxed)
+ end
+ rcall("XADD", parentQueueKey .. ":events", "*", "event", "waiting", "jobId", parentId, "prev",
+ "waiting-children")
+ end
+end
+local function moveParentToWaitIfNeeded(parentQueueKey, parentKey, parentId, timestamp)
+ if rcall("EXISTS", parentKey) == 1 then
+ local parentWaitingChildrenKey = parentQueueKey .. ":waiting-children"
+ if rcall("ZSCORE", parentWaitingChildrenKey, parentId) then
+ rcall("ZREM", parentWaitingChildrenKey, parentId)
+ moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
+ end
+ end
+end
+local function moveParentToWaitIfNoPendingDependencies(parentQueueKey, parentDependenciesKey, parentKey,
+ parentId, timestamp)
+ local doNotHavePendingDependencies = rcall("SCARD", parentDependenciesKey) == 0
+ if doNotHavePendingDependencies then
+ moveParentToWaitIfNeeded(parentQueueKey, parentKey, parentId, timestamp)
+ end
+end
+local function updateParentDepsIfNeeded(parentKey, parentQueueKey, parentDependenciesKey,
+ parentId, jobIdKey, returnvalue, timestamp )
+ local processedSet = parentKey .. ":processed"
+ rcall("HSET", processedSet, jobIdKey, returnvalue)
+ moveParentToWaitIfNoPendingDependencies(parentQueueKey, parentDependenciesKey, parentKey, parentId, timestamp)
+end
+local function updateExistingJobsParent(parentKey, parent, parentData,
+ parentDependenciesKey, completedKey,
+ jobIdKey, jobId, timestamp)
+ if parentKey ~= nil then
+ if rcall("ZSCORE", completedKey, jobId) then
+ local returnvalue = rcall("HGET", jobIdKey, "returnvalue")
+ updateParentDepsIfNeeded(parentKey, parent['queueKey'],
+ parentDependenciesKey, parent['id'],
+ jobIdKey, returnvalue, timestamp)
+ else
+ if parentDependenciesKey ~= nil then
+ rcall("SADD", parentDependenciesKey, jobIdKey)
+ end
+ end
+ rcall("HMSET", jobIdKey, "parentKey", parentKey, "parent", parentData)
+ end
+end
+local function handleDuplicatedJob(jobKey, jobId, currentParentKey, currentParent,
+ parentData, parentDependenciesKey, completedKey, eventsKey, maxEvents, timestamp)
+ local existedParentKey = rcall("HGET", jobKey, "parentKey")
+ if not existedParentKey or existedParentKey == currentParentKey then
+ updateExistingJobsParent(currentParentKey, currentParent, parentData,
+ parentDependenciesKey, completedKey, jobKey,
+ jobId, timestamp)
+ else
+ if currentParentKey ~= nil and currentParentKey ~= existedParentKey
+ and (rcall("EXISTS", existedParentKey) == 1) then
+ return -7
+ end
+ end
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
+ "duplicated", "jobId", jobId)
+ return jobId .. "" -- convert to string
+end
+--[[
+ Function to store a job
+]]
+local function storeJob(eventsKey, jobIdKey, jobId, name, data, opts, timestamp,
+ parentKey, parentData, repeatJobKey)
+ local jsonOpts = cjson.encode(opts)
+ local delay = opts['delay'] or 0
+ local priority = opts['priority'] or 0
+ local debounceId = opts['de'] and opts['de']['id']
+ local optionalValues = {}
+ if parentKey ~= nil then
+ table.insert(optionalValues, "parentKey")
+ table.insert(optionalValues, parentKey)
+ table.insert(optionalValues, "parent")
+ table.insert(optionalValues, parentData)
+ end
+ if repeatJobKey then
+ table.insert(optionalValues, "rjk")
+ table.insert(optionalValues, repeatJobKey)
+ end
+ if debounceId then
+ table.insert(optionalValues, "deid")
+ table.insert(optionalValues, debounceId)
+ end
+ rcall("HMSET", jobIdKey, "name", name, "data", data, "opts", jsonOpts,
+ "timestamp", timestamp, "delay", delay, "priority", priority,
+ unpack(optionalValues))
+ rcall("XADD", eventsKey, "*", "event", "added", "jobId", jobId, "name", name)
+ return delay, priority
+end
+if parentKey ~= nil then
+ if rcall("EXISTS", parentKey) ~= 1 then return -5 end
+ parentData = cjson.encode(parent)
+end
+local jobCounter = rcall("INCR", idKey)
+local maxEvents = getOrSetMaxEvents(metaKey)
+local opts = cmsgpack.unpack(ARGV[3])
+local parentDependenciesKey = args[6]
+local timestamp = args[4]
+if args[2] == "" then
+ jobId = jobCounter
+ jobIdKey = args[1] .. jobId
+else
+ jobId = args[2]
+ jobIdKey = args[1] .. jobId
+ if rcall("EXISTS", jobIdKey) == 1 then
+ return handleDuplicatedJob(jobIdKey, jobId, parentKey, parent,
+ parentData, parentDependenciesKey, completedKey, eventsKey,
+ maxEvents, timestamp)
+ end
+end
+local deduplicationJobId = deduplicateJob(opts['de'], jobId, delayedKey, deduplicationKey,
+ eventsKey, maxEvents, args[1], args[3], ARGV[2], opts,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+if deduplicationJobId then
+ return deduplicationJobId
+end
+local delay, priority = storeJob(eventsKey, jobIdKey, jobId, args[3], ARGV[2],
+ opts, timestamp, parentKey, parentData, repeatJobKey)
+addDelayedJob(jobId, delayedKey, eventsKey, timestamp, maxEvents, KEYS[1], delay)
+-- Check if this job is a child of another job, if so add it to the parents dependencies
+if parentDependenciesKey ~= nil then
+ rcall("SADD", parentDependenciesKey, jobIdKey)
+end
+return jobId .. "" -- convert to string
+`;
+var addDelayedJob = {
+ name: "addDelayedJob",
+ content,
+ keys: 6
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/addJobScheduler-11.js
+var content2 = `--[[
+ Adds a job scheduler, i.e. a job factory that creates jobs based on a given schedule (repeat options).
+ Input:
+ KEYS[1] 'repeat' key
+ KEYS[2] 'delayed' key
+ KEYS[3] 'wait' key
+ KEYS[4] 'paused' key
+ KEYS[5] 'meta' key
+ KEYS[6] 'prioritized' key
+ KEYS[7] 'marker' key
+ KEYS[8] 'id' key
+ KEYS[9] 'events' key
+ KEYS[10] 'pc' priority counter
+ KEYS[11] 'active' key
+ ARGV[1] next milliseconds
+ ARGV[2] msgpacked options
+ [1] name
+ [2] tz?
+ [3] pattern?
+ [4] endDate?
+ [5] every?
+ ARGV[3] jobs scheduler id
+ ARGV[4] Json stringified template data
+ ARGV[5] mspacked template opts
+ ARGV[6] msgpacked delayed opts
+ ARGV[7] timestamp
+ ARGV[8] prefix key
+ ARGV[9] producer key
+ Output:
+ repeatableKey - OK
+]] local rcall = redis.call
+local repeatKey = KEYS[1]
+local delayedKey = KEYS[2]
+local waitKey = KEYS[3]
+local pausedKey = KEYS[4]
+local metaKey = KEYS[5]
+local prioritizedKey = KEYS[6]
+local eventsKey = KEYS[9]
+local nextMillis = ARGV[1]
+local jobSchedulerId = ARGV[3]
+local templateOpts = cmsgpack.unpack(ARGV[5])
+local now = tonumber(ARGV[7])
+local prefixKey = ARGV[8]
+local jobOpts = cmsgpack.unpack(ARGV[6])
+-- Includes
+--[[
+ Add delay marker if needed.
+]]
+-- Includes
+--[[
+ Shared helper to store a job and enqueue it into the appropriate list/set.
+ Handles delayed, prioritized, and standard (LIFO/FIFO) jobs.
+ Emits the appropriate event after enqueuing ("delayed" or "waiting").
+ Returns delay, priority from storeJob.
+]]
+-- Includes
+--[[
+ Adds a delayed job to the queue by doing the following:
+ - Creates a new job key with the job data.
+ - adds to delayed zset.
+ - Emits a global event 'delayed' if the job is delayed.
+]]
+-- Includes
+--[[
+ Add delay marker if needed.
+]]
+-- Includes
+--[[
+ Function to return the next delayed job timestamp.
+]]
+local function getNextDelayedTimestamp(delayedKey)
+ local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
+ if #result then
+ local nextTimestamp = tonumber(result[2])
+ if nextTimestamp ~= nil then
+ return nextTimestamp / 0x1000
+ end
+ end
+end
+local function addDelayMarkerIfNeeded(markerKey, delayedKey)
+ local nextTimestamp = getNextDelayedTimestamp(delayedKey)
+ if nextTimestamp ~= nil then
+ -- Replace the score of the marker with the newest known
+ -- next timestamp.
+ rcall("ZADD", markerKey, nextTimestamp, "1")
+ end
+end
+--[[
+ Bake in the job id first 12 bits into the timestamp
+ to guarantee correct execution order of delayed jobs
+ (up to 4096 jobs per given timestamp or 4096 jobs apart per timestamp)
+ WARNING: Jobs that are so far apart that they wrap around will cause FIFO to fail
+]]
+local function getDelayedScore(delayedKey, timestamp, delay)
+ local delayedTimestamp = (delay > 0 and (tonumber(timestamp) + delay)) or tonumber(timestamp)
+ local minScore = delayedTimestamp * 0x1000
+ local maxScore = (delayedTimestamp + 1 ) * 0x1000 - 1
+ local result = rcall("ZREVRANGEBYSCORE", delayedKey, maxScore,
+ minScore, "WITHSCORES","LIMIT", 0, 1)
+ if #result then
+ local currentMaxScore = tonumber(result[2])
+ if currentMaxScore ~= nil then
+ if currentMaxScore >= maxScore then
+ return maxScore, delayedTimestamp
+ else
+ return currentMaxScore + 1, delayedTimestamp
+ end
+ end
+ end
+ return minScore, delayedTimestamp
+end
+local function addDelayedJob(jobId, delayedKey, eventsKey, timestamp,
+ maxEvents, markerKey, delay)
+ local score, delayedTimestamp = getDelayedScore(delayedKey, timestamp, tonumber(delay))
+ rcall("ZADD", delayedKey, score, jobId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "delayed",
+ "jobId", jobId, "delay", delayedTimestamp)
+ -- mark that a delayed job is available
+ addDelayMarkerIfNeeded(markerKey, delayedKey)
+end
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to add job considering priority.
+]]
+-- Includes
+--[[
+ Function to get priority score.
+]]
+local function getPriorityScore(priority, priorityCounterKey)
+ local prioCounter = rcall("INCR", priorityCounterKey)
+ return priority * 0x100000000 + prioCounter % 0x100000000
+end
+local function addJobWithPriority(markerKey, prioritizedKey, priority, jobId, priorityCounterKey,
+ isPausedOrMaxed)
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+--[[
+ Function to store a job
+]]
+local function storeJob(eventsKey, jobIdKey, jobId, name, data, opts, timestamp,
+ parentKey, parentData, repeatJobKey)
+ local jsonOpts = cjson.encode(opts)
+ local delay = opts['delay'] or 0
+ local priority = opts['priority'] or 0
+ local debounceId = opts['de'] and opts['de']['id']
+ local optionalValues = {}
+ if parentKey ~= nil then
+ table.insert(optionalValues, "parentKey")
+ table.insert(optionalValues, parentKey)
+ table.insert(optionalValues, "parent")
+ table.insert(optionalValues, parentData)
+ end
+ if repeatJobKey then
+ table.insert(optionalValues, "rjk")
+ table.insert(optionalValues, repeatJobKey)
+ end
+ if debounceId then
+ table.insert(optionalValues, "deid")
+ table.insert(optionalValues, debounceId)
+ end
+ rcall("HMSET", jobIdKey, "name", name, "data", data, "opts", jsonOpts,
+ "timestamp", timestamp, "delay", delay, "priority", priority,
+ unpack(optionalValues))
+ rcall("XADD", eventsKey, "*", "event", "added", "jobId", jobId, "name", name)
+ return delay, priority
+end
+local function storeAndEnqueueJob(eventsKey, jobIdKey, jobId, name, data, opts,
+ timestamp, parentKey, parentData, repeatJobKey, maxEvents,
+ waitKey, pausedKey, activeKey, metaKey, prioritizedKey,
+ priorityCounterKey, delayedKey, markerKey)
+ local delay, priority = storeJob(eventsKey, jobIdKey, jobId, name, data,
+ opts, timestamp, parentKey, parentData, repeatJobKey)
+ if delay ~= 0 and delayedKey then
+ addDelayedJob(jobId, delayedKey, eventsKey, timestamp, maxEvents, markerKey, delay)
+ else
+ local target, isPausedOrMaxed = getTargetQueueList(metaKey, activeKey, waitKey, pausedKey)
+ if priority > 0 then
+ addJobWithPriority(markerKey, prioritizedKey, priority, jobId,
+ priorityCounterKey, isPausedOrMaxed)
+ else
+ local pushCmd = opts['lifo'] and 'RPUSH' or 'LPUSH'
+ addJobInTargetList(target, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ end
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "waiting",
+ "jobId", jobId)
+ end
+ return delay, priority
+end
+local function addJobFromScheduler(jobKey, jobId, opts, waitKey, pausedKey, activeKey, metaKey,
+ prioritizedKey, priorityCounter, delayedKey, markerKey, eventsKey, name, maxEvents, timestamp,
+ data, jobSchedulerId, repeatDelay)
+ opts['delay'] = repeatDelay
+ opts['jobId'] = jobId
+ storeAndEnqueueJob(eventsKey, jobKey, jobId, name, data, opts,
+ timestamp, nil, nil, jobSchedulerId, maxEvents,
+ waitKey, pausedKey, activeKey, metaKey, prioritizedKey,
+ priorityCounter, delayedKey, markerKey)
+end
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function isQueuePaused(queueMetaKey)
+ return rcall("HEXISTS", queueMetaKey, "paused") == 1
+end
+--[[
+ Function to remove job.
+]]
+-- Includes
+--[[
+ Function to remove deduplication key if needed
+ when a job is being removed.
+]]
+local function removeDeduplicationKeyIfNeededOnRemoval(prefixKey,
+ jobId, deduplicationId)
+ if deduplicationId then
+ local deduplicationKey = prefixKey .. "de:" .. deduplicationId
+ local currentJobId = rcall('GET', deduplicationKey)
+ if currentJobId and currentJobId == jobId then
+ rcall("DEL", deduplicationKey)
+ -- Also clean up any pending dedup-next data for this dedup ID
+ rcall("DEL", prefixKey .. "dn:" .. deduplicationId)
+ return 1
+ end
+ end
+end
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+--[[
+ Check if this job has a parent. If so we will just remove it from
+ the parent child list, but if it is the last child we should move the parent to "wait/paused"
+ which requires code from "moveToFinished"
+]]
+-- Includes
+--[[
+ Functions to destructure job key.
+ Just a bit of warning, these functions may be a bit slow and affect performance significantly.
+]]
+local getJobIdFromKey = function (jobKey)
+ return string.match(jobKey, ".*:(.*)")
+end
+local getJobKeyPrefix = function (jobKey, jobId)
+ return string.sub(jobKey, 0, #jobKey - #jobId)
+end
+local function _moveParentToWait(parentPrefix, parentId, emitEvent)
+ local parentTarget, isPausedOrMaxed = getTargetQueueList(parentPrefix .. "meta", parentPrefix .. "active",
+ parentPrefix .. "wait", parentPrefix .. "paused")
+ addJobInTargetList(parentTarget, parentPrefix .. "marker", "RPUSH", isPausedOrMaxed, parentId)
+ if emitEvent then
+ local parentEventStream = parentPrefix .. "events"
+ rcall("XADD", parentEventStream, "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
+ end
+end
+local function removeParentDependencyKey(jobKey, hard, parentKey, baseKey, debounceId)
+ if parentKey then
+ local parentDependenciesKey = parentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(parentKey)
+ local parentPrefix = getJobKeyPrefix(parentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then -- remove parent in same queue
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(parentKey, hard, nil, baseKey, nil)
+ removeJobKeys(parentKey)
+ if debounceId then
+ rcall("DEL", parentPrefix .. "de:" .. debounceId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ else
+ local parentAttributes = rcall("HMGET", jobKey, "parentKey", "deid")
+ local missedParentKey = parentAttributes[1]
+ if( (type(missedParentKey) == "string") and missedParentKey ~= ""
+ and (rcall("EXISTS", missedParentKey) == 1)) then
+ local parentDependenciesKey = missedParentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(missedParentKey)
+ local parentPrefix = getJobKeyPrefix(missedParentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(missedParentKey, hard, nil, baseKey, nil)
+ removeJobKeys(missedParentKey)
+ if parentAttributes[2] then
+ rcall("DEL", parentPrefix .. "de:" .. parentAttributes[2])
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ end
+ end
+ return false
+end
+local function removeJob(jobId, hard, baseKey, shouldRemoveDeduplicationKey)
+ local jobKey = baseKey .. jobId
+ removeParentDependencyKey(jobKey, hard, nil, baseKey)
+ if shouldRemoveDeduplicationKey then
+ local deduplicationId = rcall("HGET", jobKey, "deid")
+ removeDeduplicationKeyIfNeededOnRemoval(baseKey, jobId, deduplicationId)
+ end
+ removeJobKeys(jobKey)
+end
+--[[
+ Function to store a job scheduler
+]]
+local function storeJobScheduler(schedulerId, schedulerKey, repeatKey, nextMillis, opts,
+ templateData, templateOpts)
+ rcall("ZADD", repeatKey, nextMillis, schedulerId)
+ local optionalValues = {}
+ if opts['tz'] then
+ table.insert(optionalValues, "tz")
+ table.insert(optionalValues, opts['tz'])
+ end
+ if opts['limit'] then
+ table.insert(optionalValues, "limit")
+ table.insert(optionalValues, opts['limit'])
+ end
+ if opts['pattern'] then
+ table.insert(optionalValues, "pattern")
+ table.insert(optionalValues, opts['pattern'])
+ end
+ if opts['startDate'] then
+ table.insert(optionalValues, "startDate")
+ table.insert(optionalValues, opts['startDate'])
+ end
+ if opts['endDate'] then
+ table.insert(optionalValues, "endDate")
+ table.insert(optionalValues, opts['endDate'])
+ end
+ if opts['every'] then
+ table.insert(optionalValues, "every")
+ table.insert(optionalValues, opts['every'])
+ end
+ if opts['offset'] then
+ table.insert(optionalValues, "offset")
+ table.insert(optionalValues, opts['offset'])
+ else
+ local offset = rcall("HGET", schedulerKey, "offset")
+ if offset then
+ table.insert(optionalValues, "offset")
+ table.insert(optionalValues, tonumber(offset))
+ end
+ end
+ local jsonTemplateOpts = cjson.encode(templateOpts)
+ if jsonTemplateOpts and jsonTemplateOpts ~= '{}' then
+ table.insert(optionalValues, "opts")
+ table.insert(optionalValues, jsonTemplateOpts)
+ end
+ if templateData and templateData ~= '{}' then
+ table.insert(optionalValues, "data")
+ table.insert(optionalValues, templateData)
+ end
+ table.insert(optionalValues, "ic")
+ table.insert(optionalValues, rcall("HGET", schedulerKey, "ic") or 1)
+ rcall("DEL", schedulerKey) -- remove all attributes and then re-insert new ones
+ rcall("HMSET", schedulerKey, "name", opts['name'], unpack(optionalValues))
+end
+local function getJobSchedulerEveryNextMillis(prevMillis, every, now, offset, startDate)
+ local nextMillis
+ if not prevMillis then
+ if startDate then
+ -- Assuming startDate is passed as milliseconds from JavaScript
+ nextMillis = tonumber(startDate)
+ nextMillis = nextMillis > now and nextMillis or now
+ else
+ nextMillis = now
+ end
+ else
+ nextMillis = prevMillis + every
+ -- check if we may have missed some iterations
+ if nextMillis < now then
+ nextMillis = math.floor(now / every) * every + every + (offset or 0)
+ end
+ end
+ if not offset or offset == 0 then
+ local timeSlot = math.floor(nextMillis / every) * every;
+ offset = nextMillis - timeSlot;
+ end
+ -- Return a tuple nextMillis, offset
+ return math.floor(nextMillis), math.floor(offset)
+end
+-- If we are overriding a repeatable job we must delete the delayed job for
+-- the next iteration.
+local schedulerKey = repeatKey .. ":" .. jobSchedulerId
+local maxEvents = getOrSetMaxEvents(metaKey)
+local templateData = ARGV[4]
+local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
+if prevMillis then
+ prevMillis = tonumber(prevMillis)
+end
+local schedulerOpts = cmsgpack.unpack(ARGV[2])
+local every = schedulerOpts['every']
+-- For backwards compatibility we also check the offset from the job itself.
+-- could be removed in future major versions.
+local jobOffset = jobOpts['repeat'] and jobOpts['repeat']['offset'] or 0
+local offset = schedulerOpts['offset'] or jobOffset or 0
+local newOffset = offset
+local updatedEvery = false
+if every then
+ -- if we changed the 'every' value we need to reset millis to nil
+ local millis = prevMillis
+ if prevMillis then
+ local prevEvery = tonumber(rcall("HGET", schedulerKey, "every"))
+ if prevEvery ~= every then
+ millis = nil
+ updatedEvery = true
+ end
+ end
+ local startDate = schedulerOpts['startDate']
+ nextMillis, newOffset = getJobSchedulerEveryNextMillis(millis, every, now, offset, startDate)
+end
+local function removeJobFromScheduler(prefixKey, delayedKey, prioritizedKey, waitKey, pausedKey, jobId, metaKey,
+ eventsKey)
+ if rcall("ZSCORE", delayedKey, jobId) then
+ removeJob(jobId, true, prefixKey, true --[[remove debounce key]] )
+ rcall("ZREM", delayedKey, jobId)
+ return true
+ elseif rcall("ZSCORE", prioritizedKey, jobId) then
+ removeJob(jobId, true, prefixKey, true --[[remove debounce key]] )
+ rcall("ZREM", prioritizedKey, jobId)
+ return true
+ else
+ local pausedOrWaitKey = waitKey
+ if isQueuePaused(metaKey) then
+ pausedOrWaitKey = pausedKey
+ end
+ if rcall("LREM", pausedOrWaitKey, 1, jobId) > 0 then
+ removeJob(jobId, true, prefixKey, true --[[remove debounce key]] )
+ return true
+ end
+ end
+ return false
+end
+local removedPrevJob = false
+if prevMillis then
+ local currentJobId = "repeat:" .. jobSchedulerId .. ":" .. prevMillis
+ local currentJobKey = schedulerKey .. ":" .. prevMillis
+ -- In theory it should always exist the currentJobKey if there is a prevMillis unless something has
+ -- gone really wrong.
+ if rcall("EXISTS", currentJobKey) == 1 then
+ removedPrevJob = removeJobFromScheduler(prefixKey, delayedKey, prioritizedKey, waitKey, pausedKey, currentJobId,
+ metaKey, eventsKey)
+ end
+end
+if removedPrevJob then
+ -- The jobs has been removed and we want to replace it, so lets use the same millis.
+ if every and not updatedEvery then
+ nextMillis = prevMillis
+ end
+else
+ -- Special case where no job was removed, and we need to add the next iteration.
+ schedulerOpts['offset'] = newOffset
+end
+-- Check for job ID collision with existing jobs (in any state)
+local jobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
+local jobKey = prefixKey .. jobId
+-- If there's already a job with this ID, in a state
+-- that is not updatable (active, completed, failed) we must
+-- handle the collision
+local hasCollision = false
+if rcall("EXISTS", jobKey) == 1 then
+ if every then
+ -- For 'every' case: try next time slot to avoid collision
+ local nextSlotMillis = nextMillis + every
+ local nextSlotJobId = "repeat:" .. jobSchedulerId .. ":" .. nextSlotMillis
+ local nextSlotJobKey = prefixKey .. nextSlotJobId
+ if rcall("EXISTS", nextSlotJobKey) == 0 then
+ -- Next slot is free, use it
+ nextMillis = nextSlotMillis
+ jobId = nextSlotJobId
+ else
+ -- Next slot also has a job, return error code
+ return -11 -- SchedulerJobSlotsBusy
+ end
+ else
+ hasCollision = true
+ end
+end
+local delay = nextMillis - now
+-- Fast Clamp delay to minimum of 0
+if delay < 0 then
+ delay = 0
+end
+local nextJobKey = schedulerKey .. ":" .. nextMillis
+if not hasCollision or removedPrevJob then
+ -- jobId already calculated above during collision check
+ storeJobScheduler(jobSchedulerId, schedulerKey, repeatKey, nextMillis, schedulerOpts, templateData, templateOpts)
+ rcall("INCR", KEYS[8])
+ addJobFromScheduler(nextJobKey, jobId, jobOpts, waitKey, pausedKey, KEYS[11], metaKey, prioritizedKey, KEYS[10],
+ delayedKey, KEYS[7], eventsKey, schedulerOpts['name'], maxEvents, now, templateData, jobSchedulerId, delay)
+elseif hasCollision then
+ -- For 'pattern' case: return error code
+ return -10 -- SchedulerJobIdCollision
+end
+if ARGV[9] ~= "" then
+ rcall("HSET", ARGV[9], "nrjid", jobId)
+end
+return {jobId .. "", delay}
+`;
+var addJobScheduler = {
+ name: "addJobScheduler",
+ content: content2,
+ keys: 11
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/addLog-2.js
+var content3 = `--[[
+ Add job log
+ Input:
+ KEYS[1] job id key
+ KEYS[2] job logs key
+ ARGV[1] id
+ ARGV[2] log
+ ARGV[3] keepLogs
+ Output:
+ -1 - Missing job.
+]]
+local rcall = redis.call
+if rcall("EXISTS", KEYS[1]) == 1 then -- // Make sure job exists
+ local logCount = rcall("RPUSH", KEYS[2], ARGV[2])
+ if ARGV[3] ~= '' then
+ local keepLogs = tonumber(ARGV[3])
+ rcall("LTRIM", KEYS[2], -keepLogs, -1)
+ return math.min(keepLogs, logCount)
+ end
+ return logCount
+else
+ return -1
+end
+`;
+var addLog = {
+ name: "addLog",
+ content: content3,
+ keys: 2
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/addParentJob-6.js
+var content4 = `--[[
+ Adds a parent job to the queue by doing the following:
+ - Increases the job counter if needed.
+ - Creates a new job key with the job data.
+ - adds the job to the waiting-children zset
+ Input:
+ KEYS[1] 'meta'
+ KEYS[2] 'id'
+ KEYS[3] 'delayed'
+ KEYS[4] 'waiting-children'
+ KEYS[5] 'completed'
+ KEYS[6] events stream key
+ ARGV[1] msgpacked arguments array
+ [1] key prefix,
+ [2] custom id (will not generate one automatically)
+ [3] name
+ [4] timestamp
+ [5] parentKey?
+ [6] parent dependencies key.
+ [7] parent? {id, queueKey}
+ [8] repeat job key
+ [9] deduplication key
+ ARGV[2] Json stringified job data
+ ARGV[3] msgpacked options
+ Output:
+ jobId - OK
+ -5 - Missing parent key
+]]
+local metaKey = KEYS[1]
+local idKey = KEYS[2]
+local delayedKey = KEYS[3]
+local completedKey = KEYS[5]
+local eventsKey = KEYS[6]
+local jobId
+local jobIdKey
+local rcall = redis.call
+local args = cmsgpack.unpack(ARGV[1])
+local data = ARGV[2]
+local opts = cmsgpack.unpack(ARGV[3])
+local parentKey = args[5]
+local parent = args[7]
+local repeatJobKey = args[8]
+local deduplicationKey = args[9]
+local parentData
+-- Includes
+--[[
+ Function to deduplicate a job.
+]]
+--[[
+ Function to set the deduplication key for a job.
+ Uses TTL from deduplication opts if provided.
+]]
+local function setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ local ttl = deduplicationOpts and deduplicationOpts['ttl']
+ if ttl and ttl > 0 then
+ rcall('SET', deduplicationKey, jobId, 'PX', ttl)
+ else
+ rcall('SET', deduplicationKey, jobId)
+ end
+end
+--[[
+ Function to store a deduplicated next job if the existing job is active
+ and keepLastIfActive is set. When the active job finishes, the stored
+ proto-job is used to create a real job in the queue.
+ Returns true if the proto-job was stored, false otherwise.
+]]
+--[[
+ Function to check if an item belongs to a list.
+]]
+local function checkItemInList(list, item)
+ for _, v in pairs(list) do
+ if v == item then
+ return 1
+ end
+ end
+ return nil
+end
+local function storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ if deduplicationOpts['keepLastIfActive'] and currentDebounceJobId then
+ local activeKey = prefix .. "active"
+ local activeItems = rcall('LRANGE', activeKey, 0, -1)
+ if checkItemInList(activeItems, currentDebounceJobId) then
+ local deduplicationNextKey = prefix .. "dn:" .. deduplicationId
+ local fields = {'name', jobName, 'data', jobData, 'opts', cjson.encode(fullOpts)}
+ if parentKey then
+ fields[#fields+1] = 'pk'
+ fields[#fields+1] = parentKey
+ end
+ if parentData then
+ fields[#fields+1] = 'pd'
+ fields[#fields+1] = parentData
+ end
+ if parentDependenciesKey then
+ fields[#fields+1] = 'pdk'
+ fields[#fields+1] = parentDependenciesKey
+ end
+ if repeatJobKey then
+ fields[#fields+1] = 'rjk'
+ fields[#fields+1] = repeatJobKey
+ end
+ rcall('HSET', deduplicationNextKey, unpack(fields))
+ -- Ensure the dedup key does not expire while the job is active,
+ -- so subsequent adds always hit the dedup path and never bypass
+ -- the active-check because of a TTL expiry.
+ local deduplicationKey = prefix .. "de:" .. deduplicationId
+ rcall('PERSIST', deduplicationKey)
+ -- TODO remove debounced event in next breaking change
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced", "jobId",
+ currentDebounceJobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ currentDebounceJobId, "deduplicationId", deduplicationId, "deduplicatedJobId", jobId)
+ return true
+ end
+ end
+ return false
+end
+local function deduplicateJobWithoutReplace(deduplicationId, deduplicationOpts, jobId, deduplicationKey,
+ eventsKey, maxEvents, prefix, jobName, jobData, fullOpts,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ local ttl = deduplicationOpts['ttl']
+ local deduplicationKeyExists
+ if ttl and ttl > 0 then
+ if deduplicationOpts['extend'] then
+ local currentDebounceJobId = rcall('GET', deduplicationKey)
+ if currentDebounceJobId then
+ if storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey) then
+ return currentDebounceJobId
+ end
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, currentDebounceJobId)
+ else
+ setDeduplicationKey(deduplicationKey, currentDebounceJobId, deduplicationOpts)
+ end
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced",
+ "jobId", currentDebounceJobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ currentDebounceJobId, "deduplicationId", deduplicationId, "deduplicatedJobId", jobId)
+ return currentDebounceJobId
+ else
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, jobId)
+ else
+ setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ end
+ return
+ end
+ else
+ if deduplicationOpts['keepLastIfActive'] then
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'NX')
+ else
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'PX', ttl, 'NX')
+ end
+ end
+ else
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'NX')
+ end
+ if deduplicationKeyExists then
+ local currentDebounceJobId = rcall('GET', deduplicationKey)
+ if storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey) then
+ return currentDebounceJobId
+ end
+ -- TODO remove debounced event in next breaking change
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced", "jobId",
+ currentDebounceJobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ currentDebounceJobId, "deduplicationId", deduplicationId, "deduplicatedJobId", jobId)
+ return currentDebounceJobId
+ end
+end
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+--[[
+ Function to handle the case when job is duplicated.
+]]
+-- Includes
+--[[
+ This function is used to update the parent's dependencies if the job
+ is already completed and about to be ignored. The parent must get its
+ dependencies updated to avoid the parent job being stuck forever in
+ the waiting-children state.
+]]
+-- Includes
+--[[
+ Validate and move or add dependencies to parent.
+]]
+-- Includes
+--[[
+ Validate and move parent to a wait status (waiting, delayed or prioritized)
+ if no pending dependencies.
+]]
+-- Includes
+--[[
+ Validate and move parent to a wait status (waiting, delayed or prioritized) if needed.
+]]
+-- Includes
+--[[
+ Move parent to a wait status (wait, prioritized or delayed)
+]]
+-- Includes
+--[[
+ Add delay marker if needed.
+]]
+-- Includes
+--[[
+ Function to return the next delayed job timestamp.
+]]
+local function getNextDelayedTimestamp(delayedKey)
+ local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
+ if #result then
+ local nextTimestamp = tonumber(result[2])
+ if nextTimestamp ~= nil then
+ return nextTimestamp / 0x1000
+ end
+ end
+end
+local function addDelayMarkerIfNeeded(markerKey, delayedKey)
+ local nextTimestamp = getNextDelayedTimestamp(delayedKey)
+ if nextTimestamp ~= nil then
+ -- Replace the score of the marker with the newest known
+ -- next timestamp.
+ rcall("ZADD", markerKey, nextTimestamp, "1")
+ end
+end
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to add job considering priority.
+]]
+-- Includes
+--[[
+ Function to get priority score.
+]]
+local function getPriorityScore(priority, priorityCounterKey)
+ local prioCounter = rcall("INCR", priorityCounterKey)
+ return priority * 0x100000000 + prioCounter % 0x100000000
+end
+local function addJobWithPriority(markerKey, prioritizedKey, priority, jobId, priorityCounterKey,
+ isPausedOrMaxed)
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to check if queue is paused or maxed
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function isQueuePausedOrMaxed(queueMetaKey, activeKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency")
+ if queueAttributes[1] then
+ return true
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ return activeCount >= tonumber(queueAttributes[2])
+ end
+ end
+ return false
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+local function moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
+ local parentWaitKey = parentQueueKey .. ":wait"
+ local parentPausedKey = parentQueueKey .. ":paused"
+ local parentActiveKey = parentQueueKey .. ":active"
+ local parentMetaKey = parentQueueKey .. ":meta"
+ local parentMarkerKey = parentQueueKey .. ":marker"
+ local jobAttributes = rcall("HMGET", parentKey, "priority", "delay")
+ local priority = tonumber(jobAttributes[1]) or 0
+ local delay = tonumber(jobAttributes[2]) or 0
+ if delay > 0 then
+ local delayedTimestamp = tonumber(timestamp) + delay
+ local score = delayedTimestamp * 0x1000
+ local parentDelayedKey = parentQueueKey .. ":delayed"
+ rcall("ZADD", parentDelayedKey, score, parentId)
+ rcall("XADD", parentQueueKey .. ":events", "*", "event", "delayed", "jobId", parentId, "delay",
+ delayedTimestamp)
+ addDelayMarkerIfNeeded(parentMarkerKey, parentDelayedKey)
+ else
+ if priority == 0 then
+ local parentTarget, isParentPausedOrMaxed = getTargetQueueList(parentMetaKey, parentActiveKey,
+ parentWaitKey, parentPausedKey)
+ addJobInTargetList(parentTarget, parentMarkerKey, "RPUSH", isParentPausedOrMaxed, parentId)
+ else
+ local isPausedOrMaxed = isQueuePausedOrMaxed(parentMetaKey, parentActiveKey)
+ addJobWithPriority(parentMarkerKey, parentQueueKey .. ":prioritized", priority, parentId,
+ parentQueueKey .. ":pc", isPausedOrMaxed)
+ end
+ rcall("XADD", parentQueueKey .. ":events", "*", "event", "waiting", "jobId", parentId, "prev",
+ "waiting-children")
+ end
+end
+local function moveParentToWaitIfNeeded(parentQueueKey, parentKey, parentId, timestamp)
+ if rcall("EXISTS", parentKey) == 1 then
+ local parentWaitingChildrenKey = parentQueueKey .. ":waiting-children"
+ if rcall("ZSCORE", parentWaitingChildrenKey, parentId) then
+ rcall("ZREM", parentWaitingChildrenKey, parentId)
+ moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
+ end
+ end
+end
+local function moveParentToWaitIfNoPendingDependencies(parentQueueKey, parentDependenciesKey, parentKey,
+ parentId, timestamp)
+ local doNotHavePendingDependencies = rcall("SCARD", parentDependenciesKey) == 0
+ if doNotHavePendingDependencies then
+ moveParentToWaitIfNeeded(parentQueueKey, parentKey, parentId, timestamp)
+ end
+end
+local function updateParentDepsIfNeeded(parentKey, parentQueueKey, parentDependenciesKey,
+ parentId, jobIdKey, returnvalue, timestamp )
+ local processedSet = parentKey .. ":processed"
+ rcall("HSET", processedSet, jobIdKey, returnvalue)
+ moveParentToWaitIfNoPendingDependencies(parentQueueKey, parentDependenciesKey, parentKey, parentId, timestamp)
+end
+local function updateExistingJobsParent(parentKey, parent, parentData,
+ parentDependenciesKey, completedKey,
+ jobIdKey, jobId, timestamp)
+ if parentKey ~= nil then
+ if rcall("ZSCORE", completedKey, jobId) then
+ local returnvalue = rcall("HGET", jobIdKey, "returnvalue")
+ updateParentDepsIfNeeded(parentKey, parent['queueKey'],
+ parentDependenciesKey, parent['id'],
+ jobIdKey, returnvalue, timestamp)
+ else
+ if parentDependenciesKey ~= nil then
+ rcall("SADD", parentDependenciesKey, jobIdKey)
+ end
+ end
+ rcall("HMSET", jobIdKey, "parentKey", parentKey, "parent", parentData)
+ end
+end
+local function handleDuplicatedJob(jobKey, jobId, currentParentKey, currentParent,
+ parentData, parentDependenciesKey, completedKey, eventsKey, maxEvents, timestamp)
+ local existedParentKey = rcall("HGET", jobKey, "parentKey")
+ if not existedParentKey or existedParentKey == currentParentKey then
+ updateExistingJobsParent(currentParentKey, currentParent, parentData,
+ parentDependenciesKey, completedKey, jobKey,
+ jobId, timestamp)
+ else
+ if currentParentKey ~= nil and currentParentKey ~= existedParentKey
+ and (rcall("EXISTS", existedParentKey) == 1) then
+ return -7
+ end
+ end
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
+ "duplicated", "jobId", jobId)
+ return jobId .. "" -- convert to string
+end
+--[[
+ Function to store a job
+]]
+local function storeJob(eventsKey, jobIdKey, jobId, name, data, opts, timestamp,
+ parentKey, parentData, repeatJobKey)
+ local jsonOpts = cjson.encode(opts)
+ local delay = opts['delay'] or 0
+ local priority = opts['priority'] or 0
+ local debounceId = opts['de'] and opts['de']['id']
+ local optionalValues = {}
+ if parentKey ~= nil then
+ table.insert(optionalValues, "parentKey")
+ table.insert(optionalValues, parentKey)
+ table.insert(optionalValues, "parent")
+ table.insert(optionalValues, parentData)
+ end
+ if repeatJobKey then
+ table.insert(optionalValues, "rjk")
+ table.insert(optionalValues, repeatJobKey)
+ end
+ if debounceId then
+ table.insert(optionalValues, "deid")
+ table.insert(optionalValues, debounceId)
+ end
+ rcall("HMSET", jobIdKey, "name", name, "data", data, "opts", jsonOpts,
+ "timestamp", timestamp, "delay", delay, "priority", priority,
+ unpack(optionalValues))
+ rcall("XADD", eventsKey, "*", "event", "added", "jobId", jobId, "name", name)
+ return delay, priority
+end
+if parentKey ~= nil then
+ if rcall("EXISTS", parentKey) ~= 1 then return -5 end
+ parentData = cjson.encode(parent)
+end
+local jobCounter = rcall("INCR", idKey)
+local maxEvents = getOrSetMaxEvents(metaKey)
+local parentDependenciesKey = args[6]
+local timestamp = args[4]
+if args[2] == "" then
+ jobId = jobCounter
+ jobIdKey = args[1] .. jobId
+else
+ jobId = args[2]
+ jobIdKey = args[1] .. jobId
+ if rcall("EXISTS", jobIdKey) == 1 then
+ return handleDuplicatedJob(jobIdKey, jobId, parentKey, parent,
+ parentData, parentDependenciesKey, completedKey, eventsKey,
+ maxEvents, timestamp)
+ end
+end
+local deduplicationId = opts['de'] and opts['de']['id']
+if deduplicationId then
+ local deduplicationJobId = deduplicateJobWithoutReplace(deduplicationId, opts['de'],
+ jobId, deduplicationKey, eventsKey, maxEvents, args[1], args[3], ARGV[2], opts,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ if deduplicationJobId then
+ return deduplicationJobId
+ end
+end
+-- Store the job.
+storeJob(eventsKey, jobIdKey, jobId, args[3], ARGV[2], opts, timestamp,
+ parentKey, parentData, repeatJobKey)
+local waitChildrenKey = KEYS[4]
+rcall("ZADD", waitChildrenKey, timestamp, jobId)
+rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
+ "waiting-children", "jobId", jobId)
+-- Check if this job is a child of another job, if so add it to the parents dependencies
+if parentDependenciesKey ~= nil then
+ rcall("SADD", parentDependenciesKey, jobIdKey)
+end
+return jobId .. "" -- convert to string
+`;
+var addParentJob = {
+ name: "addParentJob",
+ content: content4,
+ keys: 6
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/addPrioritizedJob-9.js
+var content5 = `--[[
+ Adds a priotitized job to the queue by doing the following:
+ - Increases the job counter if needed.
+ - Creates a new job key with the job data.
+ - Adds the job to the "added" list so that workers gets notified.
+ Input:
+ KEYS[1] 'marker',
+ KEYS[2] 'meta'
+ KEYS[3] 'id'
+ KEYS[4] 'prioritized'
+ KEYS[5] 'delayed'
+ KEYS[6] 'completed'
+ KEYS[7] 'active'
+ KEYS[8] events stream key
+ KEYS[9] 'pc' priority counter
+ ARGV[1] msgpacked arguments array
+ [1] key prefix,
+ [2] custom id (will not generate one automatically)
+ [3] name
+ [4] timestamp
+ [5] parentKey?
+ [6] parent dependencies key.
+ [7] parent? {id, queueKey}
+ [8] repeat job key
+ [9] deduplication key
+ ARGV[2] Json stringified job data
+ ARGV[3] msgpacked options
+ Output:
+ jobId - OK
+ -5 - Missing parent key
+]]
+local metaKey = KEYS[2]
+local idKey = KEYS[3]
+local priorityKey = KEYS[4]
+local completedKey = KEYS[6]
+local activeKey = KEYS[7]
+local eventsKey = KEYS[8]
+local priorityCounterKey = KEYS[9]
+local jobId
+local jobIdKey
+local rcall = redis.call
+local args = cmsgpack.unpack(ARGV[1])
+local data = ARGV[2]
+local opts = cmsgpack.unpack(ARGV[3])
+local parentKey = args[5]
+local parent = args[7]
+local repeatJobKey = args[8]
+local deduplicationKey = args[9]
+local parentData
+-- Includes
+--[[
+ Function to add job considering priority.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+--[[
+ Function to get priority score.
+]]
+local function getPriorityScore(priority, priorityCounterKey)
+ local prioCounter = rcall("INCR", priorityCounterKey)
+ return priority * 0x100000000 + prioCounter % 0x100000000
+end
+local function addJobWithPriority(markerKey, prioritizedKey, priority, jobId, priorityCounterKey,
+ isPausedOrMaxed)
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to debounce a job.
+]]
+-- Includes
+--[[
+ Function to deduplicate a job.
+]]
+--[[
+ Function to set the deduplication key for a job.
+ Uses TTL from deduplication opts if provided.
+]]
+local function setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ local ttl = deduplicationOpts and deduplicationOpts['ttl']
+ if ttl and ttl > 0 then
+ rcall('SET', deduplicationKey, jobId, 'PX', ttl)
+ else
+ rcall('SET', deduplicationKey, jobId)
+ end
+end
+--[[
+ Function to store a deduplicated next job if the existing job is active
+ and keepLastIfActive is set. When the active job finishes, the stored
+ proto-job is used to create a real job in the queue.
+ Returns true if the proto-job was stored, false otherwise.
+]]
+--[[
+ Function to check if an item belongs to a list.
+]]
+local function checkItemInList(list, item)
+ for _, v in pairs(list) do
+ if v == item then
+ return 1
+ end
+ end
+ return nil
+end
+local function storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ if deduplicationOpts['keepLastIfActive'] and currentDebounceJobId then
+ local activeKey = prefix .. "active"
+ local activeItems = rcall('LRANGE', activeKey, 0, -1)
+ if checkItemInList(activeItems, currentDebounceJobId) then
+ local deduplicationNextKey = prefix .. "dn:" .. deduplicationId
+ local fields = {'name', jobName, 'data', jobData, 'opts', cjson.encode(fullOpts)}
+ if parentKey then
+ fields[#fields+1] = 'pk'
+ fields[#fields+1] = parentKey
+ end
+ if parentData then
+ fields[#fields+1] = 'pd'
+ fields[#fields+1] = parentData
+ end
+ if parentDependenciesKey then
+ fields[#fields+1] = 'pdk'
+ fields[#fields+1] = parentDependenciesKey
+ end
+ if repeatJobKey then
+ fields[#fields+1] = 'rjk'
+ fields[#fields+1] = repeatJobKey
+ end
+ rcall('HSET', deduplicationNextKey, unpack(fields))
+ -- Ensure the dedup key does not expire while the job is active,
+ -- so subsequent adds always hit the dedup path and never bypass
+ -- the active-check because of a TTL expiry.
+ local deduplicationKey = prefix .. "de:" .. deduplicationId
+ rcall('PERSIST', deduplicationKey)
+ -- TODO remove debounced event in next breaking change
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced", "jobId",
+ currentDebounceJobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ currentDebounceJobId, "deduplicationId", deduplicationId, "deduplicatedJobId", jobId)
+ return true
+ end
+ end
+ return false
+end
+local function deduplicateJobWithoutReplace(deduplicationId, deduplicationOpts, jobId, deduplicationKey,
+ eventsKey, maxEvents, prefix, jobName, jobData, fullOpts,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ local ttl = deduplicationOpts['ttl']
+ local deduplicationKeyExists
+ if ttl and ttl > 0 then
+ if deduplicationOpts['extend'] then
+ local currentDebounceJobId = rcall('GET', deduplicationKey)
+ if currentDebounceJobId then
+ if storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey) then
+ return currentDebounceJobId
+ end
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, currentDebounceJobId)
+ else
+ setDeduplicationKey(deduplicationKey, currentDebounceJobId, deduplicationOpts)
+ end
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced",
+ "jobId", currentDebounceJobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ currentDebounceJobId, "deduplicationId", deduplicationId, "deduplicatedJobId", jobId)
+ return currentDebounceJobId
+ else
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, jobId)
+ else
+ setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ end
+ return
+ end
+ else
+ if deduplicationOpts['keepLastIfActive'] then
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'NX')
+ else
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'PX', ttl, 'NX')
+ end
+ end
+ else
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'NX')
+ end
+ if deduplicationKeyExists then
+ local currentDebounceJobId = rcall('GET', deduplicationKey)
+ if storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey) then
+ return currentDebounceJobId
+ end
+ -- TODO remove debounced event in next breaking change
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced", "jobId",
+ currentDebounceJobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ currentDebounceJobId, "deduplicationId", deduplicationId, "deduplicatedJobId", jobId)
+ return currentDebounceJobId
+ end
+end
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+local function removeDelayedJob(delayedKey, deduplicationKey, eventsKey, maxEvents, currentDeduplicatedJobId,
+ jobId, deduplicationId, prefix)
+ if rcall("ZREM", delayedKey, currentDeduplicatedJobId) > 0 then
+ removeJobKeys(prefix .. currentDeduplicatedJobId)
+ rcall("XADD", eventsKey, "*", "event", "removed", "jobId", currentDeduplicatedJobId,
+ "prev", "delayed")
+ -- TODO remove debounced event in next breaking change
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced", "jobId",
+ jobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ jobId, "deduplicationId", deduplicationId, "deduplicatedJobId", currentDeduplicatedJobId)
+ return true
+ end
+ return false
+end
+local function deduplicateJob(deduplicationOpts, jobId, delayedKey, deduplicationKey, eventsKey, maxEvents,
+ prefix, jobName, jobData, fullOpts, parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ local deduplicationId = deduplicationOpts and deduplicationOpts['id']
+ if deduplicationId then
+ if deduplicationOpts['replace'] then
+ local currentDebounceJobId = rcall('GET', deduplicationKey)
+ if currentDebounceJobId then
+ local isRemoved = removeDelayedJob(delayedKey, deduplicationKey, eventsKey, maxEvents,
+ currentDebounceJobId, jobId, deduplicationId, prefix)
+ if isRemoved then
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, jobId)
+ else
+ local ttl = deduplicationOpts['ttl']
+ if not deduplicationOpts['extend'] and ttl and ttl > 0 then
+ rcall('SET', deduplicationKey, jobId, 'KEEPTTL')
+ else
+ setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ end
+ end
+ return
+ else
+ storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ return currentDebounceJobId
+ end
+ else
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, jobId)
+ else
+ setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ end
+ return
+ end
+ else
+ return deduplicateJobWithoutReplace(deduplicationId, deduplicationOpts,
+ jobId, deduplicationKey, eventsKey, maxEvents, prefix, jobName, jobData, fullOpts,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ end
+ end
+end
+--[[
+ Function to store a job
+]]
+local function storeJob(eventsKey, jobIdKey, jobId, name, data, opts, timestamp,
+ parentKey, parentData, repeatJobKey)
+ local jsonOpts = cjson.encode(opts)
+ local delay = opts['delay'] or 0
+ local priority = opts['priority'] or 0
+ local debounceId = opts['de'] and opts['de']['id']
+ local optionalValues = {}
+ if parentKey ~= nil then
+ table.insert(optionalValues, "parentKey")
+ table.insert(optionalValues, parentKey)
+ table.insert(optionalValues, "parent")
+ table.insert(optionalValues, parentData)
+ end
+ if repeatJobKey then
+ table.insert(optionalValues, "rjk")
+ table.insert(optionalValues, repeatJobKey)
+ end
+ if debounceId then
+ table.insert(optionalValues, "deid")
+ table.insert(optionalValues, debounceId)
+ end
+ rcall("HMSET", jobIdKey, "name", name, "data", data, "opts", jsonOpts,
+ "timestamp", timestamp, "delay", delay, "priority", priority,
+ unpack(optionalValues))
+ rcall("XADD", eventsKey, "*", "event", "added", "jobId", jobId, "name", name)
+ return delay, priority
+end
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+--[[
+ Function to handle the case when job is duplicated.
+]]
+-- Includes
+--[[
+ This function is used to update the parent's dependencies if the job
+ is already completed and about to be ignored. The parent must get its
+ dependencies updated to avoid the parent job being stuck forever in
+ the waiting-children state.
+]]
+-- Includes
+--[[
+ Validate and move or add dependencies to parent.
+]]
+-- Includes
+--[[
+ Validate and move parent to a wait status (waiting, delayed or prioritized)
+ if no pending dependencies.
+]]
+-- Includes
+--[[
+ Validate and move parent to a wait status (waiting, delayed or prioritized) if needed.
+]]
+-- Includes
+--[[
+ Move parent to a wait status (wait, prioritized or delayed)
+]]
+-- Includes
+--[[
+ Add delay marker if needed.
+]]
+-- Includes
+--[[
+ Function to return the next delayed job timestamp.
+]]
+local function getNextDelayedTimestamp(delayedKey)
+ local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
+ if #result then
+ local nextTimestamp = tonumber(result[2])
+ if nextTimestamp ~= nil then
+ return nextTimestamp / 0x1000
+ end
+ end
+end
+local function addDelayMarkerIfNeeded(markerKey, delayedKey)
+ local nextTimestamp = getNextDelayedTimestamp(delayedKey)
+ if nextTimestamp ~= nil then
+ -- Replace the score of the marker with the newest known
+ -- next timestamp.
+ rcall("ZADD", markerKey, nextTimestamp, "1")
+ end
+end
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to check if queue is paused or maxed
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function isQueuePausedOrMaxed(queueMetaKey, activeKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency")
+ if queueAttributes[1] then
+ return true
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ return activeCount >= tonumber(queueAttributes[2])
+ end
+ end
+ return false
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+local function moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
+ local parentWaitKey = parentQueueKey .. ":wait"
+ local parentPausedKey = parentQueueKey .. ":paused"
+ local parentActiveKey = parentQueueKey .. ":active"
+ local parentMetaKey = parentQueueKey .. ":meta"
+ local parentMarkerKey = parentQueueKey .. ":marker"
+ local jobAttributes = rcall("HMGET", parentKey, "priority", "delay")
+ local priority = tonumber(jobAttributes[1]) or 0
+ local delay = tonumber(jobAttributes[2]) or 0
+ if delay > 0 then
+ local delayedTimestamp = tonumber(timestamp) + delay
+ local score = delayedTimestamp * 0x1000
+ local parentDelayedKey = parentQueueKey .. ":delayed"
+ rcall("ZADD", parentDelayedKey, score, parentId)
+ rcall("XADD", parentQueueKey .. ":events", "*", "event", "delayed", "jobId", parentId, "delay",
+ delayedTimestamp)
+ addDelayMarkerIfNeeded(parentMarkerKey, parentDelayedKey)
+ else
+ if priority == 0 then
+ local parentTarget, isParentPausedOrMaxed = getTargetQueueList(parentMetaKey, parentActiveKey,
+ parentWaitKey, parentPausedKey)
+ addJobInTargetList(parentTarget, parentMarkerKey, "RPUSH", isParentPausedOrMaxed, parentId)
+ else
+ local isPausedOrMaxed = isQueuePausedOrMaxed(parentMetaKey, parentActiveKey)
+ addJobWithPriority(parentMarkerKey, parentQueueKey .. ":prioritized", priority, parentId,
+ parentQueueKey .. ":pc", isPausedOrMaxed)
+ end
+ rcall("XADD", parentQueueKey .. ":events", "*", "event", "waiting", "jobId", parentId, "prev",
+ "waiting-children")
+ end
+end
+local function moveParentToWaitIfNeeded(parentQueueKey, parentKey, parentId, timestamp)
+ if rcall("EXISTS", parentKey) == 1 then
+ local parentWaitingChildrenKey = parentQueueKey .. ":waiting-children"
+ if rcall("ZSCORE", parentWaitingChildrenKey, parentId) then
+ rcall("ZREM", parentWaitingChildrenKey, parentId)
+ moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
+ end
+ end
+end
+local function moveParentToWaitIfNoPendingDependencies(parentQueueKey, parentDependenciesKey, parentKey,
+ parentId, timestamp)
+ local doNotHavePendingDependencies = rcall("SCARD", parentDependenciesKey) == 0
+ if doNotHavePendingDependencies then
+ moveParentToWaitIfNeeded(parentQueueKey, parentKey, parentId, timestamp)
+ end
+end
+local function updateParentDepsIfNeeded(parentKey, parentQueueKey, parentDependenciesKey,
+ parentId, jobIdKey, returnvalue, timestamp )
+ local processedSet = parentKey .. ":processed"
+ rcall("HSET", processedSet, jobIdKey, returnvalue)
+ moveParentToWaitIfNoPendingDependencies(parentQueueKey, parentDependenciesKey, parentKey, parentId, timestamp)
+end
+local function updateExistingJobsParent(parentKey, parent, parentData,
+ parentDependenciesKey, completedKey,
+ jobIdKey, jobId, timestamp)
+ if parentKey ~= nil then
+ if rcall("ZSCORE", completedKey, jobId) then
+ local returnvalue = rcall("HGET", jobIdKey, "returnvalue")
+ updateParentDepsIfNeeded(parentKey, parent['queueKey'],
+ parentDependenciesKey, parent['id'],
+ jobIdKey, returnvalue, timestamp)
+ else
+ if parentDependenciesKey ~= nil then
+ rcall("SADD", parentDependenciesKey, jobIdKey)
+ end
+ end
+ rcall("HMSET", jobIdKey, "parentKey", parentKey, "parent", parentData)
+ end
+end
+local function handleDuplicatedJob(jobKey, jobId, currentParentKey, currentParent,
+ parentData, parentDependenciesKey, completedKey, eventsKey, maxEvents, timestamp)
+ local existedParentKey = rcall("HGET", jobKey, "parentKey")
+ if not existedParentKey or existedParentKey == currentParentKey then
+ updateExistingJobsParent(currentParentKey, currentParent, parentData,
+ parentDependenciesKey, completedKey, jobKey,
+ jobId, timestamp)
+ else
+ if currentParentKey ~= nil and currentParentKey ~= existedParentKey
+ and (rcall("EXISTS", existedParentKey) == 1) then
+ return -7
+ end
+ end
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
+ "duplicated", "jobId", jobId)
+ return jobId .. "" -- convert to string
+end
+if parentKey ~= nil then
+ if rcall("EXISTS", parentKey) ~= 1 then return -5 end
+ parentData = cjson.encode(parent)
+end
+local jobCounter = rcall("INCR", idKey)
+local maxEvents = getOrSetMaxEvents(metaKey)
+local parentDependenciesKey = args[6]
+local timestamp = args[4]
+if args[2] == "" then
+ jobId = jobCounter
+ jobIdKey = args[1] .. jobId
+else
+ jobId = args[2]
+ jobIdKey = args[1] .. jobId
+ if rcall("EXISTS", jobIdKey) == 1 then
+ return handleDuplicatedJob(jobIdKey, jobId, parentKey, parent,
+ parentData, parentDependenciesKey, completedKey, eventsKey,
+ maxEvents, timestamp)
+ end
+end
+local deduplicationJobId = deduplicateJob(opts['de'], jobId, KEYS[5],
+ deduplicationKey, eventsKey, maxEvents, args[1], args[3], ARGV[2], opts,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+if deduplicationJobId then
+ return deduplicationJobId
+end
+-- Store the job.
+local delay, priority = storeJob(eventsKey, jobIdKey, jobId, args[3], ARGV[2],
+ opts, timestamp, parentKey, parentData,
+ repeatJobKey)
+-- Add the job to the prioritized set
+local isPausedOrMaxed = isQueuePausedOrMaxed(metaKey, activeKey)
+addJobWithPriority( KEYS[1], priorityKey, priority, jobId, priorityCounterKey, isPausedOrMaxed)
+-- Emit waiting event
+rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "waiting",
+ "jobId", jobId)
+-- Check if this job is a child of another job, if so add it to the parents dependencies
+if parentDependenciesKey ~= nil then
+ rcall("SADD", parentDependenciesKey, jobIdKey)
+end
+return jobId .. "" -- convert to string
+`;
+var addPrioritizedJob = {
+ name: "addPrioritizedJob",
+ content: content5,
+ keys: 9
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/addRepeatableJob-2.js
+var content6 = `--[[
+ Adds a repeatable job
+ Input:
+ KEYS[1] 'repeat' key
+ KEYS[2] 'delayed' key
+ ARGV[1] next milliseconds
+ ARGV[2] msgpacked options
+ [1] name
+ [2] tz?
+ [3] pattern?
+ [4] endDate?
+ [5] every?
+ ARGV[3] legacy custom key TODO: remove this logic in next breaking change
+ ARGV[4] custom key
+ ARGV[5] prefix key
+ Output:
+ repeatableKey - OK
+]]
+local rcall = redis.call
+local repeatKey = KEYS[1]
+local delayedKey = KEYS[2]
+local nextMillis = ARGV[1]
+local legacyCustomKey = ARGV[3]
+local customKey = ARGV[4]
+local prefixKey = ARGV[5]
+-- Includes
+--[[
+ Function to remove job.
+]]
+-- Includes
+--[[
+ Function to remove deduplication key if needed
+ when a job is being removed.
+]]
+local function removeDeduplicationKeyIfNeededOnRemoval(prefixKey,
+ jobId, deduplicationId)
+ if deduplicationId then
+ local deduplicationKey = prefixKey .. "de:" .. deduplicationId
+ local currentJobId = rcall('GET', deduplicationKey)
+ if currentJobId and currentJobId == jobId then
+ rcall("DEL", deduplicationKey)
+ -- Also clean up any pending dedup-next data for this dedup ID
+ rcall("DEL", prefixKey .. "dn:" .. deduplicationId)
+ return 1
+ end
+ end
+end
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+--[[
+ Check if this job has a parent. If so we will just remove it from
+ the parent child list, but if it is the last child we should move the parent to "wait/paused"
+ which requires code from "moveToFinished"
+]]
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Functions to destructure job key.
+ Just a bit of warning, these functions may be a bit slow and affect performance significantly.
+]]
+local getJobIdFromKey = function (jobKey)
+ return string.match(jobKey, ".*:(.*)")
+end
+local getJobKeyPrefix = function (jobKey, jobId)
+ return string.sub(jobKey, 0, #jobKey - #jobId)
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+local function _moveParentToWait(parentPrefix, parentId, emitEvent)
+ local parentTarget, isPausedOrMaxed = getTargetQueueList(parentPrefix .. "meta", parentPrefix .. "active",
+ parentPrefix .. "wait", parentPrefix .. "paused")
+ addJobInTargetList(parentTarget, parentPrefix .. "marker", "RPUSH", isPausedOrMaxed, parentId)
+ if emitEvent then
+ local parentEventStream = parentPrefix .. "events"
+ rcall("XADD", parentEventStream, "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
+ end
+end
+local function removeParentDependencyKey(jobKey, hard, parentKey, baseKey, debounceId)
+ if parentKey then
+ local parentDependenciesKey = parentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(parentKey)
+ local parentPrefix = getJobKeyPrefix(parentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then -- remove parent in same queue
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(parentKey, hard, nil, baseKey, nil)
+ removeJobKeys(parentKey)
+ if debounceId then
+ rcall("DEL", parentPrefix .. "de:" .. debounceId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ else
+ local parentAttributes = rcall("HMGET", jobKey, "parentKey", "deid")
+ local missedParentKey = parentAttributes[1]
+ if( (type(missedParentKey) == "string") and missedParentKey ~= ""
+ and (rcall("EXISTS", missedParentKey) == 1)) then
+ local parentDependenciesKey = missedParentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(missedParentKey)
+ local parentPrefix = getJobKeyPrefix(missedParentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(missedParentKey, hard, nil, baseKey, nil)
+ removeJobKeys(missedParentKey)
+ if parentAttributes[2] then
+ rcall("DEL", parentPrefix .. "de:" .. parentAttributes[2])
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ end
+ end
+ return false
+end
+local function removeJob(jobId, hard, baseKey, shouldRemoveDeduplicationKey)
+ local jobKey = baseKey .. jobId
+ removeParentDependencyKey(jobKey, hard, nil, baseKey)
+ if shouldRemoveDeduplicationKey then
+ local deduplicationId = rcall("HGET", jobKey, "deid")
+ removeDeduplicationKeyIfNeededOnRemoval(baseKey, jobId, deduplicationId)
+ end
+ removeJobKeys(jobKey)
+end
+local function storeRepeatableJob(repeatKey, customKey, nextMillis, rawOpts)
+ rcall("ZADD", repeatKey, nextMillis, customKey)
+ local opts = cmsgpack.unpack(rawOpts)
+ local optionalValues = {}
+ if opts['tz'] then
+ table.insert(optionalValues, "tz")
+ table.insert(optionalValues, opts['tz'])
+ end
+ if opts['pattern'] then
+ table.insert(optionalValues, "pattern")
+ table.insert(optionalValues, opts['pattern'])
+ end
+ if opts['endDate'] then
+ table.insert(optionalValues, "endDate")
+ table.insert(optionalValues, opts['endDate'])
+ end
+ if opts['every'] then
+ table.insert(optionalValues, "every")
+ table.insert(optionalValues, opts['every'])
+ end
+ rcall("HMSET", repeatKey .. ":" .. customKey, "name", opts['name'],
+ unpack(optionalValues))
+ return customKey
+end
+-- If we are overriding a repeatable job we must delete the delayed job for
+-- the next iteration.
+local prevMillis = rcall("ZSCORE", repeatKey, customKey)
+if prevMillis then
+ local delayedJobId = "repeat:" .. customKey .. ":" .. prevMillis
+ local nextDelayedJobId = repeatKey .. ":" .. customKey .. ":" .. nextMillis
+ if rcall("ZSCORE", delayedKey, delayedJobId)
+ and rcall("EXISTS", nextDelayedJobId) ~= 1 then
+ removeJob(delayedJobId, true, prefixKey, true --[[remove debounce key]])
+ rcall("ZREM", delayedKey, delayedJobId)
+ end
+end
+-- Keep backwards compatibility with old repeatable jobs (<= 3.0.0)
+if rcall("ZSCORE", repeatKey, legacyCustomKey) ~= false then
+ return storeRepeatableJob(repeatKey, legacyCustomKey, nextMillis, ARGV[2])
+end
+return storeRepeatableJob(repeatKey, customKey, nextMillis, ARGV[2])
+`;
+var addRepeatableJob = {
+ name: "addRepeatableJob",
+ content: content6,
+ keys: 2
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/addStandardJob-9.js
+var content7 = `--[[
+ Adds a job to the queue by doing the following:
+ - Increases the job counter if needed.
+ - Creates a new job key with the job data.
+ - if delayed:
+ - computes timestamp.
+ - adds to delayed zset.
+ - Emits a global event 'delayed' if the job is delayed.
+ - if not delayed
+ - Adds the jobId to the wait/paused list in one of three ways:
+ - LIFO
+ - FIFO
+ - prioritized.
+ - Adds the job to the "added" list so that workers gets notified.
+ Input:
+ KEYS[1] 'wait',
+ KEYS[2] 'paused'
+ KEYS[3] 'meta'
+ KEYS[4] 'id'
+ KEYS[5] 'completed'
+ KEYS[6] 'delayed'
+ KEYS[7] 'active'
+ KEYS[8] events stream key
+ KEYS[9] marker key
+ ARGV[1] msgpacked arguments array
+ [1] key prefix,
+ [2] custom id (will not generate one automatically)
+ [3] name
+ [4] timestamp
+ [5] parentKey?
+ [6] parent dependencies key.
+ [7] parent? {id, queueKey}
+ [8] repeat job key
+ [9] deduplication key
+ ARGV[2] Json stringified job data
+ ARGV[3] msgpacked options
+ Output:
+ jobId - OK
+ -5 - Missing parent key
+]]
+local eventsKey = KEYS[8]
+local jobId
+local jobIdKey
+local rcall = redis.call
+local args = cmsgpack.unpack(ARGV[1])
+local data = ARGV[2]
+local opts = cmsgpack.unpack(ARGV[3])
+local parentKey = args[5]
+local parent = args[7]
+local repeatJobKey = args[8]
+local deduplicationKey = args[9]
+local parentData
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to debounce a job.
+]]
+-- Includes
+--[[
+ Function to deduplicate a job.
+]]
+--[[
+ Function to set the deduplication key for a job.
+ Uses TTL from deduplication opts if provided.
+]]
+local function setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ local ttl = deduplicationOpts and deduplicationOpts['ttl']
+ if ttl and ttl > 0 then
+ rcall('SET', deduplicationKey, jobId, 'PX', ttl)
+ else
+ rcall('SET', deduplicationKey, jobId)
+ end
+end
+--[[
+ Function to store a deduplicated next job if the existing job is active
+ and keepLastIfActive is set. When the active job finishes, the stored
+ proto-job is used to create a real job in the queue.
+ Returns true if the proto-job was stored, false otherwise.
+]]
+--[[
+ Function to check if an item belongs to a list.
+]]
+local function checkItemInList(list, item)
+ for _, v in pairs(list) do
+ if v == item then
+ return 1
+ end
+ end
+ return nil
+end
+local function storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ if deduplicationOpts['keepLastIfActive'] and currentDebounceJobId then
+ local activeKey = prefix .. "active"
+ local activeItems = rcall('LRANGE', activeKey, 0, -1)
+ if checkItemInList(activeItems, currentDebounceJobId) then
+ local deduplicationNextKey = prefix .. "dn:" .. deduplicationId
+ local fields = {'name', jobName, 'data', jobData, 'opts', cjson.encode(fullOpts)}
+ if parentKey then
+ fields[#fields+1] = 'pk'
+ fields[#fields+1] = parentKey
+ end
+ if parentData then
+ fields[#fields+1] = 'pd'
+ fields[#fields+1] = parentData
+ end
+ if parentDependenciesKey then
+ fields[#fields+1] = 'pdk'
+ fields[#fields+1] = parentDependenciesKey
+ end
+ if repeatJobKey then
+ fields[#fields+1] = 'rjk'
+ fields[#fields+1] = repeatJobKey
+ end
+ rcall('HSET', deduplicationNextKey, unpack(fields))
+ -- Ensure the dedup key does not expire while the job is active,
+ -- so subsequent adds always hit the dedup path and never bypass
+ -- the active-check because of a TTL expiry.
+ local deduplicationKey = prefix .. "de:" .. deduplicationId
+ rcall('PERSIST', deduplicationKey)
+ -- TODO remove debounced event in next breaking change
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced", "jobId",
+ currentDebounceJobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ currentDebounceJobId, "deduplicationId", deduplicationId, "deduplicatedJobId", jobId)
+ return true
+ end
+ end
+ return false
+end
+local function deduplicateJobWithoutReplace(deduplicationId, deduplicationOpts, jobId, deduplicationKey,
+ eventsKey, maxEvents, prefix, jobName, jobData, fullOpts,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ local ttl = deduplicationOpts['ttl']
+ local deduplicationKeyExists
+ if ttl and ttl > 0 then
+ if deduplicationOpts['extend'] then
+ local currentDebounceJobId = rcall('GET', deduplicationKey)
+ if currentDebounceJobId then
+ if storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey) then
+ return currentDebounceJobId
+ end
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, currentDebounceJobId)
+ else
+ setDeduplicationKey(deduplicationKey, currentDebounceJobId, deduplicationOpts)
+ end
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced",
+ "jobId", currentDebounceJobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ currentDebounceJobId, "deduplicationId", deduplicationId, "deduplicatedJobId", jobId)
+ return currentDebounceJobId
+ else
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, jobId)
+ else
+ setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ end
+ return
+ end
+ else
+ if deduplicationOpts['keepLastIfActive'] then
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'NX')
+ else
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'PX', ttl, 'NX')
+ end
+ end
+ else
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'NX')
+ end
+ if deduplicationKeyExists then
+ local currentDebounceJobId = rcall('GET', deduplicationKey)
+ if storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey) then
+ return currentDebounceJobId
+ end
+ -- TODO remove debounced event in next breaking change
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced", "jobId",
+ currentDebounceJobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ currentDebounceJobId, "deduplicationId", deduplicationId, "deduplicatedJobId", jobId)
+ return currentDebounceJobId
+ end
+end
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+local function removeDelayedJob(delayedKey, deduplicationKey, eventsKey, maxEvents, currentDeduplicatedJobId,
+ jobId, deduplicationId, prefix)
+ if rcall("ZREM", delayedKey, currentDeduplicatedJobId) > 0 then
+ removeJobKeys(prefix .. currentDeduplicatedJobId)
+ rcall("XADD", eventsKey, "*", "event", "removed", "jobId", currentDeduplicatedJobId,
+ "prev", "delayed")
+ -- TODO remove debounced event in next breaking change
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "debounced", "jobId",
+ jobId, "debounceId", deduplicationId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "deduplicated", "jobId",
+ jobId, "deduplicationId", deduplicationId, "deduplicatedJobId", currentDeduplicatedJobId)
+ return true
+ end
+ return false
+end
+local function deduplicateJob(deduplicationOpts, jobId, delayedKey, deduplicationKey, eventsKey, maxEvents,
+ prefix, jobName, jobData, fullOpts, parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ local deduplicationId = deduplicationOpts and deduplicationOpts['id']
+ if deduplicationId then
+ if deduplicationOpts['replace'] then
+ local currentDebounceJobId = rcall('GET', deduplicationKey)
+ if currentDebounceJobId then
+ local isRemoved = removeDelayedJob(delayedKey, deduplicationKey, eventsKey, maxEvents,
+ currentDebounceJobId, jobId, deduplicationId, prefix)
+ if isRemoved then
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, jobId)
+ else
+ local ttl = deduplicationOpts['ttl']
+ if not deduplicationOpts['extend'] and ttl and ttl > 0 then
+ rcall('SET', deduplicationKey, jobId, 'KEEPTTL')
+ else
+ setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ end
+ end
+ return
+ else
+ storeDeduplicatedNextJob(deduplicationOpts, currentDebounceJobId, prefix,
+ deduplicationId, jobName, jobData, fullOpts, eventsKey, maxEvents, jobId,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ return currentDebounceJobId
+ end
+ else
+ if deduplicationOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, jobId)
+ else
+ setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ end
+ return
+ end
+ else
+ return deduplicateJobWithoutReplace(deduplicationId, deduplicationOpts,
+ jobId, deduplicationKey, eventsKey, maxEvents, prefix, jobName, jobData, fullOpts,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+ end
+ end
+end
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+--[[
+ Function to handle the case when job is duplicated.
+]]
+-- Includes
+--[[
+ This function is used to update the parent's dependencies if the job
+ is already completed and about to be ignored. The parent must get its
+ dependencies updated to avoid the parent job being stuck forever in
+ the waiting-children state.
+]]
+-- Includes
+--[[
+ Validate and move or add dependencies to parent.
+]]
+-- Includes
+--[[
+ Validate and move parent to a wait status (waiting, delayed or prioritized)
+ if no pending dependencies.
+]]
+-- Includes
+--[[
+ Validate and move parent to a wait status (waiting, delayed or prioritized) if needed.
+]]
+-- Includes
+--[[
+ Move parent to a wait status (wait, prioritized or delayed)
+]]
+-- Includes
+--[[
+ Add delay marker if needed.
+]]
+-- Includes
+--[[
+ Function to return the next delayed job timestamp.
+]]
+local function getNextDelayedTimestamp(delayedKey)
+ local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
+ if #result then
+ local nextTimestamp = tonumber(result[2])
+ if nextTimestamp ~= nil then
+ return nextTimestamp / 0x1000
+ end
+ end
+end
+local function addDelayMarkerIfNeeded(markerKey, delayedKey)
+ local nextTimestamp = getNextDelayedTimestamp(delayedKey)
+ if nextTimestamp ~= nil then
+ -- Replace the score of the marker with the newest known
+ -- next timestamp.
+ rcall("ZADD", markerKey, nextTimestamp, "1")
+ end
+end
+--[[
+ Function to add job considering priority.
+]]
+-- Includes
+--[[
+ Function to get priority score.
+]]
+local function getPriorityScore(priority, priorityCounterKey)
+ local prioCounter = rcall("INCR", priorityCounterKey)
+ return priority * 0x100000000 + prioCounter % 0x100000000
+end
+local function addJobWithPriority(markerKey, prioritizedKey, priority, jobId, priorityCounterKey,
+ isPausedOrMaxed)
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to check if queue is paused or maxed
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function isQueuePausedOrMaxed(queueMetaKey, activeKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency")
+ if queueAttributes[1] then
+ return true
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ return activeCount >= tonumber(queueAttributes[2])
+ end
+ end
+ return false
+end
+local function moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
+ local parentWaitKey = parentQueueKey .. ":wait"
+ local parentPausedKey = parentQueueKey .. ":paused"
+ local parentActiveKey = parentQueueKey .. ":active"
+ local parentMetaKey = parentQueueKey .. ":meta"
+ local parentMarkerKey = parentQueueKey .. ":marker"
+ local jobAttributes = rcall("HMGET", parentKey, "priority", "delay")
+ local priority = tonumber(jobAttributes[1]) or 0
+ local delay = tonumber(jobAttributes[2]) or 0
+ if delay > 0 then
+ local delayedTimestamp = tonumber(timestamp) + delay
+ local score = delayedTimestamp * 0x1000
+ local parentDelayedKey = parentQueueKey .. ":delayed"
+ rcall("ZADD", parentDelayedKey, score, parentId)
+ rcall("XADD", parentQueueKey .. ":events", "*", "event", "delayed", "jobId", parentId, "delay",
+ delayedTimestamp)
+ addDelayMarkerIfNeeded(parentMarkerKey, parentDelayedKey)
+ else
+ if priority == 0 then
+ local parentTarget, isParentPausedOrMaxed = getTargetQueueList(parentMetaKey, parentActiveKey,
+ parentWaitKey, parentPausedKey)
+ addJobInTargetList(parentTarget, parentMarkerKey, "RPUSH", isParentPausedOrMaxed, parentId)
+ else
+ local isPausedOrMaxed = isQueuePausedOrMaxed(parentMetaKey, parentActiveKey)
+ addJobWithPriority(parentMarkerKey, parentQueueKey .. ":prioritized", priority, parentId,
+ parentQueueKey .. ":pc", isPausedOrMaxed)
+ end
+ rcall("XADD", parentQueueKey .. ":events", "*", "event", "waiting", "jobId", parentId, "prev",
+ "waiting-children")
+ end
+end
+local function moveParentToWaitIfNeeded(parentQueueKey, parentKey, parentId, timestamp)
+ if rcall("EXISTS", parentKey) == 1 then
+ local parentWaitingChildrenKey = parentQueueKey .. ":waiting-children"
+ if rcall("ZSCORE", parentWaitingChildrenKey, parentId) then
+ rcall("ZREM", parentWaitingChildrenKey, parentId)
+ moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
+ end
+ end
+end
+local function moveParentToWaitIfNoPendingDependencies(parentQueueKey, parentDependenciesKey, parentKey,
+ parentId, timestamp)
+ local doNotHavePendingDependencies = rcall("SCARD", parentDependenciesKey) == 0
+ if doNotHavePendingDependencies then
+ moveParentToWaitIfNeeded(parentQueueKey, parentKey, parentId, timestamp)
+ end
+end
+local function updateParentDepsIfNeeded(parentKey, parentQueueKey, parentDependenciesKey,
+ parentId, jobIdKey, returnvalue, timestamp )
+ local processedSet = parentKey .. ":processed"
+ rcall("HSET", processedSet, jobIdKey, returnvalue)
+ moveParentToWaitIfNoPendingDependencies(parentQueueKey, parentDependenciesKey, parentKey, parentId, timestamp)
+end
+local function updateExistingJobsParent(parentKey, parent, parentData,
+ parentDependenciesKey, completedKey,
+ jobIdKey, jobId, timestamp)
+ if parentKey ~= nil then
+ if rcall("ZSCORE", completedKey, jobId) then
+ local returnvalue = rcall("HGET", jobIdKey, "returnvalue")
+ updateParentDepsIfNeeded(parentKey, parent['queueKey'],
+ parentDependenciesKey, parent['id'],
+ jobIdKey, returnvalue, timestamp)
+ else
+ if parentDependenciesKey ~= nil then
+ rcall("SADD", parentDependenciesKey, jobIdKey)
+ end
+ end
+ rcall("HMSET", jobIdKey, "parentKey", parentKey, "parent", parentData)
+ end
+end
+local function handleDuplicatedJob(jobKey, jobId, currentParentKey, currentParent,
+ parentData, parentDependenciesKey, completedKey, eventsKey, maxEvents, timestamp)
+ local existedParentKey = rcall("HGET", jobKey, "parentKey")
+ if not existedParentKey or existedParentKey == currentParentKey then
+ updateExistingJobsParent(currentParentKey, currentParent, parentData,
+ parentDependenciesKey, completedKey, jobKey,
+ jobId, timestamp)
+ else
+ if currentParentKey ~= nil and currentParentKey ~= existedParentKey
+ and (rcall("EXISTS", existedParentKey) == 1) then
+ return -7
+ end
+ end
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
+ "duplicated", "jobId", jobId)
+ return jobId .. "" -- convert to string
+end
+--[[
+ Function to store a job
+]]
+local function storeJob(eventsKey, jobIdKey, jobId, name, data, opts, timestamp,
+ parentKey, parentData, repeatJobKey)
+ local jsonOpts = cjson.encode(opts)
+ local delay = opts['delay'] or 0
+ local priority = opts['priority'] or 0
+ local debounceId = opts['de'] and opts['de']['id']
+ local optionalValues = {}
+ if parentKey ~= nil then
+ table.insert(optionalValues, "parentKey")
+ table.insert(optionalValues, parentKey)
+ table.insert(optionalValues, "parent")
+ table.insert(optionalValues, parentData)
+ end
+ if repeatJobKey then
+ table.insert(optionalValues, "rjk")
+ table.insert(optionalValues, repeatJobKey)
+ end
+ if debounceId then
+ table.insert(optionalValues, "deid")
+ table.insert(optionalValues, debounceId)
+ end
+ rcall("HMSET", jobIdKey, "name", name, "data", data, "opts", jsonOpts,
+ "timestamp", timestamp, "delay", delay, "priority", priority,
+ unpack(optionalValues))
+ rcall("XADD", eventsKey, "*", "event", "added", "jobId", jobId, "name", name)
+ return delay, priority
+end
+if parentKey ~= nil then
+ if rcall("EXISTS", parentKey) ~= 1 then return -5 end
+ parentData = cjson.encode(parent)
+end
+local jobCounter = rcall("INCR", KEYS[4])
+local metaKey = KEYS[3]
+local maxEvents = getOrSetMaxEvents(metaKey)
+local parentDependenciesKey = args[6]
+local timestamp = args[4]
+if args[2] == "" then
+ jobId = jobCounter
+ jobIdKey = args[1] .. jobId
+else
+ jobId = args[2]
+ jobIdKey = args[1] .. jobId
+ if rcall("EXISTS", jobIdKey) == 1 then
+ return handleDuplicatedJob(jobIdKey, jobId, parentKey, parent,
+ parentData, parentDependenciesKey, KEYS[5], eventsKey,
+ maxEvents, timestamp)
+ end
+end
+local deduplicationJobId = deduplicateJob(opts['de'], jobId, KEYS[6],
+ deduplicationKey, eventsKey, maxEvents, args[1], args[3], ARGV[2], opts,
+ parentKey, parentData, parentDependenciesKey, repeatJobKey)
+if deduplicationJobId then
+ return deduplicationJobId
+end
+-- Store the job.
+storeJob(eventsKey, jobIdKey, jobId, args[3], ARGV[2], opts, timestamp,
+ parentKey, parentData, repeatJobKey)
+local target, isPausedOrMaxed = getTargetQueueList(metaKey, KEYS[7], KEYS[1], KEYS[2])
+-- LIFO or FIFO
+local pushCmd = opts['lifo'] and 'RPUSH' or 'LPUSH'
+addJobInTargetList(target, KEYS[9], pushCmd, isPausedOrMaxed, jobId)
+-- Emit waiting event
+rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "waiting",
+ "jobId", jobId)
+-- Check if this job is a child of another job, if so add it to the parents dependencies
+if parentDependenciesKey ~= nil then
+ rcall("SADD", parentDependenciesKey, jobIdKey)
+end
+return jobId .. "" -- convert to string
+`;
+var addStandardJob = {
+ name: "addStandardJob",
+ content: content7,
+ keys: 9
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/changeDelay-4.js
+var content8 = `--[[
+ Change job delay when it is in delayed set.
+ Input:
+ KEYS[1] delayed key
+ KEYS[2] meta key
+ KEYS[3] marker key
+ KEYS[4] events stream
+ ARGV[1] delay
+ ARGV[2] timestamp
+ ARGV[3] the id of the job
+ ARGV[4] job key
+ Output:
+ 0 - OK
+ -1 - Missing job.
+ -3 - Job not in delayed set.
+ Events:
+ - delayed key.
+]]
+local rcall = redis.call
+-- Includes
+--[[
+ Add delay marker if needed.
+]]
+-- Includes
+--[[
+ Function to return the next delayed job timestamp.
+]]
+local function getNextDelayedTimestamp(delayedKey)
+ local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
+ if #result then
+ local nextTimestamp = tonumber(result[2])
+ if nextTimestamp ~= nil then
+ return nextTimestamp / 0x1000
+ end
+ end
+end
+local function addDelayMarkerIfNeeded(markerKey, delayedKey)
+ local nextTimestamp = getNextDelayedTimestamp(delayedKey)
+ if nextTimestamp ~= nil then
+ -- Replace the score of the marker with the newest known
+ -- next timestamp.
+ rcall("ZADD", markerKey, nextTimestamp, "1")
+ end
+end
+--[[
+ Bake in the job id first 12 bits into the timestamp
+ to guarantee correct execution order of delayed jobs
+ (up to 4096 jobs per given timestamp or 4096 jobs apart per timestamp)
+ WARNING: Jobs that are so far apart that they wrap around will cause FIFO to fail
+]]
+local function getDelayedScore(delayedKey, timestamp, delay)
+ local delayedTimestamp = (delay > 0 and (tonumber(timestamp) + delay)) or tonumber(timestamp)
+ local minScore = delayedTimestamp * 0x1000
+ local maxScore = (delayedTimestamp + 1 ) * 0x1000 - 1
+ local result = rcall("ZREVRANGEBYSCORE", delayedKey, maxScore,
+ minScore, "WITHSCORES","LIMIT", 0, 1)
+ if #result then
+ local currentMaxScore = tonumber(result[2])
+ if currentMaxScore ~= nil then
+ if currentMaxScore >= maxScore then
+ return maxScore, delayedTimestamp
+ else
+ return currentMaxScore + 1, delayedTimestamp
+ end
+ end
+ end
+ return minScore, delayedTimestamp
+end
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+if rcall("EXISTS", ARGV[4]) == 1 then
+ local jobId = ARGV[3]
+ local delay = tonumber(ARGV[1])
+ local score, delayedTimestamp = getDelayedScore(KEYS[1], ARGV[2], delay)
+ local numRemovedElements = rcall("ZREM", KEYS[1], jobId)
+ if numRemovedElements < 1 then
+ return -3
+ end
+ rcall("HSET", ARGV[4], "delay", delay)
+ rcall("ZADD", KEYS[1], score, jobId)
+ local maxEvents = getOrSetMaxEvents(KEYS[2])
+ rcall("XADD", KEYS[4], "MAXLEN", "~", maxEvents, "*", "event", "delayed",
+ "jobId", jobId, "delay", delayedTimestamp)
+ -- mark that a delayed job is available
+ addDelayMarkerIfNeeded(KEYS[3], KEYS[1])
+ return 0
+else
+ return -1
+end`;
+var changeDelay = {
+ name: "changeDelay",
+ content: content8,
+ keys: 4
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/changePriority-7.js
+var content9 = `--[[
+ Change job priority
+ Input:
+ KEYS[1] 'wait',
+ KEYS[2] 'paused'
+ KEYS[3] 'meta'
+ KEYS[4] 'prioritized'
+ KEYS[5] 'active'
+ KEYS[6] 'pc' priority counter
+ KEYS[7] 'marker'
+ ARGV[1] priority value
+ ARGV[2] prefix key
+ ARGV[3] job id
+ ARGV[4] lifo
+ Output:
+ 0 - OK
+ -1 - Missing job
+]]
+local jobId = ARGV[3]
+local jobKey = ARGV[2] .. jobId
+local priority = tonumber(ARGV[1])
+local rcall = redis.call
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to add job considering priority.
+]]
+-- Includes
+--[[
+ Function to get priority score.
+]]
+local function getPriorityScore(priority, priorityCounterKey)
+ local prioCounter = rcall("INCR", priorityCounterKey)
+ return priority * 0x100000000 + prioCounter % 0x100000000
+end
+local function addJobWithPriority(markerKey, prioritizedKey, priority, jobId, priorityCounterKey,
+ isPausedOrMaxed)
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+--[[
+ Function to push back job considering priority in front of same prioritized jobs.
+]]
+local function pushBackJobWithPriority(prioritizedKey, priority, jobId)
+ -- in order to put it at front of same prioritized jobs
+ -- we consider prioritized counter as 0
+ local score = priority * 0x100000000
+ rcall("ZADD", prioritizedKey, score, jobId)
+end
+local function reAddJobWithNewPriority( prioritizedKey, markerKey, targetKey,
+ priorityCounter, lifo, priority, jobId, isPausedOrMaxed)
+ if priority == 0 then
+ local pushCmd = lifo and 'RPUSH' or 'LPUSH'
+ addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ else
+ if lifo then
+ pushBackJobWithPriority(prioritizedKey, priority, jobId)
+ else
+ addJobWithPriority(markerKey, prioritizedKey, priority, jobId,
+ priorityCounter, isPausedOrMaxed)
+ end
+ end
+end
+if rcall("EXISTS", jobKey) == 1 then
+ local metaKey = KEYS[3]
+ local target, isPausedOrMaxed = getTargetQueueList(metaKey, KEYS[5], KEYS[1], KEYS[2])
+ local prioritizedKey = KEYS[4]
+ local priorityCounterKey = KEYS[6]
+ local markerKey = KEYS[7]
+ -- Re-add with the new priority
+ if rcall("ZREM", prioritizedKey, jobId) > 0 then
+ reAddJobWithNewPriority( prioritizedKey, markerKey, target,
+ priorityCounterKey, ARGV[4] == '1', priority, jobId, isPausedOrMaxed)
+ elseif rcall("LREM", target, -1, jobId) > 0 then
+ reAddJobWithNewPriority( prioritizedKey, markerKey, target,
+ priorityCounterKey, ARGV[4] == '1', priority, jobId, isPausedOrMaxed)
+ end
+ rcall("HSET", jobKey, "priority", priority)
+ return 0
+else
+ return -1
+end
+`;
+var changePriority = {
+ name: "changePriority",
+ content: content9,
+ keys: 7
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/cleanJobsInSet-3.js
+var content10 = `--[[
+ Remove jobs from the specific set.
+ Input:
+ KEYS[1] set key,
+ KEYS[2] events stream key
+ KEYS[3] repeat key
+ ARGV[1] jobKey prefix
+ ARGV[2] timestamp
+ ARGV[3] limit the number of jobs to be removed. 0 is unlimited
+ ARGV[4] set name, can be any of 'wait', 'active', 'paused', 'delayed', 'completed', or 'failed'
+]]
+local rcall = redis.call
+local repeatKey = KEYS[3]
+local rangeStart = 0
+local rangeEnd = -1
+local limit = tonumber(ARGV[3])
+-- If we're only deleting _n_ items, avoid retrieving all items
+-- for faster performance
+--
+-- Start from the tail of the list, since that's where oldest elements
+-- are generally added for FIFO lists
+if limit > 0 then
+ rangeStart = -1 - limit + 1
+ rangeEnd = -1
+end
+-- Includes
+--[[
+ Function to clean job list.
+ Returns jobIds and deleted count number.
+]]
+-- Includes
+--[[
+ Function to get the latest saved timestamp.
+]]
+local function getTimestamp(jobKey, attributes)
+ if #attributes == 1 then
+ return rcall("HGET", jobKey, attributes[1])
+ end
+ local jobTs
+ for _, ts in ipairs(rcall("HMGET", jobKey, unpack(attributes))) do
+ if (ts) then
+ jobTs = ts
+ break
+ end
+ end
+ return jobTs
+end
+--[[
+ Function to check if the job belongs to a job scheduler and
+ current delayed job matches with jobId
+]]
+local function isJobSchedulerJob(jobId, jobKey, jobSchedulersKey)
+ local repeatJobKey = rcall("HGET", jobKey, "rjk")
+ if repeatJobKey then
+ local prevMillis = rcall("ZSCORE", jobSchedulersKey, repeatJobKey)
+ if prevMillis then
+ local currentDelayedJobId = "repeat:" .. repeatJobKey .. ":" .. prevMillis
+ return jobId == currentDelayedJobId
+ end
+ end
+ return false
+end
+--[[
+ Function to remove job.
+]]
+-- Includes
+--[[
+ Function to remove deduplication key if needed
+ when a job is being removed.
+]]
+local function removeDeduplicationKeyIfNeededOnRemoval(prefixKey,
+ jobId, deduplicationId)
+ if deduplicationId then
+ local deduplicationKey = prefixKey .. "de:" .. deduplicationId
+ local currentJobId = rcall('GET', deduplicationKey)
+ if currentJobId and currentJobId == jobId then
+ rcall("DEL", deduplicationKey)
+ -- Also clean up any pending dedup-next data for this dedup ID
+ rcall("DEL", prefixKey .. "dn:" .. deduplicationId)
+ return 1
+ end
+ end
+end
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+--[[
+ Check if this job has a parent. If so we will just remove it from
+ the parent child list, but if it is the last child we should move the parent to "wait/paused"
+ which requires code from "moveToFinished"
+]]
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Functions to destructure job key.
+ Just a bit of warning, these functions may be a bit slow and affect performance significantly.
+]]
+local getJobIdFromKey = function (jobKey)
+ return string.match(jobKey, ".*:(.*)")
+end
+local getJobKeyPrefix = function (jobKey, jobId)
+ return string.sub(jobKey, 0, #jobKey - #jobId)
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+local function _moveParentToWait(parentPrefix, parentId, emitEvent)
+ local parentTarget, isPausedOrMaxed = getTargetQueueList(parentPrefix .. "meta", parentPrefix .. "active",
+ parentPrefix .. "wait", parentPrefix .. "paused")
+ addJobInTargetList(parentTarget, parentPrefix .. "marker", "RPUSH", isPausedOrMaxed, parentId)
+ if emitEvent then
+ local parentEventStream = parentPrefix .. "events"
+ rcall("XADD", parentEventStream, "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
+ end
+end
+local function removeParentDependencyKey(jobKey, hard, parentKey, baseKey, debounceId)
+ if parentKey then
+ local parentDependenciesKey = parentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(parentKey)
+ local parentPrefix = getJobKeyPrefix(parentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then -- remove parent in same queue
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(parentKey, hard, nil, baseKey, nil)
+ removeJobKeys(parentKey)
+ if debounceId then
+ rcall("DEL", parentPrefix .. "de:" .. debounceId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ else
+ local parentAttributes = rcall("HMGET", jobKey, "parentKey", "deid")
+ local missedParentKey = parentAttributes[1]
+ if( (type(missedParentKey) == "string") and missedParentKey ~= ""
+ and (rcall("EXISTS", missedParentKey) == 1)) then
+ local parentDependenciesKey = missedParentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(missedParentKey)
+ local parentPrefix = getJobKeyPrefix(missedParentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(missedParentKey, hard, nil, baseKey, nil)
+ removeJobKeys(missedParentKey)
+ if parentAttributes[2] then
+ rcall("DEL", parentPrefix .. "de:" .. parentAttributes[2])
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ end
+ end
+ return false
+end
+local function removeJob(jobId, hard, baseKey, shouldRemoveDeduplicationKey)
+ local jobKey = baseKey .. jobId
+ removeParentDependencyKey(jobKey, hard, nil, baseKey)
+ if shouldRemoveDeduplicationKey then
+ local deduplicationId = rcall("HGET", jobKey, "deid")
+ removeDeduplicationKeyIfNeededOnRemoval(baseKey, jobId, deduplicationId)
+ end
+ removeJobKeys(jobKey)
+end
+local function cleanList(listKey, jobKeyPrefix, rangeStart, rangeEnd,
+ timestamp, isWaiting, jobSchedulersKey)
+ local jobs = rcall("LRANGE", listKey, rangeStart, rangeEnd)
+ local deleted = {}
+ local deletedCount = 0
+ local jobTS
+ local deletionMarker = ''
+ local jobIdsLen = #jobs
+ for i, job in ipairs(jobs) do
+ if limit > 0 and deletedCount >= limit then
+ break
+ end
+ local jobKey = jobKeyPrefix .. job
+ if (isWaiting or rcall("EXISTS", jobKey .. ":lock") == 0) and
+ not isJobSchedulerJob(job, jobKey, jobSchedulersKey) then
+ -- Find the right timestamp of the job to compare to maxTimestamp:
+ -- * finishedOn says when the job was completed, but it isn't set unless the job has actually completed
+ -- * processedOn represents when the job was last attempted, but it doesn't get populated until
+ -- the job is first tried
+ -- * timestamp is the original job submission time
+ -- Fetch all three of these (in that order) and use the first one that is set so that we'll leave jobs
+ -- that have been active within the grace period:
+ jobTS = getTimestamp(jobKey, {"finishedOn", "processedOn", "timestamp"})
+ if (not jobTS or jobTS <= timestamp) then
+ -- replace the entry with a deletion marker; the actual deletion will
+ -- occur at the end of the script
+ rcall("LSET", listKey, rangeEnd - jobIdsLen + i, deletionMarker)
+ removeJob(job, true, jobKeyPrefix, true --[[remove debounce key]])
+ deletedCount = deletedCount + 1
+ table.insert(deleted, job)
+ end
+ end
+ end
+ rcall("LREM", listKey, 0, deletionMarker)
+ return {deleted, deletedCount}
+end
+--[[
+ Function to clean job set.
+ Returns jobIds and deleted count number.
+]]
+-- Includes
+--[[
+ Function to loop in batches.
+ Just a bit of warning, some commands as ZREM
+ could receive a maximum of 7000 parameters per call.
+]]
+local function batches(n, batchSize)
+ local i = 0
+ return function()
+ local from = i * batchSize + 1
+ i = i + 1
+ if (from <= n) then
+ local to = math.min(from + batchSize - 1, n)
+ return from, to
+ end
+ end
+end
+--[[
+ We use ZRANGEBYSCORE to make the case where we're deleting a limited number
+ of items in a sorted set only run a single iteration. If we simply used
+ ZRANGE, we may take a long time traversing through jobs that are within the
+ grace period.
+]]
+local function getJobsInZset(zsetKey, rangeEnd, limit)
+ if limit > 0 then
+ return rcall("ZRANGEBYSCORE", zsetKey, 0, rangeEnd, "LIMIT", 0, limit)
+ else
+ return rcall("ZRANGEBYSCORE", zsetKey, 0, rangeEnd)
+ end
+end
+local function cleanSet(
+ setKey,
+ jobKeyPrefix,
+ rangeEnd,
+ timestamp,
+ limit,
+ attributes,
+ isFinished,
+ jobSchedulersKey)
+ local jobs = getJobsInZset(setKey, rangeEnd, limit)
+ local deleted = {}
+ local deletedCount = 0
+ local jobTS
+ for i, job in ipairs(jobs) do
+ if limit > 0 and deletedCount >= limit then
+ break
+ end
+ local jobKey = jobKeyPrefix .. job
+ -- Extract a Job Scheduler Id from jobId ("repeat:job-scheduler-id:millis")
+ -- and check if it is in the scheduled jobs
+ if not (jobSchedulersKey and isJobSchedulerJob(job, jobKey, jobSchedulersKey)) then
+ if isFinished then
+ removeJob(job, true, jobKeyPrefix, true --[[remove debounce key]] )
+ deletedCount = deletedCount + 1
+ table.insert(deleted, job)
+ else
+ -- * finishedOn says when the job was completed, but it isn't set unless the job has actually completed
+ jobTS = getTimestamp(jobKey, attributes)
+ if (not jobTS or jobTS <= timestamp) then
+ removeJob(job, true, jobKeyPrefix, true --[[remove debounce key]] )
+ deletedCount = deletedCount + 1
+ table.insert(deleted, job)
+ end
+ end
+ end
+ end
+ if (#deleted > 0) then
+ for from, to in batches(#deleted, 7000) do
+ rcall("ZREM", setKey, unpack(deleted, from, to))
+ end
+ end
+ return {deleted, deletedCount}
+end
+local result
+if ARGV[4] == "active" then
+ result = cleanList(KEYS[1], ARGV[1], rangeStart, rangeEnd, ARGV[2], false --[[ hasFinished ]],
+ repeatKey)
+elseif ARGV[4] == "delayed" then
+ rangeEnd = "+inf"
+ result = cleanSet(KEYS[1], ARGV[1], rangeEnd, ARGV[2], limit,
+ {"processedOn", "timestamp"}, false --[[ hasFinished ]], repeatKey)
+elseif ARGV[4] == "prioritized" then
+ rangeEnd = "+inf"
+ result = cleanSet(KEYS[1], ARGV[1], rangeEnd, ARGV[2], limit,
+ {"timestamp"}, false --[[ hasFinished ]], repeatKey)
+elseif ARGV[4] == "wait" or ARGV[4] == "paused" then
+ result = cleanList(KEYS[1], ARGV[1], rangeStart, rangeEnd, ARGV[2], true --[[ hasFinished ]],
+ repeatKey)
+else
+ rangeEnd = ARGV[2]
+ -- No need to pass repeat key as in that moment job won't be related to a job scheduler
+ result = cleanSet(KEYS[1], ARGV[1], rangeEnd, ARGV[2], limit,
+ {"finishedOn"}, true --[[ hasFinished ]])
+end
+rcall("XADD", KEYS[2], "*", "event", "cleaned", "count", result[2])
+return result[1]
+`;
+var cleanJobsInSet = {
+ name: "cleanJobsInSet",
+ content: content10,
+ keys: 3
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/drain-5.js
+var content11 = `--[[
+ Drains the queue, removes all jobs that are waiting
+ or delayed, but not active, completed or failed
+ Input:
+ KEYS[1] 'wait',
+ KEYS[2] 'paused'
+ KEYS[3] 'delayed'
+ KEYS[4] 'prioritized'
+ KEYS[5] 'jobschedulers' (repeat)
+ ARGV[1] queue key prefix
+ ARGV[2] should clean delayed jobs
+]]
+local rcall = redis.call
+local queueBaseKey = ARGV[1]
+--[[
+ Functions to remove jobs.
+]]
+-- Includes
+--[[
+ Function to filter out jobs to ignore from a table.
+]]
+local function filterOutJobsToIgnore(jobs, jobsToIgnore)
+ local filteredJobs = {}
+ for i = 1, #jobs do
+ if not jobsToIgnore[jobs[i]] then
+ table.insert(filteredJobs, jobs[i])
+ end
+ end
+ return filteredJobs
+end
+--[[
+ Functions to remove jobs.
+]]
+-- Includes
+--[[
+ Function to remove job.
+]]
+-- Includes
+--[[
+ Function to remove deduplication key if needed
+ when a job is being removed.
+]]
+local function removeDeduplicationKeyIfNeededOnRemoval(prefixKey,
+ jobId, deduplicationId)
+ if deduplicationId then
+ local deduplicationKey = prefixKey .. "de:" .. deduplicationId
+ local currentJobId = rcall('GET', deduplicationKey)
+ if currentJobId and currentJobId == jobId then
+ rcall("DEL", deduplicationKey)
+ -- Also clean up any pending dedup-next data for this dedup ID
+ rcall("DEL", prefixKey .. "dn:" .. deduplicationId)
+ return 1
+ end
+ end
+end
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+--[[
+ Check if this job has a parent. If so we will just remove it from
+ the parent child list, but if it is the last child we should move the parent to "wait/paused"
+ which requires code from "moveToFinished"
+]]
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Functions to destructure job key.
+ Just a bit of warning, these functions may be a bit slow and affect performance significantly.
+]]
+local getJobIdFromKey = function (jobKey)
+ return string.match(jobKey, ".*:(.*)")
+end
+local getJobKeyPrefix = function (jobKey, jobId)
+ return string.sub(jobKey, 0, #jobKey - #jobId)
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+local function _moveParentToWait(parentPrefix, parentId, emitEvent)
+ local parentTarget, isPausedOrMaxed = getTargetQueueList(parentPrefix .. "meta", parentPrefix .. "active",
+ parentPrefix .. "wait", parentPrefix .. "paused")
+ addJobInTargetList(parentTarget, parentPrefix .. "marker", "RPUSH", isPausedOrMaxed, parentId)
+ if emitEvent then
+ local parentEventStream = parentPrefix .. "events"
+ rcall("XADD", parentEventStream, "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
+ end
+end
+local function removeParentDependencyKey(jobKey, hard, parentKey, baseKey, debounceId)
+ if parentKey then
+ local parentDependenciesKey = parentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(parentKey)
+ local parentPrefix = getJobKeyPrefix(parentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then -- remove parent in same queue
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(parentKey, hard, nil, baseKey, nil)
+ removeJobKeys(parentKey)
+ if debounceId then
+ rcall("DEL", parentPrefix .. "de:" .. debounceId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ else
+ local parentAttributes = rcall("HMGET", jobKey, "parentKey", "deid")
+ local missedParentKey = parentAttributes[1]
+ if( (type(missedParentKey) == "string") and missedParentKey ~= ""
+ and (rcall("EXISTS", missedParentKey) == 1)) then
+ local parentDependenciesKey = missedParentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(missedParentKey)
+ local parentPrefix = getJobKeyPrefix(missedParentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(missedParentKey, hard, nil, baseKey, nil)
+ removeJobKeys(missedParentKey)
+ if parentAttributes[2] then
+ rcall("DEL", parentPrefix .. "de:" .. parentAttributes[2])
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ end
+ end
+ return false
+end
+local function removeJob(jobId, hard, baseKey, shouldRemoveDeduplicationKey)
+ local jobKey = baseKey .. jobId
+ removeParentDependencyKey(jobKey, hard, nil, baseKey)
+ if shouldRemoveDeduplicationKey then
+ local deduplicationId = rcall("HGET", jobKey, "deid")
+ removeDeduplicationKeyIfNeededOnRemoval(baseKey, jobId, deduplicationId)
+ end
+ removeJobKeys(jobKey)
+end
+local function removeJobs(keys, hard, baseKey, max)
+ for i, key in ipairs(keys) do
+ removeJob(key, hard, baseKey, true --[[remove debounce key]])
+ end
+ return max - #keys
+end
+local function getListItems(keyName, max)
+ return rcall('LRANGE', keyName, 0, max - 1)
+end
+local function removeListJobs(keyName, hard, baseKey, max, jobsToIgnore)
+ local jobs = getListItems(keyName, max)
+ if jobsToIgnore then
+ jobs = filterOutJobsToIgnore(jobs, jobsToIgnore)
+ end
+ local count = removeJobs(jobs, hard, baseKey, max)
+ rcall("LTRIM", keyName, #jobs, -1)
+ return count
+end
+-- Includes
+--[[
+ Function to loop in batches.
+ Just a bit of warning, some commands as ZREM
+ could receive a maximum of 7000 parameters per call.
+]]
+local function batches(n, batchSize)
+ local i = 0
+ return function()
+ local from = i * batchSize + 1
+ i = i + 1
+ if (from <= n) then
+ local to = math.min(from + batchSize - 1, n)
+ return from, to
+ end
+ end
+end
+--[[
+ Function to get ZSet items.
+]]
+local function getZSetItems(keyName, max)
+ return rcall('ZRANGE', keyName, 0, max - 1)
+end
+local function removeZSetJobs(keyName, hard, baseKey, max, jobsToIgnore)
+ local jobs = getZSetItems(keyName, max)
+ if jobsToIgnore then
+ jobs = filterOutJobsToIgnore(jobs, jobsToIgnore)
+ end
+ local count = removeJobs(jobs, hard, baseKey, max)
+ if(#jobs > 0) then
+ for from, to in batches(#jobs, 7000) do
+ rcall("ZREM", keyName, unpack(jobs, from, to))
+ end
+ end
+ return count
+end
+-- We must not remove delayed jobs if they are associated to a job scheduler.
+local scheduledJobs = {}
+local jobSchedulers = rcall("ZRANGE", KEYS[5], 0, -1, "WITHSCORES")
+-- For every job scheduler, get the current delayed job id.
+for i = 1, #jobSchedulers, 2 do
+ local jobSchedulerId = jobSchedulers[i]
+ local jobSchedulerMillis = jobSchedulers[i + 1]
+ local delayedJobId = "repeat:" .. jobSchedulerId .. ":" .. jobSchedulerMillis
+ scheduledJobs[delayedJobId] = true
+end
+removeListJobs(KEYS[1], true, queueBaseKey, 0, scheduledJobs) -- wait
+removeListJobs(KEYS[2], true, queueBaseKey, 0, scheduledJobs) -- paused
+if ARGV[2] == "1" then
+ removeZSetJobs(KEYS[3], true, queueBaseKey, 0, scheduledJobs) -- delayed
+end
+removeZSetJobs(KEYS[4], true, queueBaseKey, 0, scheduledJobs) -- prioritized
+`;
+var drain = {
+ name: "drain",
+ content: content11,
+ keys: 5
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/extendLock-2.js
+var content12 = `--[[
+ Extend lock and removes the job from the stalled set.
+ Input:
+ KEYS[1] 'lock',
+ KEYS[2] 'stalled'
+ ARGV[1] token
+ ARGV[2] lock duration in milliseconds
+ ARGV[3] jobid
+ Output:
+ "1" if lock extented succesfully.
+]]
+local rcall = redis.call
+if rcall("GET", KEYS[1]) == ARGV[1] then
+ -- if rcall("SET", KEYS[1], ARGV[1], "PX", ARGV[2], "XX") then
+ if rcall("SET", KEYS[1], ARGV[1], "PX", ARGV[2]) then
+ rcall("SREM", KEYS[2], ARGV[3])
+ return 1
+ end
+end
+return 0
+`;
+var extendLock = {
+ name: "extendLock",
+ content: content12,
+ keys: 2
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/extendLocks-1.js
+var content13 = `--[[
+ Extend locks for multiple jobs and remove them from the stalled set if successful.
+ Return the list of job IDs for which the operation failed.
+ KEYS[1] = stalled key
+ ARGV[1] = baseKey
+ ARGV[2] = tokens
+ ARGV[3] = jobIds
+ ARGV[4] = lockDuration (ms)
+ Output:
+ An array of failed job IDs. If empty, all succeeded.
+]]
+local rcall = redis.call
+local stalledKey = KEYS[1]
+local baseKey = ARGV[1]
+local tokens = cmsgpack.unpack(ARGV[2])
+local jobIds = cmsgpack.unpack(ARGV[3])
+local lockDuration = ARGV[4]
+local jobCount = #jobIds
+local failedJobs = {}
+for i = 1, jobCount, 1 do
+ local lockKey = baseKey .. jobIds[i] .. ':lock'
+ local jobId = jobIds[i]
+ local token = tokens[i]
+ local currentToken = rcall("GET", lockKey)
+ if currentToken then
+ if currentToken == token then
+ local setResult = rcall("SET", lockKey, token, "PX", lockDuration)
+ if setResult then
+ rcall("SREM", stalledKey, jobId)
+ else
+ table.insert(failedJobs, jobId)
+ end
+ else
+ table.insert(failedJobs, jobId)
+ end
+ else
+ table.insert(failedJobs, jobId)
+ end
+end
+return failedJobs
+`;
+var extendLocks = {
+ name: "extendLocks",
+ content: content13,
+ keys: 1
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/getCounts-1.js
+var content14 = `--[[
+ Get counts per provided states
+ Input:
+ KEYS[1] 'prefix'
+ ARGV[1...] types
+]]
+local rcall = redis.call;
+local prefix = KEYS[1]
+local results = {}
+for i = 1, #ARGV do
+ local stateKey = prefix .. ARGV[i]
+ if ARGV[i] == "wait" or ARGV[i] == "paused" then
+ -- Markers in waitlist DEPRECATED in v5: Remove in v6.
+ local marker = rcall("LINDEX", stateKey, -1)
+ if marker and string.sub(marker, 1, 2) == "0:" then
+ local count = rcall("LLEN", stateKey)
+ if count > 1 then
+ rcall("RPOP", stateKey)
+ results[#results+1] = count-1
+ else
+ results[#results+1] = 0
+ end
+ else
+ results[#results+1] = rcall("LLEN", stateKey)
+ end
+ elseif ARGV[i] == "active" then
+ results[#results+1] = rcall("LLEN", stateKey)
+ else
+ results[#results+1] = rcall("ZCARD", stateKey)
+ end
+end
+return results
+`;
+var getCounts = {
+ name: "getCounts",
+ content: content14,
+ keys: 1
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/getCountsPerPriority-4.js
+var content15 = `--[[
+ Get counts per provided states
+ Input:
+ KEYS[1] wait key
+ KEYS[2] paused key
+ KEYS[3] meta key
+ KEYS[4] prioritized key
+ ARGV[1...] priorities
+]]
+local rcall = redis.call
+local results = {}
+local waitKey = KEYS[1]
+local pausedKey = KEYS[2]
+local prioritizedKey = KEYS[4]
+-- Includes
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function isQueuePaused(queueMetaKey)
+ return rcall("HEXISTS", queueMetaKey, "paused") == 1
+end
+for i = 1, #ARGV do
+ local priority = tonumber(ARGV[i])
+ if priority == 0 then
+ if isQueuePaused(KEYS[3]) then
+ results[#results+1] = rcall("LLEN", pausedKey)
+ else
+ results[#results+1] = rcall("LLEN", waitKey)
+ end
+ else
+ results[#results+1] = rcall("ZCOUNT", prioritizedKey,
+ priority * 0x100000000, (priority + 1) * 0x100000000 - 1)
+ end
+end
+return results
+`;
+var getCountsPerPriority = {
+ name: "getCountsPerPriority",
+ content: content15,
+ keys: 4
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/getDependencyCounts-4.js
+var content16 = `--[[
+ Get counts per child states
+ Input:
+ KEYS[1] processed key
+ KEYS[2] unprocessed key
+ KEYS[3] ignored key
+ KEYS[4] failed key
+ ARGV[1...] types
+]]
+local rcall = redis.call;
+local processedKey = KEYS[1]
+local unprocessedKey = KEYS[2]
+local ignoredKey = KEYS[3]
+local failedKey = KEYS[4]
+local results = {}
+for i = 1, #ARGV do
+ if ARGV[i] == "processed" then
+ results[#results+1] = rcall("HLEN", processedKey)
+ elseif ARGV[i] == "unprocessed" then
+ results[#results+1] = rcall("SCARD", unprocessedKey)
+ elseif ARGV[i] == "ignored" then
+ results[#results+1] = rcall("HLEN", ignoredKey)
+ else
+ results[#results+1] = rcall("ZCARD", failedKey)
+ end
+end
+return results
+`;
+var getDependencyCounts = {
+ name: "getDependencyCounts",
+ content: content16,
+ keys: 4
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/getJobScheduler-1.js
+var content17 = `--[[
+ Get job scheduler record.
+ Input:
+ KEYS[1] 'repeat' key
+ ARGV[1] id
+]]
+local rcall = redis.call
+local jobSchedulerKey = KEYS[1] .. ":" .. ARGV[1]
+local score = rcall("ZSCORE", KEYS[1], ARGV[1])
+if score then
+ return {rcall("HGETALL", jobSchedulerKey), score} -- get job data
+end
+return {nil, nil}
+`;
+var getJobScheduler = {
+ name: "getJobScheduler",
+ content: content17,
+ keys: 1
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/getMetrics-2.js
+var content18 = `--[[
+ Get metrics
+ Input:
+ KEYS[1] 'metrics' key
+ KEYS[2] 'metrics data' key
+ ARGV[1] start index
+ ARGV[2] end index
+]]
+local rcall = redis.call;
+local metricsKey = KEYS[1]
+local dataKey = KEYS[2]
+local metrics = rcall("HMGET", metricsKey, "count", "prevTS", "prevCount")
+local data = rcall("LRANGE", dataKey, tonumber(ARGV[1]), tonumber(ARGV[2]))
+local numPoints = rcall("LLEN", dataKey)
+return {metrics, data, numPoints}
+`;
+var getMetrics = {
+ name: "getMetrics",
+ content: content18,
+ keys: 2
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/getRanges-1.js
+var content19 = `--[[
+ Get job ids per provided states
+ Input:
+ KEYS[1] 'prefix'
+ ARGV[1] start
+ ARGV[2] end
+ ARGV[3] asc
+ ARGV[4...] types
+]]
+local rcall = redis.call
+local prefix = KEYS[1]
+local rangeStart = tonumber(ARGV[1])
+local rangeEnd = tonumber(ARGV[2])
+local asc = ARGV[3]
+local results = {}
+local function getRangeInList(listKey, asc, rangeStart, rangeEnd, results)
+ if asc == "1" then
+ local modifiedRangeStart
+ local modifiedRangeEnd
+ if rangeStart == -1 then
+ modifiedRangeStart = 0
+ else
+ modifiedRangeStart = -(rangeStart + 1)
+ end
+ if rangeEnd == -1 then
+ modifiedRangeEnd = 0
+ else
+ modifiedRangeEnd = -(rangeEnd + 1)
+ end
+ results[#results+1] = rcall("LRANGE", listKey,
+ modifiedRangeEnd,
+ modifiedRangeStart)
+ else
+ results[#results+1] = rcall("LRANGE", listKey, rangeStart, rangeEnd)
+ end
+end
+for i = 4, #ARGV do
+ local stateKey = prefix .. ARGV[i]
+ if ARGV[i] == "wait" or ARGV[i] == "paused" then
+ -- Markers in waitlist DEPRECATED in v5: Remove in v6.
+ local marker = rcall("LINDEX", stateKey, -1)
+ if marker and string.sub(marker, 1, 2) == "0:" then
+ local count = rcall("LLEN", stateKey)
+ if count > 1 then
+ rcall("RPOP", stateKey)
+ getRangeInList(stateKey, asc, rangeStart, rangeEnd, results)
+ else
+ results[#results+1] = {}
+ end
+ else
+ getRangeInList(stateKey, asc, rangeStart, rangeEnd, results)
+ end
+ elseif ARGV[i] == "active" then
+ getRangeInList(stateKey, asc, rangeStart, rangeEnd, results)
+ else
+ if asc == "1" then
+ results[#results+1] = rcall("ZRANGE", stateKey, rangeStart, rangeEnd)
+ else
+ results[#results+1] = rcall("ZREVRANGE", stateKey, rangeStart, rangeEnd)
+ end
+ end
+end
+return results
+`;
+var getRanges = {
+ name: "getRanges",
+ content: content19,
+ keys: 1
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/getRateLimitTtl-2.js
+var content20 = `--[[
+ Get rate limit ttl
+ Input:
+ KEYS[1] 'limiter'
+ KEYS[2] 'meta'
+ ARGV[1] maxJobs
+]]
+local rcall = redis.call
+-- Includes
+--[[
+ Function to get current rate limit ttl.
+]]
+local function getRateLimitTTL(maxJobs, rateLimiterKey)
+ if maxJobs and maxJobs <= tonumber(rcall("GET", rateLimiterKey) or 0) then
+ local pttl = rcall("PTTL", rateLimiterKey)
+ if pttl == 0 then
+ rcall("DEL", rateLimiterKey)
+ end
+ if pttl > 0 then
+ return pttl
+ end
+ end
+ return 0
+end
+local rateLimiterKey = KEYS[1]
+if ARGV[1] ~= "0" then
+ return getRateLimitTTL(tonumber(ARGV[1]), rateLimiterKey)
+else
+ local rateLimitMax = rcall("HGET", KEYS[2], "max")
+ if rateLimitMax then
+ return getRateLimitTTL(tonumber(rateLimitMax), rateLimiterKey)
+ end
+ return rcall("PTTL", rateLimiterKey)
+end
+`;
+var getRateLimitTtl = {
+ name: "getRateLimitTtl",
+ content: content20,
+ keys: 2
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/getState-8.js
+var content21 = `--[[
+ Get a job state
+ Input:
+ KEYS[1] 'completed' key,
+ KEYS[2] 'failed' key
+ KEYS[3] 'delayed' key
+ KEYS[4] 'active' key
+ KEYS[5] 'wait' key
+ KEYS[6] 'paused' key
+ KEYS[7] 'waiting-children' key
+ KEYS[8] 'prioritized' key
+ ARGV[1] job id
+ Output:
+ 'completed'
+ 'failed'
+ 'delayed'
+ 'active'
+ 'prioritized'
+ 'waiting'
+ 'waiting-children'
+ 'unknown'
+]]
+local rcall = redis.call
+if rcall("ZSCORE", KEYS[1], ARGV[1]) then
+ return "completed"
+end
+if rcall("ZSCORE", KEYS[2], ARGV[1]) then
+ return "failed"
+end
+if rcall("ZSCORE", KEYS[3], ARGV[1]) then
+ return "delayed"
+end
+if rcall("ZSCORE", KEYS[8], ARGV[1]) then
+ return "prioritized"
+end
+-- Includes
+--[[
+ Function to check if an item belongs to a list.
+]]
+local function checkItemInList(list, item)
+ for _, v in pairs(list) do
+ if v == item then
+ return 1
+ end
+ end
+ return nil
+end
+local active_items = rcall("LRANGE", KEYS[4] , 0, -1)
+if checkItemInList(active_items, ARGV[1]) ~= nil then
+ return "active"
+end
+local wait_items = rcall("LRANGE", KEYS[5] , 0, -1)
+if checkItemInList(wait_items, ARGV[1]) ~= nil then
+ return "waiting"
+end
+local paused_items = rcall("LRANGE", KEYS[6] , 0, -1)
+if checkItemInList(paused_items, ARGV[1]) ~= nil then
+ return "waiting"
+end
+if rcall("ZSCORE", KEYS[7], ARGV[1]) then
+ return "waiting-children"
+end
+return "unknown"
+`;
+var getState = {
+ name: "getState",
+ content: content21,
+ keys: 8
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/getStateV2-8.js
+var content22 = `--[[
+ Get a job state
+ Input:
+ KEYS[1] 'completed' key,
+ KEYS[2] 'failed' key
+ KEYS[3] 'delayed' key
+ KEYS[4] 'active' key
+ KEYS[5] 'wait' key
+ KEYS[6] 'paused' key
+ KEYS[7] 'waiting-children' key
+ KEYS[8] 'prioritized' key
+ ARGV[1] job id
+ Output:
+ 'completed'
+ 'failed'
+ 'delayed'
+ 'active'
+ 'waiting'
+ 'waiting-children'
+ 'unknown'
+]]
+local rcall = redis.call
+if rcall("ZSCORE", KEYS[1], ARGV[1]) then
+ return "completed"
+end
+if rcall("ZSCORE", KEYS[2], ARGV[1]) then
+ return "failed"
+end
+if rcall("ZSCORE", KEYS[3], ARGV[1]) then
+ return "delayed"
+end
+if rcall("ZSCORE", KEYS[8], ARGV[1]) then
+ return "prioritized"
+end
+if rcall("LPOS", KEYS[4] , ARGV[1]) then
+ return "active"
+end
+if rcall("LPOS", KEYS[5] , ARGV[1]) then
+ return "waiting"
+end
+if rcall("LPOS", KEYS[6] , ARGV[1]) then
+ return "waiting"
+end
+if rcall("ZSCORE", KEYS[7] , ARGV[1]) then
+ return "waiting-children"
+end
+return "unknown"
+`;
+var getStateV2 = {
+ name: "getStateV2",
+ content: content22,
+ keys: 8
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/isFinished-3.js
+var content23 = `--[[
+ Checks if a job is finished (.i.e. is in the completed or failed set)
+ Input:
+ KEYS[1] completed key
+ KEYS[2] failed key
+ KEYS[3] job key
+ ARGV[1] job id
+ ARGV[2] return value?
+ Output:
+ 0 - Not finished.
+ 1 - Completed.
+ 2 - Failed.
+ -1 - Missing job.
+]]
+local rcall = redis.call
+if rcall("EXISTS", KEYS[3]) ~= 1 then
+ if ARGV[2] == "1" then
+ return {-1,"Missing key for job " .. KEYS[3] .. ". isFinished"}
+ end
+ return -1
+end
+if rcall("ZSCORE", KEYS[1], ARGV[1]) then
+ if ARGV[2] == "1" then
+ local returnValue = rcall("HGET", KEYS[3], "returnvalue")
+ return {1,returnValue}
+ end
+ return 1
+end
+if rcall("ZSCORE", KEYS[2], ARGV[1]) then
+ if ARGV[2] == "1" then
+ local failedReason = rcall("HGET", KEYS[3], "failedReason")
+ return {2,failedReason}
+ end
+ return 2
+end
+if ARGV[2] == "1" then
+ return {0}
+end
+return 0
+`;
+var isFinished = {
+ name: "isFinished",
+ content: content23,
+ keys: 3
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/isJobInList-1.js
+var content24 = `--[[
+ Checks if job is in a given list.
+ Input:
+ KEYS[1]
+ ARGV[1]
+ Output:
+ 1 if element found in the list.
+]]
+-- Includes
+--[[
+ Function to check if an item belongs to a list.
+]]
+local function checkItemInList(list, item)
+ for _, v in pairs(list) do
+ if v == item then
+ return 1
+ end
+ end
+ return nil
+end
+local items = redis.call("LRANGE", KEYS[1] , 0, -1)
+return checkItemInList(items, ARGV[1])
+`;
+var isJobInList = {
+ name: "isJobInList",
+ content: content24,
+ keys: 1
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/isMaxed-2.js
+var content25 = `--[[
+ Checks if queue is maxed.
+ Input:
+ KEYS[1] meta key
+ KEYS[2] active key
+ Output:
+ 1 if element found in the list.
+]]
+local rcall = redis.call
+-- Includes
+--[[
+ Function to check if queue is maxed or not.
+]]
+local function isQueueMaxed(queueMetaKey, activeKey)
+ local maxConcurrency = rcall("HGET", queueMetaKey, "concurrency")
+ if maxConcurrency then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(maxConcurrency) then
+ return true
+ end
+ end
+ return false
+end
+return isQueueMaxed(KEYS[1], KEYS[2])
+`;
+var isMaxed = {
+ name: "isMaxed",
+ content: content25,
+ keys: 2
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/moveJobFromActiveToWait-9.js
+var content26 = `--[[
+ Function to move job from active state to wait.
+ Input:
+ KEYS[1] active key
+ KEYS[2] wait key
+ KEYS[3] stalled key
+ KEYS[4] paused key
+ KEYS[5] meta key
+ KEYS[6] limiter key
+ KEYS[7] prioritized key
+ KEYS[8] marker key
+ KEYS[9] event key
+ ARGV[1] job id
+ ARGV[2] lock token
+ ARGV[3] job id key
+]]
+local rcall = redis.call
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to push back job considering priority in front of same prioritized jobs.
+]]
+local function pushBackJobWithPriority(prioritizedKey, priority, jobId)
+ -- in order to put it at front of same prioritized jobs
+ -- we consider prioritized counter as 0
+ local score = priority * 0x100000000
+ rcall("ZADD", prioritizedKey, score, jobId)
+end
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+local function removeLock(jobKey, stalledKey, token, jobId)
+ if token ~= "0" then
+ local lockKey = jobKey .. ':lock'
+ local lockToken = rcall("GET", lockKey)
+ if lockToken == token then
+ rcall("DEL", lockKey)
+ rcall("SREM", stalledKey, jobId)
+ else
+ if lockToken then
+ -- Lock exists but token does not match
+ return -6
+ else
+ -- Lock is missing completely
+ return -2
+ end
+ end
+ end
+ return 0
+end
+local jobId = ARGV[1]
+local token = ARGV[2]
+local jobKey = ARGV[3]
+if rcall("EXISTS", jobKey) == 0 then
+ return -1
+end
+local errorCode = removeLock(jobKey, KEYS[3], token, jobId)
+if errorCode < 0 then
+ return errorCode
+end
+local metaKey = KEYS[5]
+local removed = rcall("LREM", KEYS[1], 1, jobId)
+if removed > 0 then
+ local target, isPausedOrMaxed = getTargetQueueList(metaKey, KEYS[1], KEYS[2], KEYS[4])
+ local priority = tonumber(rcall("HGET", ARGV[3], "priority")) or 0
+ if priority > 0 then
+ pushBackJobWithPriority(KEYS[7], priority, jobId)
+ else
+ addJobInTargetList(target, KEYS[8], "RPUSH", isPausedOrMaxed, jobId)
+ end
+ local maxEvents = getOrSetMaxEvents(metaKey)
+ -- Emit waiting event
+ rcall("XADD", KEYS[9], "MAXLEN", "~", maxEvents, "*", "event", "waiting",
+ "jobId", jobId, "prev", "active")
+end
+local pttl = rcall("PTTL", KEYS[6])
+if pttl > 0 then
+ return pttl
+else
+ return 0
+end
+`;
+var moveJobFromActiveToWait = {
+ name: "moveJobFromActiveToWait",
+ content: content26,
+ keys: 9
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/moveJobsToWait-8.js
+var content27 = `--[[
+ Move completed, failed or delayed jobs to wait.
+ Note: Does not support jobs with priorities.
+ Input:
+ KEYS[1] base key
+ KEYS[2] events stream
+ KEYS[3] state key (failed, completed, delayed)
+ KEYS[4] 'wait'
+ KEYS[5] 'paused'
+ KEYS[6] 'meta'
+ KEYS[7] 'active'
+ KEYS[8] 'marker'
+ ARGV[1] count
+ ARGV[2] timestamp
+ ARGV[3] prev state
+ Output:
+ 1 means the operation is not completed
+ 0 means the operation is completed
+]]
+local maxCount = tonumber(ARGV[1])
+local timestamp = tonumber(ARGV[2])
+local rcall = redis.call;
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+--[[
+ Function to loop in batches.
+ Just a bit of warning, some commands as ZREM
+ could receive a maximum of 7000 parameters per call.
+]]
+local function batches(n, batchSize)
+ local i = 0
+ return function()
+ local from = i * batchSize + 1
+ i = i + 1
+ if (from <= n) then
+ local to = math.min(from + batchSize - 1, n)
+ return from, to
+ end
+ end
+end
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+local metaKey = KEYS[6]
+local target, isPausedOrMaxed = getTargetQueueList(metaKey, KEYS[7], KEYS[4], KEYS[5])
+local jobs = rcall('ZRANGEBYSCORE', KEYS[3], 0, timestamp, 'LIMIT', 0, maxCount)
+if (#jobs > 0) then
+ if ARGV[3] == "failed" then
+ for i, key in ipairs(jobs) do
+ local jobKey = KEYS[1] .. key
+ rcall("HDEL", jobKey, "finishedOn", "processedOn", "failedReason")
+ end
+ elseif ARGV[3] == "completed" then
+ for i, key in ipairs(jobs) do
+ local jobKey = KEYS[1] .. key
+ rcall("HDEL", jobKey, "finishedOn", "processedOn", "returnvalue")
+ end
+ end
+ local maxEvents = getOrSetMaxEvents(metaKey)
+ for i, key in ipairs(jobs) do
+ -- Emit waiting event
+ rcall("XADD", KEYS[2], "MAXLEN", "~", maxEvents, "*", "event",
+ "waiting", "jobId", key, "prev", ARGV[3]);
+ end
+ for from, to in batches(#jobs, 7000) do
+ rcall("ZREM", KEYS[3], unpack(jobs, from, to))
+ rcall("LPUSH", target, unpack(jobs, from, to))
+ end
+ addBaseMarkerIfNeeded(KEYS[8], isPausedOrMaxed)
+end
+maxCount = maxCount - #jobs
+if (maxCount <= 0) then return 1 end
+return 0
+`;
+var moveJobsToWait = {
+ name: "moveJobsToWait",
+ content: content27,
+ keys: 8
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/moveStalledJobsToWait-8.js
+var content28 = `--[[
+ Move stalled jobs to wait.
+ Input:
+ KEYS[1] 'stalled' (SET)
+ KEYS[2] 'wait', (LIST)
+ KEYS[3] 'active', (LIST)
+ KEYS[4] 'stalled-check', (KEY)
+ KEYS[5] 'meta', (KEY)
+ KEYS[6] 'paused', (LIST)
+ KEYS[7] 'marker'
+ KEYS[8] 'event stream' (STREAM)
+ ARGV[1] Max stalled job count
+ ARGV[2] queue.toKey('')
+ ARGV[3] timestamp
+ ARGV[4] max check time
+ Events:
+ 'stalled' with stalled job id.
+]]
+local rcall = redis.call
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to loop in batches.
+ Just a bit of warning, some commands as ZREM
+ could receive a maximum of 7000 parameters per call.
+]]
+local function batches(n, batchSize)
+ local i = 0
+ return function()
+ local from = i * batchSize + 1
+ i = i + 1
+ if (from <= n) then
+ local to = math.min(from + batchSize - 1, n)
+ return from, to
+ end
+ end
+end
+--[[
+ Function to move job to wait to be picked up by a waiting worker.
+]]
+-- Includes
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+local function moveJobToWait(metaKey, activeKey, waitKey, pausedKey, markerKey, eventStreamKey,
+ jobId, pushCmd)
+ local target, isPausedOrMaxed = getTargetQueueList(metaKey, activeKey, waitKey, pausedKey)
+ addJobInTargetList(target, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall("XADD", eventStreamKey, "*", "event", "waiting", "jobId", jobId, 'prev', 'active')
+end
+--[[
+ Function to trim events, default 10000.
+]]
+-- Includes
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+local function trimEvents(metaKey, eventStreamKey)
+ local maxEvents = getOrSetMaxEvents(metaKey)
+ if maxEvents then
+ rcall("XTRIM", eventStreamKey, "MAXLEN", "~", maxEvents)
+ else
+ rcall("XTRIM", eventStreamKey, "MAXLEN", "~", 10000)
+ end
+end
+local stalledKey = KEYS[1]
+local waitKey = KEYS[2]
+local activeKey = KEYS[3]
+local stalledCheckKey = KEYS[4]
+local metaKey = KEYS[5]
+local pausedKey = KEYS[6]
+local markerKey = KEYS[7]
+local eventStreamKey = KEYS[8]
+local maxStalledJobCount = tonumber(ARGV[1])
+local queueKeyPrefix = ARGV[2]
+local timestamp = ARGV[3]
+local maxCheckTime = ARGV[4]
+if rcall("EXISTS", stalledCheckKey) == 1 then
+ return {}
+end
+rcall("SET", stalledCheckKey, timestamp, "PX", maxCheckTime)
+-- Trim events before emiting them to avoid trimming events emitted in this script
+trimEvents(metaKey, eventStreamKey)
+-- Move all stalled jobs to wait
+local stalling = rcall('SMEMBERS', stalledKey)
+local stalled = {}
+if (#stalling > 0) then
+ rcall('DEL', stalledKey)
+ -- Remove from active list
+ for i, jobId in ipairs(stalling) do
+ -- Markers in waitlist DEPRECATED in v5: Remove in v6.
+ if string.sub(jobId, 1, 2) == "0:" then
+ -- If the jobId is a delay marker ID we just remove it.
+ rcall("LREM", activeKey, 1, jobId)
+ else
+ local jobKey = queueKeyPrefix .. jobId
+ -- Check that the lock is also missing, then we can handle this job as really stalled.
+ if (rcall("EXISTS", jobKey .. ":lock") == 0) then
+ -- Remove from the active queue.
+ local removed = rcall("LREM", activeKey, 1, jobId)
+ if (removed > 0) then
+ -- If this job has been stalled too many times, such as if it crashes the worker, then fail it.
+ local stalledCount = rcall("HINCRBY", jobKey, "stc", 1)
+ -- Check if this is a repeatable job by looking at job options
+ local jobOpts = rcall("HGET", jobKey, "opts")
+ local isRepeatableJob = false
+ if jobOpts then
+ local opts = cjson.decode(jobOpts)
+ if opts and opts["repeat"] then
+ isRepeatableJob = true
+ end
+ end
+ -- Only fail job if it exceeds stall limit AND is not a repeatable job
+ if stalledCount > maxStalledJobCount and not isRepeatableJob then
+ local failedReason = "job stalled more than allowable limit"
+ rcall("HSET", jobKey, "defa", failedReason)
+ end
+ moveJobToWait(metaKey, activeKey, waitKey, pausedKey, markerKey, eventStreamKey, jobId,
+ "RPUSH")
+ -- Emit the stalled event
+ rcall("XADD", eventStreamKey, "*", "event", "stalled", "jobId", jobId)
+ table.insert(stalled, jobId)
+ end
+ end
+ end
+ end
+end
+-- Mark potentially stalled jobs
+local active = rcall('LRANGE', activeKey, 0, -1)
+if (#active > 0) then
+ for from, to in batches(#active, 7000) do
+ rcall('SADD', stalledKey, unpack(active, from, to))
+ end
+end
+return stalled
+`;
+var moveStalledJobsToWait = {
+ name: "moveStalledJobsToWait",
+ content: content28,
+ keys: 8
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/moveToActive-11.js
+var content29 = `--[[
+ Move next job to be processed to active, lock it and fetch its data. The job
+ may be delayed, in that case we need to move it to the delayed set instead.
+ This operation guarantees that the worker owns the job during the lock
+ expiration time. The worker is responsible of keeping the lock fresh
+ so that no other worker picks this job again.
+ Input:
+ KEYS[1] wait key
+ KEYS[2] active key
+ KEYS[3] prioritized key
+ KEYS[4] stream events key
+ KEYS[5] stalled key
+ -- Rate limiting
+ KEYS[6] rate limiter key
+ KEYS[7] delayed key
+ -- Delayed jobs
+ KEYS[8] paused key
+ KEYS[9] meta key
+ KEYS[10] pc priority counter
+ -- Marker
+ KEYS[11] marker key
+ -- Arguments
+ ARGV[1] key prefix
+ ARGV[2] timestamp
+ ARGV[3] opts
+ opts - token - lock token
+ opts - lockDuration
+ opts - limiter
+ opts - name - worker name
+]]
+local rcall = redis.call
+local waitKey = KEYS[1]
+local activeKey = KEYS[2]
+local eventStreamKey = KEYS[4]
+local rateLimiterKey = KEYS[6]
+local delayedKey = KEYS[7]
+local opts = cmsgpack.unpack(ARGV[3])
+-- Includes
+--[[
+ Function to return the next delayed job timestamp.
+]]
+local function getNextDelayedTimestamp(delayedKey)
+ local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
+ if #result then
+ local nextTimestamp = tonumber(result[2])
+ if nextTimestamp ~= nil then
+ return nextTimestamp / 0x1000
+ end
+ end
+end
+--[[
+ Function to get current rate limit ttl.
+]]
+local function getRateLimitTTL(maxJobs, rateLimiterKey)
+ if maxJobs and maxJobs <= tonumber(rcall("GET", rateLimiterKey) or 0) then
+ local pttl = rcall("PTTL", rateLimiterKey)
+ if pttl == 0 then
+ rcall("DEL", rateLimiterKey)
+ end
+ if pttl > 0 then
+ return pttl
+ end
+ end
+ return 0
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+--[[
+ Function to move job from prioritized state to active.
+]]
+local function moveJobFromPrioritizedToActive(priorityKey, activeKey, priorityCounterKey)
+ local prioritizedJob = rcall("ZPOPMIN", priorityKey)
+ if #prioritizedJob > 0 then
+ rcall("LPUSH", activeKey, prioritizedJob[1])
+ return prioritizedJob[1]
+ else
+ rcall("DEL", priorityCounterKey)
+ end
+end
+--[[
+ Function to move job from wait state to active.
+ Input:
+ opts - token - lock token
+ opts - lockDuration
+ opts - limiter
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function prepareJobForProcessing(keyPrefix, rateLimiterKey, eventStreamKey,
+ jobId, processedOn, maxJobs, limiterDuration, markerKey, opts)
+ local jobKey = keyPrefix .. jobId
+ -- Check if we need to perform rate limiting.
+ if maxJobs then
+ local jobCounter = tonumber(rcall("INCR", rateLimiterKey))
+ if jobCounter == 1 then
+ local integerDuration = math.floor(math.abs(limiterDuration))
+ rcall("PEXPIRE", rateLimiterKey, integerDuration)
+ end
+ end
+ -- get a lock
+ if opts['token'] ~= "0" then
+ local lockKey = jobKey .. ':lock'
+ rcall("SET", lockKey, opts['token'], "PX", opts['lockDuration'])
+ end
+ local optionalValues = {}
+ if opts['name'] then
+ -- Set "processedBy" field to the worker name
+ table.insert(optionalValues, "pb")
+ table.insert(optionalValues, opts['name'])
+ end
+ rcall("XADD", eventStreamKey, "*", "event", "active", "jobId", jobId, "prev", "waiting")
+ rcall("HMSET", jobKey, "processedOn", processedOn, unpack(optionalValues))
+ rcall("HINCRBY", jobKey, "ats", 1)
+ addBaseMarkerIfNeeded(markerKey, false)
+ -- rate limit delay must be 0 in this case to prevent adding more delay
+ -- when job that is moved to active needs to be processed
+ return {rcall("HGETALL", jobKey), jobId, 0, 0} -- get job data
+end
+--[[
+ Updates the delay set, by moving delayed jobs that should
+ be processed now to "wait".
+ Events:
+ 'waiting'
+]]
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to add job considering priority.
+]]
+-- Includes
+--[[
+ Function to get priority score.
+]]
+local function getPriorityScore(priority, priorityCounterKey)
+ local prioCounter = rcall("INCR", priorityCounterKey)
+ return priority * 0x100000000 + prioCounter % 0x100000000
+end
+local function addJobWithPriority(markerKey, prioritizedKey, priority, jobId, priorityCounterKey,
+ isPausedOrMaxed)
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+-- Try to get as much as 1000 jobs at once
+local function promoteDelayedJobs(delayedKey, markerKey, targetKey, prioritizedKey,
+ eventStreamKey, prefix, timestamp, priorityCounterKey, isPaused)
+ local jobs = rcall("ZRANGEBYSCORE", delayedKey, 0, (timestamp + 1) * 0x1000 - 1, "LIMIT", 0, 1000)
+ if (#jobs > 0) then
+ rcall("ZREM", delayedKey, unpack(jobs))
+ for _, jobId in ipairs(jobs) do
+ local jobKey = prefix .. jobId
+ local priority =
+ tonumber(rcall("HGET", jobKey, "priority")) or 0
+ if priority == 0 then
+ -- LIFO or FIFO
+ rcall("LPUSH", targetKey, jobId)
+ else
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ end
+ -- Emit waiting event
+ rcall("XADD", eventStreamKey, "*", "event", "waiting", "jobId",
+ jobId, "prev", "delayed")
+ rcall("HSET", jobKey, "delay", 0)
+ end
+ addBaseMarkerIfNeeded(markerKey, isPaused)
+ end
+end
+local target, isPausedOrMaxed, rateLimitMax, rateLimitDuration = getTargetQueueList(KEYS[9],
+ activeKey, waitKey, KEYS[8])
+-- Check if there are delayed jobs that we can move to wait.
+local markerKey = KEYS[11]
+promoteDelayedJobs(delayedKey, markerKey, target, KEYS[3], eventStreamKey, ARGV[1],
+ ARGV[2], KEYS[10], isPausedOrMaxed)
+local maxJobs = tonumber(rateLimitMax or (opts['limiter'] and opts['limiter']['max']))
+local expireTime = getRateLimitTTL(maxJobs, rateLimiterKey)
+-- Check if we are rate limited first.
+if expireTime > 0 then return {0, 0, expireTime, 0} end
+-- paused or maxed queue
+if isPausedOrMaxed then return {0, 0, 0, 0} end
+local limiterDuration = (opts['limiter'] and opts['limiter']['duration']) or rateLimitDuration
+-- no job ID, try non-blocking move from wait to active
+local jobId = rcall("RPOPLPUSH", waitKey, activeKey)
+-- Markers in waitlist DEPRECATED in v5: Will be completely removed in v6.
+if jobId and string.sub(jobId, 1, 2) == "0:" then
+ rcall("LREM", activeKey, 1, jobId)
+ jobId = rcall("RPOPLPUSH", waitKey, activeKey)
+end
+if jobId then
+ return prepareJobForProcessing(ARGV[1], rateLimiterKey, eventStreamKey, jobId, ARGV[2],
+ maxJobs, limiterDuration, markerKey, opts)
+else
+ jobId = moveJobFromPrioritizedToActive(KEYS[3], activeKey, KEYS[10])
+ if jobId then
+ return prepareJobForProcessing(ARGV[1], rateLimiterKey, eventStreamKey, jobId, ARGV[2],
+ maxJobs, limiterDuration, markerKey, opts)
+ end
+end
+-- Return the timestamp for the next delayed job if any.
+local nextTimestamp = getNextDelayedTimestamp(delayedKey)
+if nextTimestamp ~= nil then return {0, 0, 0, nextTimestamp} end
+return {0, 0, 0, 0}
+`;
+var moveToActive = {
+ name: "moveToActive",
+ content: content29,
+ keys: 11
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/moveToDelayed-12.js
+var content30 = `--[[
+ Moves job from active to delayed set.
+ Input:
+ KEYS[1] marker key
+ KEYS[2] active key
+ KEYS[3] prioritized key
+ KEYS[4] delayed key
+ KEYS[5] job key
+ KEYS[6] events stream
+ KEYS[7] meta key
+ KEYS[8] stalled key
+ KEYS[9] wait key
+ KEYS[10] rate limiter key
+ KEYS[11] paused key
+ KEYS[12] pc priority counter
+ ARGV[1] key prefix
+ ARGV[2] timestamp
+ ARGV[3] the id of the job
+ ARGV[4] queue token
+ ARGV[5] delay value
+ ARGV[6] skip attempt
+ ARGV[7] optional job fields to update
+ ARGV[8] fetch next?
+ ARGV[9] opts
+ Output:
+ 0 - OK
+ -1 - Missing job.
+ -3 - Job not in active set.
+ Events:
+ - delayed key.
+]]
+local rcall = redis.call
+-- Includes
+--[[
+ Add delay marker if needed.
+]]
+-- Includes
+--[[
+ Function to return the next delayed job timestamp.
+]]
+local function getNextDelayedTimestamp(delayedKey)
+ local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
+ if #result then
+ local nextTimestamp = tonumber(result[2])
+ if nextTimestamp ~= nil then
+ return nextTimestamp / 0x1000
+ end
+ end
+end
+local function addDelayMarkerIfNeeded(markerKey, delayedKey)
+ local nextTimestamp = getNextDelayedTimestamp(delayedKey)
+ if nextTimestamp ~= nil then
+ -- Replace the score of the marker with the newest known
+ -- next timestamp.
+ rcall("ZADD", markerKey, nextTimestamp, "1")
+ end
+end
+--[[
+ Function to fetch the next job to process.
+ Tries to get the next job to avoid an extra roundtrip if the queue is
+ not closing and not rate limited.
+ Input:
+ waitKey - wait list key
+ activeKey - active list key
+ prioritizedKey - prioritized sorted set key
+ eventStreamKey - event stream key
+ rateLimiterKey - rate limiter key
+ delayedKey - delayed sorted set key
+ pausedKey - paused list key
+ metaKey - meta hash key
+ pcKey - priority counter key
+ markerKey - marker key
+ prefix - keys prefix
+ timestamp - current timestamp
+ opts - options table:
+ token (required) - lock token used when locking jobs
+ lockDuration (required) - lock duration for acquired jobs
+ limiter (optional) - rate limiter options table (e.g. { max = number })
+]]
+-- Includes
+--[[
+ Function to get current rate limit ttl.
+]]
+local function getRateLimitTTL(maxJobs, rateLimiterKey)
+ if maxJobs and maxJobs <= tonumber(rcall("GET", rateLimiterKey) or 0) then
+ local pttl = rcall("PTTL", rateLimiterKey)
+ if pttl == 0 then
+ rcall("DEL", rateLimiterKey)
+ end
+ if pttl > 0 then
+ return pttl
+ end
+ end
+ return 0
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+--[[
+ Function to move job from prioritized state to active.
+]]
+local function moveJobFromPrioritizedToActive(priorityKey, activeKey, priorityCounterKey)
+ local prioritizedJob = rcall("ZPOPMIN", priorityKey)
+ if #prioritizedJob > 0 then
+ rcall("LPUSH", activeKey, prioritizedJob[1])
+ return prioritizedJob[1]
+ else
+ rcall("DEL", priorityCounterKey)
+ end
+end
+--[[
+ Function to move job from wait state to active.
+ Input:
+ opts - token - lock token
+ opts - lockDuration
+ opts - limiter
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function prepareJobForProcessing(keyPrefix, rateLimiterKey, eventStreamKey,
+ jobId, processedOn, maxJobs, limiterDuration, markerKey, opts)
+ local jobKey = keyPrefix .. jobId
+ -- Check if we need to perform rate limiting.
+ if maxJobs then
+ local jobCounter = tonumber(rcall("INCR", rateLimiterKey))
+ if jobCounter == 1 then
+ local integerDuration = math.floor(math.abs(limiterDuration))
+ rcall("PEXPIRE", rateLimiterKey, integerDuration)
+ end
+ end
+ -- get a lock
+ if opts['token'] ~= "0" then
+ local lockKey = jobKey .. ':lock'
+ rcall("SET", lockKey, opts['token'], "PX", opts['lockDuration'])
+ end
+ local optionalValues = {}
+ if opts['name'] then
+ -- Set "processedBy" field to the worker name
+ table.insert(optionalValues, "pb")
+ table.insert(optionalValues, opts['name'])
+ end
+ rcall("XADD", eventStreamKey, "*", "event", "active", "jobId", jobId, "prev", "waiting")
+ rcall("HMSET", jobKey, "processedOn", processedOn, unpack(optionalValues))
+ rcall("HINCRBY", jobKey, "ats", 1)
+ addBaseMarkerIfNeeded(markerKey, false)
+ -- rate limit delay must be 0 in this case to prevent adding more delay
+ -- when job that is moved to active needs to be processed
+ return {rcall("HGETALL", jobKey), jobId, 0, 0} -- get job data
+end
+--[[
+ Updates the delay set, by moving delayed jobs that should
+ be processed now to "wait".
+ Events:
+ 'waiting'
+]]
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to add job considering priority.
+]]
+-- Includes
+--[[
+ Function to get priority score.
+]]
+local function getPriorityScore(priority, priorityCounterKey)
+ local prioCounter = rcall("INCR", priorityCounterKey)
+ return priority * 0x100000000 + prioCounter % 0x100000000
+end
+local function addJobWithPriority(markerKey, prioritizedKey, priority, jobId, priorityCounterKey,
+ isPausedOrMaxed)
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+-- Try to get as much as 1000 jobs at once
+local function promoteDelayedJobs(delayedKey, markerKey, targetKey, prioritizedKey,
+ eventStreamKey, prefix, timestamp, priorityCounterKey, isPaused)
+ local jobs = rcall("ZRANGEBYSCORE", delayedKey, 0, (timestamp + 1) * 0x1000 - 1, "LIMIT", 0, 1000)
+ if (#jobs > 0) then
+ rcall("ZREM", delayedKey, unpack(jobs))
+ for _, jobId in ipairs(jobs) do
+ local jobKey = prefix .. jobId
+ local priority =
+ tonumber(rcall("HGET", jobKey, "priority")) or 0
+ if priority == 0 then
+ -- LIFO or FIFO
+ rcall("LPUSH", targetKey, jobId)
+ else
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ end
+ -- Emit waiting event
+ rcall("XADD", eventStreamKey, "*", "event", "waiting", "jobId",
+ jobId, "prev", "delayed")
+ rcall("HSET", jobKey, "delay", 0)
+ end
+ addBaseMarkerIfNeeded(markerKey, isPaused)
+ end
+end
+local function fetchNextJob(waitKey, activeKey, prioritizedKey, eventStreamKey,
+ rateLimiterKey, delayedKey, pausedKey, metaKey, pcKey, markerKey, prefix,
+ timestamp, opts)
+ local target, isPausedOrMaxed, rateLimitMax, rateLimitDuration =
+ getTargetQueueList(metaKey, activeKey, waitKey, pausedKey)
+ -- Check if there are delayed jobs that can be promoted
+ promoteDelayedJobs(delayedKey, markerKey, target, prioritizedKey,
+ eventStreamKey, prefix, timestamp, pcKey, isPausedOrMaxed)
+ local maxJobs = tonumber(rateLimitMax or (opts['limiter'] and opts['limiter']['max']))
+ -- Check if we are rate limited first.
+ local expireTime = getRateLimitTTL(maxJobs, rateLimiterKey)
+ if expireTime > 0 then
+ return {0, 0, expireTime, 0}
+ end
+ -- paused or maxed queue
+ if isPausedOrMaxed then
+ return {0, 0, 0, 0}
+ end
+ local limiterDuration = (opts['limiter'] and opts['limiter']['duration']) or rateLimitDuration
+ local jobId = rcall("RPOPLPUSH", waitKey, activeKey)
+ if jobId then
+ -- Markers in waitlist DEPRECATED in v5: Remove in v6.
+ if string.sub(jobId, 1, 2) == "0:" then
+ rcall("LREM", activeKey, 1, jobId)
+ -- If jobId is special ID 0:delay (delay greater than 0), then there is no job to process
+ -- but if ID is 0:0, then there is at least 1 prioritized job to process
+ if jobId == "0:0" then
+ jobId = moveJobFromPrioritizedToActive(prioritizedKey, activeKey, pcKey)
+ return prepareJobForProcessing(prefix, rateLimiterKey,
+ eventStreamKey, jobId, timestamp, maxJobs,
+ limiterDuration, markerKey, opts)
+ end
+ else
+ return prepareJobForProcessing(prefix, rateLimiterKey,
+ eventStreamKey, jobId, timestamp, maxJobs,
+ limiterDuration, markerKey, opts)
+ end
+ else
+ jobId = moveJobFromPrioritizedToActive(prioritizedKey, activeKey, pcKey)
+ if jobId then
+ return prepareJobForProcessing(prefix, rateLimiterKey,
+ eventStreamKey, jobId, timestamp, maxJobs,
+ limiterDuration, markerKey, opts)
+ end
+ end
+ -- Return the timestamp for the next delayed job if any.
+ local nextTimestamp = getNextDelayedTimestamp(delayedKey)
+ if nextTimestamp ~= nil then
+ -- The result is guaranteed to be positive, since the
+ -- ZRANGEBYSCORE command would have return a job otherwise.
+ return {0, 0, 0, nextTimestamp}
+ end
+end
+--[[
+ Bake in the job id first 12 bits into the timestamp
+ to guarantee correct execution order of delayed jobs
+ (up to 4096 jobs per given timestamp or 4096 jobs apart per timestamp)
+ WARNING: Jobs that are so far apart that they wrap around will cause FIFO to fail
+]]
+local function getDelayedScore(delayedKey, timestamp, delay)
+ local delayedTimestamp = (delay > 0 and (tonumber(timestamp) + delay)) or tonumber(timestamp)
+ local minScore = delayedTimestamp * 0x1000
+ local maxScore = (delayedTimestamp + 1 ) * 0x1000 - 1
+ local result = rcall("ZREVRANGEBYSCORE", delayedKey, maxScore,
+ minScore, "WITHSCORES","LIMIT", 0, 1)
+ if #result then
+ local currentMaxScore = tonumber(result[2])
+ if currentMaxScore ~= nil then
+ if currentMaxScore >= maxScore then
+ return maxScore, delayedTimestamp
+ else
+ return currentMaxScore + 1, delayedTimestamp
+ end
+ end
+ end
+ return minScore, delayedTimestamp
+end
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+local function removeLock(jobKey, stalledKey, token, jobId)
+ if token ~= "0" then
+ local lockKey = jobKey .. ':lock'
+ local lockToken = rcall("GET", lockKey)
+ if lockToken == token then
+ rcall("DEL", lockKey)
+ rcall("SREM", stalledKey, jobId)
+ else
+ if lockToken then
+ -- Lock exists but token does not match
+ return -6
+ else
+ -- Lock is missing completely
+ return -2
+ end
+ end
+ end
+ return 0
+end
+--[[
+ Function to update a bunch of fields in a job.
+]]
+local function updateJobFields(jobKey, msgpackedFields)
+ if msgpackedFields and #msgpackedFields > 0 then
+ local fieldsToUpdate = cmsgpack.unpack(msgpackedFields)
+ if fieldsToUpdate then
+ rcall("HMSET", jobKey, unpack(fieldsToUpdate))
+ end
+ end
+end
+local jobKey = KEYS[5]
+local markerKey = KEYS[1]
+local metaKey = KEYS[7]
+local token = ARGV[4]
+if rcall("EXISTS", jobKey) == 1 then
+ local errorCode = removeLock(jobKey, KEYS[8], token, ARGV[3])
+ if errorCode < 0 then
+ return errorCode
+ end
+ updateJobFields(jobKey, ARGV[7])
+ local delayedKey = KEYS[4]
+ local jobId = ARGV[3]
+ local delay = tonumber(ARGV[5])
+ local numRemovedElements = rcall("LREM", KEYS[2], -1, jobId)
+ if numRemovedElements < 1 then return -3 end
+ local score, delayedTimestamp = getDelayedScore(delayedKey, ARGV[2], delay)
+ if ARGV[6] == "0" then
+ rcall("HINCRBY", jobKey, "atm", 1)
+ end
+ rcall("HSET", jobKey, "delay", ARGV[5])
+ local maxEvents = getOrSetMaxEvents(metaKey)
+ rcall("ZADD", delayedKey, score, jobId)
+ rcall("XADD", KEYS[6], "MAXLEN", "~", maxEvents, "*", "event", "delayed",
+ "jobId", jobId, "delay", delayedTimestamp)
+ -- Try to get next job to avoid an extra roundtrip if the queue is not closing,
+ -- and not rate limited.
+ if (ARGV[8] == "1") then
+ local opts = cmsgpack.unpack(ARGV[9])
+ local result = fetchNextJob(KEYS[9], KEYS[2], KEYS[3], KEYS[6],
+ KEYS[10], KEYS[4], KEYS[11], metaKey, KEYS[12], markerKey,
+ ARGV[1], ARGV[2], opts)
+ if result and type(result[1]) == "table" then
+ return result
+ end
+ end
+ -- Check if we need to push a marker job to wake up sleeping workers.
+ addDelayMarkerIfNeeded(markerKey, delayedKey)
+ return 0
+else
+ return -1
+end
+`;
+var moveToDelayed = {
+ name: "moveToDelayed",
+ content: content30,
+ keys: 12
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/moveToFinished-14.js
+var content31 = `--[[
+ Move job from active to a finished status (completed o failed)
+ A job can only be moved to completed if it was active.
+ The job must be locked before it can be moved to a finished status,
+ and the lock must be released in this script.
+ Input:
+ KEYS[1] wait key
+ KEYS[2] active key
+ KEYS[3] prioritized key
+ KEYS[4] event stream key
+ KEYS[5] stalled key
+ -- Rate limiting
+ KEYS[6] rate limiter key
+ KEYS[7] delayed key
+ KEYS[8] paused key
+ KEYS[9] meta key
+ KEYS[10] pc priority counter
+ KEYS[11] completed/failed key
+ KEYS[12] jobId key
+ KEYS[13] metrics key
+ KEYS[14] marker key
+ ARGV[1] jobId
+ ARGV[2] timestamp
+ ARGV[3] msg property returnvalue / failedReason
+ ARGV[4] return value / failed reason
+ ARGV[5] target (completed/failed)
+ ARGV[6] fetch next?
+ ARGV[7] keys prefix
+ ARGV[8] opts
+ ARGV[9] job fields to update
+ opts - token - lock token
+ opts - keepJobs
+ opts - lockDuration - lock duration in milliseconds
+ opts - attempts max attempts
+ opts - maxMetricsSize
+ opts - fpof - fail parent on fail
+ opts - cpof - continue parent on fail
+ opts - idof - ignore dependency on fail
+ opts - rdof - remove dependency on fail
+ opts - name - worker name
+ Output:
+ 0 OK
+ -1 Missing key.
+ -2 Missing lock.
+ -3 Job not in active set
+ -4 Job has pending children
+ -6 Lock is not owned by this client
+ -9 Job has failed children
+ Events:
+ 'completed/failed'
+]]
+local rcall = redis.call
+--- Includes
+--[[
+ Functions to collect metrics based on a current and previous count of jobs.
+ Granualarity is fixed at 1 minute.
+]]
+--[[
+ Function to loop in batches.
+ Just a bit of warning, some commands as ZREM
+ could receive a maximum of 7000 parameters per call.
+]]
+local function batches(n, batchSize)
+ local i = 0
+ return function()
+ local from = i * batchSize + 1
+ i = i + 1
+ if (from <= n) then
+ local to = math.min(from + batchSize - 1, n)
+ return from, to
+ end
+ end
+end
+local function collectMetrics(metaKey, dataPointsList, maxDataPoints,
+ timestamp)
+ -- Increment current count
+ local count = rcall("HINCRBY", metaKey, "count", 1) - 1
+ -- Compute how many data points we need to add to the list, N.
+ local prevTS = rcall("HGET", metaKey, "prevTS")
+ if not prevTS then
+ -- If prevTS is nil, set it to the current timestamp
+ rcall("HSET", metaKey, "prevTS", timestamp, "prevCount", 0)
+ return
+ end
+ local N = math.min(math.floor(timestamp / 60000) - math.floor(prevTS / 60000), tonumber(maxDataPoints))
+ if N > 0 then
+ local delta = count - rcall("HGET", metaKey, "prevCount")
+ -- If N > 1, add N-1 zeros to the list
+ if N > 1 then
+ local points = {}
+ points[1] = delta
+ for i = 2, N do
+ points[i] = 0
+ end
+ for from, to in batches(#points, 7000) do
+ rcall("LPUSH", dataPointsList, unpack(points, from, to))
+ end
+ else
+ -- LPUSH delta to the list
+ rcall("LPUSH", dataPointsList, delta)
+ end
+ -- LTRIM to keep list to its max size
+ rcall("LTRIM", dataPointsList, 0, maxDataPoints - 1)
+ -- update prev count with current count
+ rcall("HSET", metaKey, "prevCount", count, "prevTS", timestamp)
+ end
+end
+--[[
+ Function to fetch the next job to process.
+ Tries to get the next job to avoid an extra roundtrip if the queue is
+ not closing and not rate limited.
+ Input:
+ waitKey - wait list key
+ activeKey - active list key
+ prioritizedKey - prioritized sorted set key
+ eventStreamKey - event stream key
+ rateLimiterKey - rate limiter key
+ delayedKey - delayed sorted set key
+ pausedKey - paused list key
+ metaKey - meta hash key
+ pcKey - priority counter key
+ markerKey - marker key
+ prefix - keys prefix
+ timestamp - current timestamp
+ opts - options table:
+ token (required) - lock token used when locking jobs
+ lockDuration (required) - lock duration for acquired jobs
+ limiter (optional) - rate limiter options table (e.g. { max = number })
+]]
+-- Includes
+--[[
+ Function to return the next delayed job timestamp.
+]]
+local function getNextDelayedTimestamp(delayedKey)
+ local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
+ if #result then
+ local nextTimestamp = tonumber(result[2])
+ if nextTimestamp ~= nil then
+ return nextTimestamp / 0x1000
+ end
+ end
+end
+--[[
+ Function to get current rate limit ttl.
+]]
+local function getRateLimitTTL(maxJobs, rateLimiterKey)
+ if maxJobs and maxJobs <= tonumber(rcall("GET", rateLimiterKey) or 0) then
+ local pttl = rcall("PTTL", rateLimiterKey)
+ if pttl == 0 then
+ rcall("DEL", rateLimiterKey)
+ end
+ if pttl > 0 then
+ return pttl
+ end
+ end
+ return 0
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+--[[
+ Function to move job from prioritized state to active.
+]]
+local function moveJobFromPrioritizedToActive(priorityKey, activeKey, priorityCounterKey)
+ local prioritizedJob = rcall("ZPOPMIN", priorityKey)
+ if #prioritizedJob > 0 then
+ rcall("LPUSH", activeKey, prioritizedJob[1])
+ return prioritizedJob[1]
+ else
+ rcall("DEL", priorityCounterKey)
+ end
+end
+--[[
+ Function to move job from wait state to active.
+ Input:
+ opts - token - lock token
+ opts - lockDuration
+ opts - limiter
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function prepareJobForProcessing(keyPrefix, rateLimiterKey, eventStreamKey,
+ jobId, processedOn, maxJobs, limiterDuration, markerKey, opts)
+ local jobKey = keyPrefix .. jobId
+ -- Check if we need to perform rate limiting.
+ if maxJobs then
+ local jobCounter = tonumber(rcall("INCR", rateLimiterKey))
+ if jobCounter == 1 then
+ local integerDuration = math.floor(math.abs(limiterDuration))
+ rcall("PEXPIRE", rateLimiterKey, integerDuration)
+ end
+ end
+ -- get a lock
+ if opts['token'] ~= "0" then
+ local lockKey = jobKey .. ':lock'
+ rcall("SET", lockKey, opts['token'], "PX", opts['lockDuration'])
+ end
+ local optionalValues = {}
+ if opts['name'] then
+ -- Set "processedBy" field to the worker name
+ table.insert(optionalValues, "pb")
+ table.insert(optionalValues, opts['name'])
+ end
+ rcall("XADD", eventStreamKey, "*", "event", "active", "jobId", jobId, "prev", "waiting")
+ rcall("HMSET", jobKey, "processedOn", processedOn, unpack(optionalValues))
+ rcall("HINCRBY", jobKey, "ats", 1)
+ addBaseMarkerIfNeeded(markerKey, false)
+ -- rate limit delay must be 0 in this case to prevent adding more delay
+ -- when job that is moved to active needs to be processed
+ return {rcall("HGETALL", jobKey), jobId, 0, 0} -- get job data
+end
+--[[
+ Updates the delay set, by moving delayed jobs that should
+ be processed now to "wait".
+ Events:
+ 'waiting'
+]]
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to add job considering priority.
+]]
+-- Includes
+--[[
+ Function to get priority score.
+]]
+local function getPriorityScore(priority, priorityCounterKey)
+ local prioCounter = rcall("INCR", priorityCounterKey)
+ return priority * 0x100000000 + prioCounter % 0x100000000
+end
+local function addJobWithPriority(markerKey, prioritizedKey, priority, jobId, priorityCounterKey,
+ isPausedOrMaxed)
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+-- Try to get as much as 1000 jobs at once
+local function promoteDelayedJobs(delayedKey, markerKey, targetKey, prioritizedKey,
+ eventStreamKey, prefix, timestamp, priorityCounterKey, isPaused)
+ local jobs = rcall("ZRANGEBYSCORE", delayedKey, 0, (timestamp + 1) * 0x1000 - 1, "LIMIT", 0, 1000)
+ if (#jobs > 0) then
+ rcall("ZREM", delayedKey, unpack(jobs))
+ for _, jobId in ipairs(jobs) do
+ local jobKey = prefix .. jobId
+ local priority =
+ tonumber(rcall("HGET", jobKey, "priority")) or 0
+ if priority == 0 then
+ -- LIFO or FIFO
+ rcall("LPUSH", targetKey, jobId)
+ else
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ end
+ -- Emit waiting event
+ rcall("XADD", eventStreamKey, "*", "event", "waiting", "jobId",
+ jobId, "prev", "delayed")
+ rcall("HSET", jobKey, "delay", 0)
+ end
+ addBaseMarkerIfNeeded(markerKey, isPaused)
+ end
+end
+local function fetchNextJob(waitKey, activeKey, prioritizedKey, eventStreamKey,
+ rateLimiterKey, delayedKey, pausedKey, metaKey, pcKey, markerKey, prefix,
+ timestamp, opts)
+ local target, isPausedOrMaxed, rateLimitMax, rateLimitDuration =
+ getTargetQueueList(metaKey, activeKey, waitKey, pausedKey)
+ -- Check if there are delayed jobs that can be promoted
+ promoteDelayedJobs(delayedKey, markerKey, target, prioritizedKey,
+ eventStreamKey, prefix, timestamp, pcKey, isPausedOrMaxed)
+ local maxJobs = tonumber(rateLimitMax or (opts['limiter'] and opts['limiter']['max']))
+ -- Check if we are rate limited first.
+ local expireTime = getRateLimitTTL(maxJobs, rateLimiterKey)
+ if expireTime > 0 then
+ return {0, 0, expireTime, 0}
+ end
+ -- paused or maxed queue
+ if isPausedOrMaxed then
+ return {0, 0, 0, 0}
+ end
+ local limiterDuration = (opts['limiter'] and opts['limiter']['duration']) or rateLimitDuration
+ local jobId = rcall("RPOPLPUSH", waitKey, activeKey)
+ if jobId then
+ -- Markers in waitlist DEPRECATED in v5: Remove in v6.
+ if string.sub(jobId, 1, 2) == "0:" then
+ rcall("LREM", activeKey, 1, jobId)
+ -- If jobId is special ID 0:delay (delay greater than 0), then there is no job to process
+ -- but if ID is 0:0, then there is at least 1 prioritized job to process
+ if jobId == "0:0" then
+ jobId = moveJobFromPrioritizedToActive(prioritizedKey, activeKey, pcKey)
+ return prepareJobForProcessing(prefix, rateLimiterKey,
+ eventStreamKey, jobId, timestamp, maxJobs,
+ limiterDuration, markerKey, opts)
+ end
+ else
+ return prepareJobForProcessing(prefix, rateLimiterKey,
+ eventStreamKey, jobId, timestamp, maxJobs,
+ limiterDuration, markerKey, opts)
+ end
+ else
+ jobId = moveJobFromPrioritizedToActive(prioritizedKey, activeKey, pcKey)
+ if jobId then
+ return prepareJobForProcessing(prefix, rateLimiterKey,
+ eventStreamKey, jobId, timestamp, maxJobs,
+ limiterDuration, markerKey, opts)
+ end
+ end
+ -- Return the timestamp for the next delayed job if any.
+ local nextTimestamp = getNextDelayedTimestamp(delayedKey)
+ if nextTimestamp ~= nil then
+ -- The result is guaranteed to be positive, since the
+ -- ZRANGEBYSCORE command would have return a job otherwise.
+ return {0, 0, 0, nextTimestamp}
+ end
+end
+--[[
+ Function to recursively move from waitingChildren to failed.
+]]
+-- Includes
+--[[
+ Validate and move parent to a wait status (waiting, delayed or prioritized)
+ if no pending dependencies.
+]]
+-- Includes
+--[[
+ Validate and move parent to a wait status (waiting, delayed or prioritized) if needed.
+]]
+-- Includes
+--[[
+ Move parent to a wait status (wait, prioritized or delayed)
+]]
+-- Includes
+--[[
+ Add delay marker if needed.
+]]
+-- Includes
+local function addDelayMarkerIfNeeded(markerKey, delayedKey)
+ local nextTimestamp = getNextDelayedTimestamp(delayedKey)
+ if nextTimestamp ~= nil then
+ -- Replace the score of the marker with the newest known
+ -- next timestamp.
+ rcall("ZADD", markerKey, nextTimestamp, "1")
+ end
+end
+--[[
+ Function to check if queue is paused or maxed
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function isQueuePausedOrMaxed(queueMetaKey, activeKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency")
+ if queueAttributes[1] then
+ return true
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ return activeCount >= tonumber(queueAttributes[2])
+ end
+ end
+ return false
+end
+local function moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
+ local parentWaitKey = parentQueueKey .. ":wait"
+ local parentPausedKey = parentQueueKey .. ":paused"
+ local parentActiveKey = parentQueueKey .. ":active"
+ local parentMetaKey = parentQueueKey .. ":meta"
+ local parentMarkerKey = parentQueueKey .. ":marker"
+ local jobAttributes = rcall("HMGET", parentKey, "priority", "delay")
+ local priority = tonumber(jobAttributes[1]) or 0
+ local delay = tonumber(jobAttributes[2]) or 0
+ if delay > 0 then
+ local delayedTimestamp = tonumber(timestamp) + delay
+ local score = delayedTimestamp * 0x1000
+ local parentDelayedKey = parentQueueKey .. ":delayed"
+ rcall("ZADD", parentDelayedKey, score, parentId)
+ rcall("XADD", parentQueueKey .. ":events", "*", "event", "delayed", "jobId", parentId, "delay",
+ delayedTimestamp)
+ addDelayMarkerIfNeeded(parentMarkerKey, parentDelayedKey)
+ else
+ if priority == 0 then
+ local parentTarget, isParentPausedOrMaxed = getTargetQueueList(parentMetaKey, parentActiveKey,
+ parentWaitKey, parentPausedKey)
+ addJobInTargetList(parentTarget, parentMarkerKey, "RPUSH", isParentPausedOrMaxed, parentId)
+ else
+ local isPausedOrMaxed = isQueuePausedOrMaxed(parentMetaKey, parentActiveKey)
+ addJobWithPriority(parentMarkerKey, parentQueueKey .. ":prioritized", priority, parentId,
+ parentQueueKey .. ":pc", isPausedOrMaxed)
+ end
+ rcall("XADD", parentQueueKey .. ":events", "*", "event", "waiting", "jobId", parentId, "prev",
+ "waiting-children")
+ end
+end
+local function moveParentToWaitIfNeeded(parentQueueKey, parentKey, parentId, timestamp)
+ if rcall("EXISTS", parentKey) == 1 then
+ local parentWaitingChildrenKey = parentQueueKey .. ":waiting-children"
+ if rcall("ZSCORE", parentWaitingChildrenKey, parentId) then
+ rcall("ZREM", parentWaitingChildrenKey, parentId)
+ moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
+ end
+ end
+end
+local function moveParentToWaitIfNoPendingDependencies(parentQueueKey, parentDependenciesKey, parentKey,
+ parentId, timestamp)
+ local doNotHavePendingDependencies = rcall("SCARD", parentDependenciesKey) == 0
+ if doNotHavePendingDependencies then
+ moveParentToWaitIfNeeded(parentQueueKey, parentKey, parentId, timestamp)
+ end
+end
+local handleChildFailureAndMoveParentToWait = function (parentQueueKey, parentKey, parentId, jobIdKey, timestamp)
+ if rcall("EXISTS", parentKey) == 1 then
+ local parentWaitingChildrenKey = parentQueueKey .. ":waiting-children"
+ local parentDelayedKey = parentQueueKey .. ":delayed"
+ local parentWaitingChildrenOrDelayedKey
+ if rcall("ZSCORE", parentWaitingChildrenKey, parentId) then
+ parentWaitingChildrenOrDelayedKey = parentWaitingChildrenKey
+ elseif rcall("ZSCORE", parentDelayedKey, parentId) then
+ parentWaitingChildrenOrDelayedKey = parentDelayedKey
+ rcall("HSET", parentKey, "delay", 0)
+ end
+ if parentWaitingChildrenOrDelayedKey then
+ rcall("ZREM", parentWaitingChildrenOrDelayedKey, parentId)
+ local deferredFailure = "child " .. jobIdKey .. " failed"
+ rcall("HSET", parentKey, "defa", deferredFailure)
+ moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
+ else
+ if not rcall("ZSCORE", parentQueueKey .. ":failed", parentId) then
+ local deferredFailure = "child " .. jobIdKey .. " failed"
+ rcall("HSET", parentKey, "defa", deferredFailure)
+ end
+ end
+ end
+end
+local moveChildFromDependenciesIfNeeded = function (rawParentData, childKey, failedReason, timestamp)
+ if rawParentData then
+ local parentData = cjson.decode(rawParentData)
+ local parentKey = parentData['queueKey'] .. ':' .. parentData['id']
+ local parentDependenciesChildrenKey = parentKey .. ":dependencies"
+ if parentData['fpof'] then
+ if rcall("SREM", parentDependenciesChildrenKey, childKey) == 1 then
+ local parentUnsuccessfulChildrenKey = parentKey .. ":unsuccessful"
+ rcall("ZADD", parentUnsuccessfulChildrenKey, timestamp, childKey)
+ handleChildFailureAndMoveParentToWait(
+ parentData['queueKey'],
+ parentKey,
+ parentData['id'],
+ childKey,
+ timestamp
+ )
+ end
+ elseif parentData['cpof'] then
+ if rcall("SREM", parentDependenciesChildrenKey, childKey) == 1 then
+ local parentFailedChildrenKey = parentKey .. ":failed"
+ rcall("HSET", parentFailedChildrenKey, childKey, failedReason)
+ moveParentToWaitIfNeeded(parentData['queueKey'], parentKey, parentData['id'], timestamp)
+ end
+ elseif parentData['idof'] or parentData['rdof'] then
+ if rcall("SREM", parentDependenciesChildrenKey, childKey) == 1 then
+ moveParentToWaitIfNoPendingDependencies(parentData['queueKey'], parentDependenciesChildrenKey,
+ parentKey, parentData['id'], timestamp)
+ if parentData['idof'] then
+ local parentFailedChildrenKey = parentKey .. ":failed"
+ rcall("HSET", parentFailedChildrenKey, childKey, failedReason)
+ end
+ end
+ end
+ end
+end
+--[[
+ Function to remove deduplication key if needed
+ when a job is moved to completed or failed states.
+]]
+local function removeDeduplicationKeyIfNeededOnFinalization(prefixKey,
+ deduplicationId, jobId)
+ if deduplicationId then
+ local deduplicationKey = prefixKey .. "de:" .. deduplicationId
+ local pttl = rcall("PTTL", deduplicationKey)
+ if pttl == 0 then
+ return rcall("DEL", deduplicationKey)
+ end
+ if pttl == -1 then
+ local currentJobId = rcall('GET', deduplicationKey)
+ if currentJobId and currentJobId == jobId then
+ return rcall("DEL", deduplicationKey)
+ end
+ end
+ end
+end
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+--[[
+ Functions to remove jobs by max age.
+]]
+-- Includes
+--[[
+ Function to remove job.
+]]
+-- Includes
+--[[
+ Function to remove deduplication key if needed
+ when a job is being removed.
+]]
+local function removeDeduplicationKeyIfNeededOnRemoval(prefixKey,
+ jobId, deduplicationId)
+ if deduplicationId then
+ local deduplicationKey = prefixKey .. "de:" .. deduplicationId
+ local currentJobId = rcall('GET', deduplicationKey)
+ if currentJobId and currentJobId == jobId then
+ rcall("DEL", deduplicationKey)
+ -- Also clean up any pending dedup-next data for this dedup ID
+ rcall("DEL", prefixKey .. "dn:" .. deduplicationId)
+ return 1
+ end
+ end
+end
+--[[
+ Check if this job has a parent. If so we will just remove it from
+ the parent child list, but if it is the last child we should move the parent to "wait/paused"
+ which requires code from "moveToFinished"
+]]
+-- Includes
+--[[
+ Functions to destructure job key.
+ Just a bit of warning, these functions may be a bit slow and affect performance significantly.
+]]
+local getJobIdFromKey = function (jobKey)
+ return string.match(jobKey, ".*:(.*)")
+end
+local getJobKeyPrefix = function (jobKey, jobId)
+ return string.sub(jobKey, 0, #jobKey - #jobId)
+end
+local function _moveParentToWait(parentPrefix, parentId, emitEvent)
+ local parentTarget, isPausedOrMaxed = getTargetQueueList(parentPrefix .. "meta", parentPrefix .. "active",
+ parentPrefix .. "wait", parentPrefix .. "paused")
+ addJobInTargetList(parentTarget, parentPrefix .. "marker", "RPUSH", isPausedOrMaxed, parentId)
+ if emitEvent then
+ local parentEventStream = parentPrefix .. "events"
+ rcall("XADD", parentEventStream, "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
+ end
+end
+local function removeParentDependencyKey(jobKey, hard, parentKey, baseKey, debounceId)
+ if parentKey then
+ local parentDependenciesKey = parentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(parentKey)
+ local parentPrefix = getJobKeyPrefix(parentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then -- remove parent in same queue
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(parentKey, hard, nil, baseKey, nil)
+ removeJobKeys(parentKey)
+ if debounceId then
+ rcall("DEL", parentPrefix .. "de:" .. debounceId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ else
+ local parentAttributes = rcall("HMGET", jobKey, "parentKey", "deid")
+ local missedParentKey = parentAttributes[1]
+ if( (type(missedParentKey) == "string") and missedParentKey ~= ""
+ and (rcall("EXISTS", missedParentKey) == 1)) then
+ local parentDependenciesKey = missedParentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(missedParentKey)
+ local parentPrefix = getJobKeyPrefix(missedParentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(missedParentKey, hard, nil, baseKey, nil)
+ removeJobKeys(missedParentKey)
+ if parentAttributes[2] then
+ rcall("DEL", parentPrefix .. "de:" .. parentAttributes[2])
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ end
+ end
+ return false
+end
+local function removeJob(jobId, hard, baseKey, shouldRemoveDeduplicationKey)
+ local jobKey = baseKey .. jobId
+ removeParentDependencyKey(jobKey, hard, nil, baseKey)
+ if shouldRemoveDeduplicationKey then
+ local deduplicationId = rcall("HGET", jobKey, "deid")
+ removeDeduplicationKeyIfNeededOnRemoval(baseKey, jobId, deduplicationId)
+ end
+ removeJobKeys(jobKey)
+end
+local function removeJobsByMaxAge(timestamp, maxAge, targetSet, prefix, maxLimit)
+ local start = timestamp - maxAge * 1000
+ local jobIds = rcall("ZREVRANGEBYSCORE", targetSet, start, "-inf", "LIMIT", 0, maxLimit)
+ for i, jobId in ipairs(jobIds) do
+ removeJob(jobId, false, prefix, false --[[remove debounce key]])
+ end
+ if #jobIds > 0 then
+ if #jobIds < maxLimit then
+ rcall("ZREMRANGEBYSCORE", targetSet, "-inf", start)
+ else
+ for from, to in batches(#jobIds, 7000) do
+ rcall("ZREM", targetSet, unpack(jobIds, from, to))
+ end
+ end
+ end
+end
+--[[
+ Functions to remove jobs by max count.
+]]
+-- Includes
+local function removeJobsByMaxCount(maxCount, targetSet, prefix)
+ local start = maxCount
+ local jobIds = rcall("ZREVRANGE", targetSet, start, -1)
+ for i, jobId in ipairs(jobIds) do
+ removeJob(jobId, false, prefix, false --[[remove debounce key]])
+ end
+ rcall("ZREMRANGEBYRANK", targetSet, 0, -(maxCount + 1))
+end
+local function removeLock(jobKey, stalledKey, token, jobId)
+ if token ~= "0" then
+ local lockKey = jobKey .. ':lock'
+ local lockToken = rcall("GET", lockKey)
+ if lockToken == token then
+ rcall("DEL", lockKey)
+ rcall("SREM", stalledKey, jobId)
+ else
+ if lockToken then
+ -- Lock exists but token does not match
+ return -6
+ else
+ -- Lock is missing completely
+ return -2
+ end
+ end
+ end
+ return 0
+end
+--[[
+ Function to create a new job from stored dedup-next data
+ when a deduplicated job with keepLastIfActive finishes.
+ At most one next job is created per deduplication ID.
+ Multiple triggers while active overwrite the dedup-next data,
+ so only the latest data is used.
+]]
+-- Includes
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+--[[
+ Function to set the deduplication key for a job.
+ Uses TTL from deduplication opts if provided.
+]]
+local function setDeduplicationKey(deduplicationKey, jobId, deduplicationOpts)
+ local ttl = deduplicationOpts and deduplicationOpts['ttl']
+ if ttl and ttl > 0 then
+ rcall('SET', deduplicationKey, jobId, 'PX', ttl)
+ else
+ rcall('SET', deduplicationKey, jobId)
+ end
+end
+--[[
+ Shared helper to store a job and enqueue it into the appropriate list/set.
+ Handles delayed, prioritized, and standard (LIFO/FIFO) jobs.
+ Emits the appropriate event after enqueuing ("delayed" or "waiting").
+ Returns delay, priority from storeJob.
+]]
+-- Includes
+--[[
+ Adds a delayed job to the queue by doing the following:
+ - Creates a new job key with the job data.
+ - adds to delayed zset.
+ - Emits a global event 'delayed' if the job is delayed.
+]]
+-- Includes
+--[[
+ Bake in the job id first 12 bits into the timestamp
+ to guarantee correct execution order of delayed jobs
+ (up to 4096 jobs per given timestamp or 4096 jobs apart per timestamp)
+ WARNING: Jobs that are so far apart that they wrap around will cause FIFO to fail
+]]
+local function getDelayedScore(delayedKey, timestamp, delay)
+ local delayedTimestamp = (delay > 0 and (tonumber(timestamp) + delay)) or tonumber(timestamp)
+ local minScore = delayedTimestamp * 0x1000
+ local maxScore = (delayedTimestamp + 1 ) * 0x1000 - 1
+ local result = rcall("ZREVRANGEBYSCORE", delayedKey, maxScore,
+ minScore, "WITHSCORES","LIMIT", 0, 1)
+ if #result then
+ local currentMaxScore = tonumber(result[2])
+ if currentMaxScore ~= nil then
+ if currentMaxScore >= maxScore then
+ return maxScore, delayedTimestamp
+ else
+ return currentMaxScore + 1, delayedTimestamp
+ end
+ end
+ end
+ return minScore, delayedTimestamp
+end
+local function addDelayedJob(jobId, delayedKey, eventsKey, timestamp,
+ maxEvents, markerKey, delay)
+ local score, delayedTimestamp = getDelayedScore(delayedKey, timestamp, tonumber(delay))
+ rcall("ZADD", delayedKey, score, jobId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "delayed",
+ "jobId", jobId, "delay", delayedTimestamp)
+ -- mark that a delayed job is available
+ addDelayMarkerIfNeeded(markerKey, delayedKey)
+end
+--[[
+ Function to store a job
+]]
+local function storeJob(eventsKey, jobIdKey, jobId, name, data, opts, timestamp,
+ parentKey, parentData, repeatJobKey)
+ local jsonOpts = cjson.encode(opts)
+ local delay = opts['delay'] or 0
+ local priority = opts['priority'] or 0
+ local debounceId = opts['de'] and opts['de']['id']
+ local optionalValues = {}
+ if parentKey ~= nil then
+ table.insert(optionalValues, "parentKey")
+ table.insert(optionalValues, parentKey)
+ table.insert(optionalValues, "parent")
+ table.insert(optionalValues, parentData)
+ end
+ if repeatJobKey then
+ table.insert(optionalValues, "rjk")
+ table.insert(optionalValues, repeatJobKey)
+ end
+ if debounceId then
+ table.insert(optionalValues, "deid")
+ table.insert(optionalValues, debounceId)
+ end
+ rcall("HMSET", jobIdKey, "name", name, "data", data, "opts", jsonOpts,
+ "timestamp", timestamp, "delay", delay, "priority", priority,
+ unpack(optionalValues))
+ rcall("XADD", eventsKey, "*", "event", "added", "jobId", jobId, "name", name)
+ return delay, priority
+end
+local function storeAndEnqueueJob(eventsKey, jobIdKey, jobId, name, data, opts,
+ timestamp, parentKey, parentData, repeatJobKey, maxEvents,
+ waitKey, pausedKey, activeKey, metaKey, prioritizedKey,
+ priorityCounterKey, delayedKey, markerKey)
+ local delay, priority = storeJob(eventsKey, jobIdKey, jobId, name, data,
+ opts, timestamp, parentKey, parentData, repeatJobKey)
+ if delay ~= 0 and delayedKey then
+ addDelayedJob(jobId, delayedKey, eventsKey, timestamp, maxEvents, markerKey, delay)
+ else
+ local target, isPausedOrMaxed = getTargetQueueList(metaKey, activeKey, waitKey, pausedKey)
+ if priority > 0 then
+ addJobWithPriority(markerKey, prioritizedKey, priority, jobId,
+ priorityCounterKey, isPausedOrMaxed)
+ else
+ local pushCmd = opts['lifo'] and 'RPUSH' or 'LPUSH'
+ addJobInTargetList(target, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ end
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "waiting",
+ "jobId", jobId)
+ end
+ return delay, priority
+end
+local function requeueDeduplicatedJob(prefix, deduplicationId, eventStreamKey,
+ metaKey, activeKey, waitKey, pausedKey, markerKey, prioritizedKey,
+ priorityCounterKey, delayedKey, timestamp)
+ local deduplicationNextKey = prefix .. "dn:" .. deduplicationId
+ if rcall("EXISTS", deduplicationNextKey) == 1 then
+ local nextData = rcall("HMGET", deduplicationNextKey,
+ "name", "data", "opts", "pk", "pd", "pdk", "rjk")
+ local newJobId = rcall("INCR", prefix .. "id") .. ""
+ local newJobIdKey = prefix .. newJobId
+ local newOpts = cjson.decode(nextData[3])
+ local deduplicationKey = prefix .. "de:" .. deduplicationId
+ local parentKey = nextData[4] or nil
+ local parentData = nextData[5] or nil
+ local parentDependenciesKey = nextData[6] or nil
+ local repeatJobKey = nextData[7] or nil
+ -- Set dedup key for the new job (without TTL when keepLastIfActive,
+ -- so the key outlives the job's active duration)
+ local deOpts = newOpts['de']
+ if deOpts and deOpts['keepLastIfActive'] then
+ rcall('SET', deduplicationKey, newJobId)
+ else
+ setDeduplicationKey(deduplicationKey, newJobId, deOpts)
+ end
+ -- Store and enqueue using the shared helper (handles priority/lifo/delayed)
+ local maxEvents = getOrSetMaxEvents(metaKey)
+ storeAndEnqueueJob(eventStreamKey, newJobIdKey, newJobId, nextData[1], nextData[2],
+ newOpts, timestamp, parentKey, parentData, repeatJobKey, maxEvents,
+ waitKey, pausedKey, activeKey, metaKey, prioritizedKey,
+ priorityCounterKey, delayedKey, markerKey)
+ -- Register as child dependency if the job has a parent
+ if parentDependenciesKey then
+ rcall("SADD", parentDependenciesKey, newJobIdKey)
+ end
+ -- Only delete the dedup-next hash after the job is fully created,
+ -- so that if any step above errors, the data is not permanently lost.
+ rcall("DEL", deduplicationNextKey)
+ end
+end
+--[[
+ Function to trim events, default 10000.
+]]
+-- Includes
+local function trimEvents(metaKey, eventStreamKey)
+ local maxEvents = getOrSetMaxEvents(metaKey)
+ if maxEvents then
+ rcall("XTRIM", eventStreamKey, "MAXLEN", "~", maxEvents)
+ else
+ rcall("XTRIM", eventStreamKey, "MAXLEN", "~", 10000)
+ end
+end
+--[[
+ Validate and move or add dependencies to parent.
+]]
+-- Includes
+local function updateParentDepsIfNeeded(parentKey, parentQueueKey, parentDependenciesKey,
+ parentId, jobIdKey, returnvalue, timestamp )
+ local processedSet = parentKey .. ":processed"
+ rcall("HSET", processedSet, jobIdKey, returnvalue)
+ moveParentToWaitIfNoPendingDependencies(parentQueueKey, parentDependenciesKey, parentKey, parentId, timestamp)
+end
+--[[
+ Function to update a bunch of fields in a job.
+]]
+local function updateJobFields(jobKey, msgpackedFields)
+ if msgpackedFields and #msgpackedFields > 0 then
+ local fieldsToUpdate = cmsgpack.unpack(msgpackedFields)
+ if fieldsToUpdate then
+ rcall("HMSET", jobKey, unpack(fieldsToUpdate))
+ end
+ end
+end
+local jobIdKey = KEYS[12]
+if rcall("EXISTS", jobIdKey) == 1 then -- Make sure job exists
+ -- Make sure it does not have pending dependencies
+ -- It must happen before removing lock
+ if ARGV[5] == "completed" then
+ if rcall("SCARD", jobIdKey .. ":dependencies") ~= 0 then
+ return -4
+ end
+ if rcall("ZCARD", jobIdKey .. ":unsuccessful") ~= 0 then
+ return -9
+ end
+ end
+ local opts = cmsgpack.unpack(ARGV[8])
+ local token = opts['token']
+ local errorCode = removeLock(jobIdKey, KEYS[5], token, ARGV[1])
+ if errorCode < 0 then
+ return errorCode
+ end
+ updateJobFields(jobIdKey, ARGV[9]);
+ local attempts = opts['attempts']
+ local maxMetricsSize = opts['maxMetricsSize']
+ local maxCount = opts['keepJobs']['count']
+ local maxAge = opts['keepJobs']['age']
+ local maxLimit = opts['keepJobs']['limit'] or 1000
+ local jobAttributes = rcall("HMGET", jobIdKey, "parentKey", "parent", "deid")
+ local parentKey = jobAttributes[1] or ""
+ local parentId = ""
+ local parentQueueKey = ""
+ if jobAttributes[2] then -- TODO: need to revisit this logic if it's still needed
+ local jsonDecodedParent = cjson.decode(jobAttributes[2])
+ parentId = jsonDecodedParent['id']
+ parentQueueKey = jsonDecodedParent['queueKey']
+ end
+ local jobId = ARGV[1]
+ local timestamp = ARGV[2]
+ -- Remove from active list (if not active we shall return error)
+ local numRemovedElements = rcall("LREM", KEYS[2], -1, jobId)
+ if (numRemovedElements < 1) then
+ return -3
+ end
+ local eventStreamKey = KEYS[4]
+ local metaKey = KEYS[9]
+ -- Trim events before emiting them to avoid trimming events emitted in this script
+ trimEvents(metaKey, eventStreamKey)
+ local prefix = ARGV[7]
+ removeDeduplicationKeyIfNeededOnFinalization(prefix, jobAttributes[3], jobId)
+ -- Check if there is requeue data for this dedup ID (keepLastIfActive mode)
+ if jobAttributes[3] then
+ requeueDeduplicatedJob(prefix, jobAttributes[3], eventStreamKey,
+ metaKey, KEYS[2], KEYS[1], KEYS[8], KEYS[14], KEYS[3], KEYS[10],
+ KEYS[7], timestamp)
+ end
+ -- If job has a parent we need to
+ -- 1) remove this job id from parents dependencies
+ -- 2) move the job Id to parent "processed" set
+ -- 3) push the results into parent "results" list
+ -- 4) if parent's dependencies is empty, then move parent to "wait/paused". Note it may be a different queue!.
+ if parentId == "" and parentKey ~= "" then
+ parentId = getJobIdFromKey(parentKey)
+ parentQueueKey = getJobKeyPrefix(parentKey, ":" .. parentId)
+ end
+ if parentId ~= "" then
+ if ARGV[5] == "completed" then
+ local dependenciesSet = parentKey .. ":dependencies"
+ if rcall("SREM", dependenciesSet, jobIdKey) == 1 then
+ updateParentDepsIfNeeded(parentKey, parentQueueKey, dependenciesSet, parentId, jobIdKey, ARGV[4],
+ timestamp)
+ end
+ else
+ moveChildFromDependenciesIfNeeded(jobAttributes[2], jobIdKey, ARGV[4], timestamp)
+ end
+ end
+ local attemptsMade = rcall("HINCRBY", jobIdKey, "atm", 1)
+ -- Remove job?
+ if maxCount ~= 0 then
+ local targetSet = KEYS[11]
+ -- Add to complete/failed set
+ rcall("ZADD", targetSet, timestamp, jobId)
+ rcall("HSET", jobIdKey, ARGV[3], ARGV[4], "finishedOn", timestamp)
+ -- "returnvalue" / "failedReason" and "finishedOn"
+ if ARGV[5] == "failed" then
+ rcall("HDEL", jobIdKey, "defa")
+ end
+ -- Remove old jobs?
+ if maxAge ~= nil then
+ removeJobsByMaxAge(timestamp, maxAge, targetSet, prefix, maxLimit)
+ end
+ if maxCount ~= nil and maxCount > 0 then
+ removeJobsByMaxCount(maxCount, targetSet, prefix)
+ end
+ else
+ removeJobKeys(jobIdKey)
+ if parentKey ~= "" then
+ -- TODO: when a child is removed when finished, result or failure in parent
+ -- must not be deleted, those value references should be deleted when the parent
+ -- is deleted
+ removeParentDependencyKey(jobIdKey, false, parentKey, jobAttributes[3])
+ end
+ end
+ rcall("XADD", eventStreamKey, "*", "event", ARGV[5], "jobId", jobId, ARGV[3], ARGV[4], "prev", "active")
+ if ARGV[5] == "failed" then
+ if tonumber(attemptsMade) >= tonumber(attempts) then
+ rcall("XADD", eventStreamKey, "*", "event", "retries-exhausted", "jobId", jobId, "attemptsMade",
+ attemptsMade)
+ end
+ end
+ -- Collect metrics
+ if maxMetricsSize ~= "" then
+ collectMetrics(KEYS[13], KEYS[13] .. ':data', maxMetricsSize, timestamp)
+ end
+ -- Try to get next job to avoid an extra roundtrip if the queue is not closing,
+ -- and not rate limited.
+ if (ARGV[6] == "1") then
+ local result = fetchNextJob(KEYS[1], KEYS[2], KEYS[3], eventStreamKey,
+ KEYS[6], KEYS[7], KEYS[8], metaKey, KEYS[10], KEYS[14], prefix,
+ timestamp, opts)
+ if result then
+ return result
+ end
+ end
+ local waitLen = rcall("LLEN", KEYS[1])
+ if waitLen == 0 then
+ local activeLen = rcall("LLEN", KEYS[2])
+ if activeLen == 0 then
+ local prioritizedLen = rcall("ZCARD", KEYS[3])
+ if prioritizedLen == 0 then
+ rcall("XADD", eventStreamKey, "*", "event", "drained")
+ end
+ end
+ end
+ return 0
+else
+ return -1
+end
+`;
+var moveToFinished = {
+ name: "moveToFinished",
+ content: content31,
+ keys: 14
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/moveToWaitingChildren-7.js
+var content32 = `--[[
+ Moves job from active to waiting children set.
+ Input:
+ KEYS[1] active key
+ KEYS[2] wait-children key
+ KEYS[3] job key
+ KEYS[4] job dependencies key
+ KEYS[5] job unsuccessful key
+ KEYS[6] stalled key
+ KEYS[7] events key
+ ARGV[1] token
+ ARGV[2] child key
+ ARGV[3] timestamp
+ ARGV[4] jobId
+ ARGV[5] prefix
+ Output:
+ 0 - OK
+ 1 - There are not pending dependencies.
+ -1 - Missing job.
+ -2 - Missing lock
+ -3 - Job not in active set
+ -9 - Job has failed children
+]]
+local rcall = redis.call
+local activeKey = KEYS[1]
+local waitingChildrenKey = KEYS[2]
+local jobKey = KEYS[3]
+local jobDependenciesKey = KEYS[4]
+local jobUnsuccessfulKey = KEYS[5]
+local stalledKey = KEYS[6]
+local eventStreamKey = KEYS[7]
+local token = ARGV[1]
+local timestamp = ARGV[3]
+local jobId = ARGV[4]
+--- Includes
+local function removeLock(jobKey, stalledKey, token, jobId)
+ if token ~= "0" then
+ local lockKey = jobKey .. ':lock'
+ local lockToken = rcall("GET", lockKey)
+ if lockToken == token then
+ rcall("DEL", lockKey)
+ rcall("SREM", stalledKey, jobId)
+ else
+ if lockToken then
+ -- Lock exists but token does not match
+ return -6
+ else
+ -- Lock is missing completely
+ return -2
+ end
+ end
+ end
+ return 0
+end
+local function removeJobFromActive(activeKey, stalledKey, jobKey, jobId,
+ token)
+ local errorCode = removeLock(jobKey, stalledKey, token, jobId)
+ if errorCode < 0 then
+ return errorCode
+ end
+ local numRemovedElements = rcall("LREM", activeKey, -1, jobId)
+ if numRemovedElements < 1 then
+ return -3
+ end
+ return 0
+end
+local function moveToWaitingChildren(activeKey, waitingChildrenKey, stalledKey, eventStreamKey,
+ jobKey, jobId, timestamp, token)
+ local errorCode = removeJobFromActive(activeKey, stalledKey, jobKey, jobId, token)
+ if errorCode < 0 then
+ return errorCode
+ end
+ local score = tonumber(timestamp)
+ rcall("ZADD", waitingChildrenKey, score, jobId)
+ rcall("XADD", eventStreamKey, "*", "event", "waiting-children", "jobId", jobId, 'prev', 'active')
+ return 0
+end
+if rcall("EXISTS", jobKey) == 1 then
+ if rcall("ZCARD", jobUnsuccessfulKey) ~= 0 then
+ return -9
+ else
+ if ARGV[2] ~= "" then
+ if rcall("SISMEMBER", jobDependenciesKey, ARGV[2]) ~= 0 then
+ return moveToWaitingChildren(activeKey, waitingChildrenKey, stalledKey, eventStreamKey,
+ jobKey, jobId, timestamp, token)
+ end
+ return 1
+ else
+ if rcall("SCARD", jobDependenciesKey) ~= 0 then
+ return moveToWaitingChildren(activeKey, waitingChildrenKey, stalledKey, eventStreamKey,
+ jobKey, jobId, timestamp, token)
+ end
+ return 1
+ end
+ end
+end
+return -1
+`;
+var moveToWaitingChildren = {
+ name: "moveToWaitingChildren",
+ content: content32,
+ keys: 7
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/obliterate-2.js
+var content33 = `--[[
+ Completely obliterates a queue and all of its contents
+ This command completely destroys a queue including all of its jobs, current or past
+ leaving no trace of its existence. Since this script needs to iterate to find all the job
+ keys, consider that this call may be slow for very large queues.
+ The queue needs to be "paused" or it will return an error
+ If the queue has currently active jobs then the script by default will return error,
+ however this behaviour can be overrided using the 'force' option.
+ Input:
+ KEYS[1] meta
+ KEYS[2] base
+ ARGV[1] count
+ ARGV[2] force
+]]
+local maxCount = tonumber(ARGV[1])
+local baseKey = KEYS[2]
+local rcall = redis.call
+-- Includes
+--[[
+ Functions to remove jobs.
+]]
+-- Includes
+--[[
+ Function to remove job.
+]]
+-- Includes
+--[[
+ Function to remove deduplication key if needed
+ when a job is being removed.
+]]
+local function removeDeduplicationKeyIfNeededOnRemoval(prefixKey,
+ jobId, deduplicationId)
+ if deduplicationId then
+ local deduplicationKey = prefixKey .. "de:" .. deduplicationId
+ local currentJobId = rcall('GET', deduplicationKey)
+ if currentJobId and currentJobId == jobId then
+ rcall("DEL", deduplicationKey)
+ -- Also clean up any pending dedup-next data for this dedup ID
+ rcall("DEL", prefixKey .. "dn:" .. deduplicationId)
+ return 1
+ end
+ end
+end
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+--[[
+ Check if this job has a parent. If so we will just remove it from
+ the parent child list, but if it is the last child we should move the parent to "wait/paused"
+ which requires code from "moveToFinished"
+]]
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Functions to destructure job key.
+ Just a bit of warning, these functions may be a bit slow and affect performance significantly.
+]]
+local getJobIdFromKey = function (jobKey)
+ return string.match(jobKey, ".*:(.*)")
+end
+local getJobKeyPrefix = function (jobKey, jobId)
+ return string.sub(jobKey, 0, #jobKey - #jobId)
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+local function _moveParentToWait(parentPrefix, parentId, emitEvent)
+ local parentTarget, isPausedOrMaxed = getTargetQueueList(parentPrefix .. "meta", parentPrefix .. "active",
+ parentPrefix .. "wait", parentPrefix .. "paused")
+ addJobInTargetList(parentTarget, parentPrefix .. "marker", "RPUSH", isPausedOrMaxed, parentId)
+ if emitEvent then
+ local parentEventStream = parentPrefix .. "events"
+ rcall("XADD", parentEventStream, "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
+ end
+end
+local function removeParentDependencyKey(jobKey, hard, parentKey, baseKey, debounceId)
+ if parentKey then
+ local parentDependenciesKey = parentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(parentKey)
+ local parentPrefix = getJobKeyPrefix(parentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then -- remove parent in same queue
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(parentKey, hard, nil, baseKey, nil)
+ removeJobKeys(parentKey)
+ if debounceId then
+ rcall("DEL", parentPrefix .. "de:" .. debounceId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ else
+ local parentAttributes = rcall("HMGET", jobKey, "parentKey", "deid")
+ local missedParentKey = parentAttributes[1]
+ if( (type(missedParentKey) == "string") and missedParentKey ~= ""
+ and (rcall("EXISTS", missedParentKey) == 1)) then
+ local parentDependenciesKey = missedParentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(missedParentKey)
+ local parentPrefix = getJobKeyPrefix(missedParentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(missedParentKey, hard, nil, baseKey, nil)
+ removeJobKeys(missedParentKey)
+ if parentAttributes[2] then
+ rcall("DEL", parentPrefix .. "de:" .. parentAttributes[2])
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ end
+ end
+ return false
+end
+local function removeJob(jobId, hard, baseKey, shouldRemoveDeduplicationKey)
+ local jobKey = baseKey .. jobId
+ removeParentDependencyKey(jobKey, hard, nil, baseKey)
+ if shouldRemoveDeduplicationKey then
+ local deduplicationId = rcall("HGET", jobKey, "deid")
+ removeDeduplicationKeyIfNeededOnRemoval(baseKey, jobId, deduplicationId)
+ end
+ removeJobKeys(jobKey)
+end
+local function removeJobs(keys, hard, baseKey, max)
+ for i, key in ipairs(keys) do
+ removeJob(key, hard, baseKey, true --[[remove debounce key]])
+ end
+ return max - #keys
+end
+--[[
+ Functions to remove jobs.
+]]
+-- Includes
+--[[
+ Function to filter out jobs to ignore from a table.
+]]
+local function filterOutJobsToIgnore(jobs, jobsToIgnore)
+ local filteredJobs = {}
+ for i = 1, #jobs do
+ if not jobsToIgnore[jobs[i]] then
+ table.insert(filteredJobs, jobs[i])
+ end
+ end
+ return filteredJobs
+end
+local function getListItems(keyName, max)
+ return rcall('LRANGE', keyName, 0, max - 1)
+end
+local function removeListJobs(keyName, hard, baseKey, max, jobsToIgnore)
+ local jobs = getListItems(keyName, max)
+ if jobsToIgnore then
+ jobs = filterOutJobsToIgnore(jobs, jobsToIgnore)
+ end
+ local count = removeJobs(jobs, hard, baseKey, max)
+ rcall("LTRIM", keyName, #jobs, -1)
+ return count
+end
+-- Includes
+--[[
+ Function to loop in batches.
+ Just a bit of warning, some commands as ZREM
+ could receive a maximum of 7000 parameters per call.
+]]
+local function batches(n, batchSize)
+ local i = 0
+ return function()
+ local from = i * batchSize + 1
+ i = i + 1
+ if (from <= n) then
+ local to = math.min(from + batchSize - 1, n)
+ return from, to
+ end
+ end
+end
+--[[
+ Function to get ZSet items.
+]]
+local function getZSetItems(keyName, max)
+ return rcall('ZRANGE', keyName, 0, max - 1)
+end
+local function removeZSetJobs(keyName, hard, baseKey, max, jobsToIgnore)
+ local jobs = getZSetItems(keyName, max)
+ if jobsToIgnore then
+ jobs = filterOutJobsToIgnore(jobs, jobsToIgnore)
+ end
+ local count = removeJobs(jobs, hard, baseKey, max)
+ if(#jobs > 0) then
+ for from, to in batches(#jobs, 7000) do
+ rcall("ZREM", keyName, unpack(jobs, from, to))
+ end
+ end
+ return count
+end
+local function removeLockKeys(keys)
+ for i, key in ipairs(keys) do
+ rcall("DEL", baseKey .. key .. ':lock')
+ end
+end
+-- 1) Check if paused, if not return with error.
+if rcall("HEXISTS", KEYS[1], "paused") ~= 1 then
+ return -1 -- Error, NotPaused
+end
+-- 2) Check if there are active jobs, if there are and not "force" return error.
+local activeKey = baseKey .. 'active'
+local activeJobs = getListItems(activeKey, maxCount)
+if (#activeJobs > 0) then
+ if(ARGV[2] == "") then
+ return -2 -- Error, ExistActiveJobs
+ end
+end
+removeLockKeys(activeJobs)
+maxCount = removeJobs(activeJobs, true, baseKey, maxCount)
+rcall("LTRIM", activeKey, #activeJobs, -1)
+if(maxCount <= 0) then
+ return 1
+end
+local delayedKey = baseKey .. 'delayed'
+maxCount = removeZSetJobs(delayedKey, true, baseKey, maxCount)
+if(maxCount <= 0) then
+ return 1
+end
+local repeatKey = baseKey .. 'repeat'
+local repeatJobsIds = getZSetItems(repeatKey, maxCount)
+for i, key in ipairs(repeatJobsIds) do
+ local jobKey = repeatKey .. ":" .. key
+ rcall("DEL", jobKey)
+end
+if(#repeatJobsIds > 0) then
+ for from, to in batches(#repeatJobsIds, 7000) do
+ rcall("ZREM", repeatKey, unpack(repeatJobsIds, from, to))
+ end
+end
+maxCount = maxCount - #repeatJobsIds
+if(maxCount <= 0) then
+ return 1
+end
+local completedKey = baseKey .. 'completed'
+maxCount = removeZSetJobs(completedKey, true, baseKey, maxCount)
+if(maxCount <= 0) then
+ return 1
+end
+local pausedKey = baseKey .. 'paused'
+maxCount = removeListJobs(pausedKey, true, baseKey, maxCount)
+if(maxCount <= 0) then
+ return 1
+end
+local prioritizedKey = baseKey .. 'prioritized'
+maxCount = removeZSetJobs(prioritizedKey, true, baseKey, maxCount)
+if(maxCount <= 0) then
+ return 1
+end
+local failedKey = baseKey .. 'failed'
+maxCount = removeZSetJobs(failedKey, true, baseKey, maxCount)
+if(maxCount <= 0) then
+ return 1
+end
+if(maxCount > 0) then
+ rcall("DEL",
+ baseKey .. 'events',
+ baseKey .. 'delay',
+ baseKey .. 'stalled-check',
+ baseKey .. 'stalled',
+ baseKey .. 'id',
+ baseKey .. 'pc',
+ baseKey .. 'marker',
+ baseKey .. 'meta',
+ baseKey .. 'metrics:completed',
+ baseKey .. 'metrics:completed:data',
+ baseKey .. 'metrics:failed',
+ baseKey .. 'metrics:failed:data')
+ return 0
+else
+ return 1
+end
+`;
+var obliterate = {
+ name: "obliterate",
+ content: content33,
+ keys: 2
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/paginate-1.js
+var content34 = `--[[
+ 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}
+`;
+var paginate = {
+ name: "paginate",
+ content: content34,
+ keys: 1
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/pause-7.js
+var content35 = `--[[
+ Pauses or resumes a queue globably.
+ Input:
+ KEYS[1] 'wait' or 'paused''
+ KEYS[2] 'paused' or 'wait'
+ KEYS[3] 'meta'
+ KEYS[4] 'prioritized'
+ KEYS[5] events stream key
+ KEYS[6] 'delayed'
+ KEYS|7] 'marker'
+ ARGV[1] 'paused' or 'resumed'
+ Event:
+ publish paused or resumed event.
+]]
+local rcall = redis.call
+-- Includes
+--[[
+ Add delay marker if needed.
+]]
+-- Includes
+--[[
+ Function to return the next delayed job timestamp.
+]]
+local function getNextDelayedTimestamp(delayedKey)
+ local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
+ if #result then
+ local nextTimestamp = tonumber(result[2])
+ if nextTimestamp ~= nil then
+ return nextTimestamp / 0x1000
+ end
+ end
+end
+local function addDelayMarkerIfNeeded(markerKey, delayedKey)
+ local nextTimestamp = getNextDelayedTimestamp(delayedKey)
+ if nextTimestamp ~= nil then
+ -- Replace the score of the marker with the newest known
+ -- next timestamp.
+ rcall("ZADD", markerKey, nextTimestamp, "1")
+ end
+end
+local markerKey = KEYS[7]
+local hasJobs = rcall("EXISTS", KEYS[1]) == 1
+--TODO: check this logic to be reused when changing a delay
+if hasJobs then rcall("RENAME", KEYS[1], KEYS[2]) end
+if ARGV[1] == "paused" then
+ rcall("HSET", KEYS[3], "paused", 1)
+ rcall("DEL", markerKey)
+else
+ rcall("HDEL", KEYS[3], "paused")
+ if hasJobs or rcall("ZCARD", KEYS[4]) > 0 then
+ -- Add marker if there are waiting or priority jobs
+ rcall("ZADD", markerKey, 0, "0")
+ else
+ addDelayMarkerIfNeeded(markerKey, KEYS[6])
+ end
+end
+rcall("XADD", KEYS[5], "*", "event", ARGV[1]);
+`;
+var pause = {
+ name: "pause",
+ content: content35,
+ keys: 7
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/promote-9.js
+var content36 = `--[[
+ Promotes a job that is currently "delayed" to the "waiting" state
+ Input:
+ KEYS[1] 'delayed'
+ KEYS[2] 'wait'
+ KEYS[3] 'paused'
+ KEYS[4] 'meta'
+ KEYS[5] 'prioritized'
+ KEYS[6] 'active'
+ KEYS[7] 'pc' priority counter
+ KEYS[8] 'event stream'
+ KEYS[9] 'marker'
+ ARGV[1] queue.toKey('')
+ ARGV[2] jobId
+ Output:
+ 0 - OK
+ -3 - Job not in delayed zset.
+ Events:
+ 'waiting'
+]]
+local rcall = redis.call
+local jobId = ARGV[2]
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to add job considering priority.
+]]
+-- Includes
+--[[
+ Function to get priority score.
+]]
+local function getPriorityScore(priority, priorityCounterKey)
+ local prioCounter = rcall("INCR", priorityCounterKey)
+ return priority * 0x100000000 + prioCounter % 0x100000000
+end
+local function addJobWithPriority(markerKey, prioritizedKey, priority, jobId, priorityCounterKey,
+ isPausedOrMaxed)
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+if rcall("ZREM", KEYS[1], jobId) == 1 then
+ local jobKey = ARGV[1] .. jobId
+ local priority = tonumber(rcall("HGET", jobKey, "priority")) or 0
+ local metaKey = KEYS[4]
+ local markerKey = KEYS[9]
+ -- Remove delayed "marker" from the wait list if there is any.
+ -- Since we are adding a job we do not need the marker anymore.
+ -- Markers in waitlist DEPRECATED in v5: Remove in v6.
+ local target, isPausedOrMaxed = getTargetQueueList(metaKey, KEYS[6], KEYS[2], KEYS[3])
+ local marker = rcall("LINDEX", target, 0)
+ if marker and string.sub(marker, 1, 2) == "0:" then rcall("LPOP", target) end
+ if priority == 0 then
+ -- LIFO or FIFO
+ addJobInTargetList(target, markerKey, "LPUSH", isPausedOrMaxed, jobId)
+ else
+ addJobWithPriority(markerKey, KEYS[5], priority, jobId, KEYS[7], isPausedOrMaxed)
+ end
+ rcall("XADD", KEYS[8], "*", "event", "waiting", "jobId", jobId, "prev",
+ "delayed");
+ rcall("HSET", jobKey, "delay", 0)
+ return 0
+else
+ return -3
+end
+`;
+var promote = {
+ name: "promote",
+ content: content36,
+ keys: 9
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/releaseLock-1.js
+var content37 = `--[[
+ Release lock
+ Input:
+ KEYS[1] 'lock',
+ ARGV[1] token
+ ARGV[2] lock duration in milliseconds
+ Output:
+ "OK" if lock extented succesfully.
+]]
+local rcall = redis.call
+if rcall("GET", KEYS[1]) == ARGV[1] then
+ return rcall("DEL", KEYS[1])
+else
+ return 0
+end
+`;
+var releaseLock = {
+ name: "releaseLock",
+ content: content37,
+ keys: 1
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/removeChildDependency-1.js
+var content38 = `--[[
+ Break parent-child dependency by removing
+ child reference from parent
+ Input:
+ KEYS[1] 'key' prefix,
+ ARGV[1] job key
+ ARGV[2] parent key
+ Output:
+ 0 - OK
+ 1 - There is not relationship.
+ -1 - Missing job key
+ -5 - Missing parent key
+]]
+local rcall = redis.call
+local jobKey = ARGV[1]
+local parentKey = ARGV[2]
+-- Includes
+--[[
+ Check if this job has a parent. If so we will just remove it from
+ the parent child list, but if it is the last child we should move the parent to "wait/paused"
+ which requires code from "moveToFinished"
+]]
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Functions to destructure job key.
+ Just a bit of warning, these functions may be a bit slow and affect performance significantly.
+]]
+local getJobIdFromKey = function (jobKey)
+ return string.match(jobKey, ".*:(.*)")
+end
+local getJobKeyPrefix = function (jobKey, jobId)
+ return string.sub(jobKey, 0, #jobKey - #jobId)
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+local function _moveParentToWait(parentPrefix, parentId, emitEvent)
+ local parentTarget, isPausedOrMaxed = getTargetQueueList(parentPrefix .. "meta", parentPrefix .. "active",
+ parentPrefix .. "wait", parentPrefix .. "paused")
+ addJobInTargetList(parentTarget, parentPrefix .. "marker", "RPUSH", isPausedOrMaxed, parentId)
+ if emitEvent then
+ local parentEventStream = parentPrefix .. "events"
+ rcall("XADD", parentEventStream, "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
+ end
+end
+local function removeParentDependencyKey(jobKey, hard, parentKey, baseKey, debounceId)
+ if parentKey then
+ local parentDependenciesKey = parentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(parentKey)
+ local parentPrefix = getJobKeyPrefix(parentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then -- remove parent in same queue
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(parentKey, hard, nil, baseKey, nil)
+ removeJobKeys(parentKey)
+ if debounceId then
+ rcall("DEL", parentPrefix .. "de:" .. debounceId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ else
+ local parentAttributes = rcall("HMGET", jobKey, "parentKey", "deid")
+ local missedParentKey = parentAttributes[1]
+ if( (type(missedParentKey) == "string") and missedParentKey ~= ""
+ and (rcall("EXISTS", missedParentKey) == 1)) then
+ local parentDependenciesKey = missedParentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(missedParentKey)
+ local parentPrefix = getJobKeyPrefix(missedParentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(missedParentKey, hard, nil, baseKey, nil)
+ removeJobKeys(missedParentKey)
+ if parentAttributes[2] then
+ rcall("DEL", parentPrefix .. "de:" .. parentAttributes[2])
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ end
+ end
+ return false
+end
+if rcall("EXISTS", jobKey) ~= 1 then return -1 end
+if rcall("EXISTS", parentKey) ~= 1 then return -5 end
+if removeParentDependencyKey(jobKey, false, parentKey, KEYS[1], nil) then
+ rcall("HDEL", jobKey, "parentKey", "parent")
+ return 0
+else
+ return 1
+end`;
+var removeChildDependency = {
+ name: "removeChildDependency",
+ content: content38,
+ keys: 1
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/removeDeduplicationKey-1.js
+var content39 = `--[[
+ Remove deduplication key if it matches the job id.
+ Input:
+ KEYS[1] deduplication key
+ ARGV[1] job id
+ Output:
+ 0 - false
+ 1 - true
+]]
+local rcall = redis.call
+local deduplicationKey = KEYS[1]
+local jobId = ARGV[1]
+local currentJobId = rcall('GET', deduplicationKey)
+if currentJobId and currentJobId == jobId then
+ return rcall("DEL", deduplicationKey)
+end
+return 0
+`;
+var removeDeduplicationKey = {
+ name: "removeDeduplicationKey",
+ content: content39,
+ keys: 1
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/removeJob-2.js
+var content40 = `--[[
+ Remove a job from all the statuses it may be in as well as all its data.
+ In order to be able to remove a job, it cannot be active.
+ Input:
+ KEYS[1] jobKey
+ KEYS[2] repeat key
+ ARGV[1] jobId
+ ARGV[2] remove children
+ ARGV[3] queue prefix
+ Events:
+ 'removed'
+]]
+local rcall = redis.call
+-- Includes
+--[[
+ Function to check if the job belongs to a job scheduler and
+ current delayed job matches with jobId
+]]
+local function isJobSchedulerJob(jobId, jobKey, jobSchedulersKey)
+ local repeatJobKey = rcall("HGET", jobKey, "rjk")
+ if repeatJobKey then
+ local prevMillis = rcall("ZSCORE", jobSchedulersKey, repeatJobKey)
+ if prevMillis then
+ local currentDelayedJobId = "repeat:" .. repeatJobKey .. ":" .. prevMillis
+ return jobId == currentDelayedJobId
+ end
+ end
+ return false
+end
+--[[
+ Function to recursively check if there are no locks
+ on the jobs to be removed.
+ returns:
+ boolean
+]]
+--[[
+ Functions to destructure job key.
+ Just a bit of warning, these functions may be a bit slow and affect performance significantly.
+]]
+local getJobIdFromKey = function (jobKey)
+ return string.match(jobKey, ".*:(.*)")
+end
+local getJobKeyPrefix = function (jobKey, jobId)
+ return string.sub(jobKey, 0, #jobKey - #jobId)
+end
+local function isLocked( prefix, jobId, removeChildren)
+ local jobKey = prefix .. jobId;
+ -- Check if this job is locked
+ local lockKey = jobKey .. ':lock'
+ local lock = rcall("GET", lockKey)
+ if not lock then
+ if removeChildren == "1" then
+ local dependencies = rcall("SMEMBERS", jobKey .. ":dependencies")
+ if (#dependencies > 0) then
+ for i, childJobKey in ipairs(dependencies) do
+ -- We need to get the jobId for this job.
+ local childJobId = getJobIdFromKey(childJobKey)
+ local childJobPrefix = getJobKeyPrefix(childJobKey, childJobId)
+ local result = isLocked( childJobPrefix, childJobId, removeChildren )
+ if result then
+ return true
+ end
+ end
+ end
+ end
+ return false
+ end
+ return true
+end
+--[[
+ Remove a job from all the statuses it may be in as well as all its data,
+ including its children. Active children can be ignored.
+ Events:
+ 'removed'
+]]
+local rcall = redis.call
+-- Includes
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+--[[
+ Function to remove deduplication key if needed
+ when a job is being removed.
+]]
+local function removeDeduplicationKeyIfNeededOnRemoval(prefixKey,
+ jobId, deduplicationId)
+ if deduplicationId then
+ local deduplicationKey = prefixKey .. "de:" .. deduplicationId
+ local currentJobId = rcall('GET', deduplicationKey)
+ if currentJobId and currentJobId == jobId then
+ rcall("DEL", deduplicationKey)
+ -- Also clean up any pending dedup-next data for this dedup ID
+ rcall("DEL", prefixKey .. "dn:" .. deduplicationId)
+ return 1
+ end
+ end
+end
+--[[
+ Function to remove from any state.
+ returns:
+ prev state
+]]
+local function removeJobFromAnyState( prefix, jobId)
+ -- We start with the ZSCORE checks, since they have O(1) complexity
+ if rcall("ZSCORE", prefix .. "completed", jobId) then
+ rcall("ZREM", prefix .. "completed", jobId)
+ return "completed"
+ elseif rcall("ZSCORE", prefix .. "waiting-children", jobId) then
+ rcall("ZREM", prefix .. "waiting-children", jobId)
+ return "waiting-children"
+ elseif rcall("ZSCORE", prefix .. "delayed", jobId) then
+ rcall("ZREM", prefix .. "delayed", jobId)
+ return "delayed"
+ elseif rcall("ZSCORE", prefix .. "failed", jobId) then
+ rcall("ZREM", prefix .. "failed", jobId)
+ return "failed"
+ elseif rcall("ZSCORE", prefix .. "prioritized", jobId) then
+ rcall("ZREM", prefix .. "prioritized", jobId)
+ return "prioritized"
+ -- We remove only 1 element from the list, since we assume they are not added multiple times
+ elseif rcall("LREM", prefix .. "wait", 1, jobId) == 1 then
+ return "wait"
+ elseif rcall("LREM", prefix .. "paused", 1, jobId) == 1 then
+ return "paused"
+ elseif rcall("LREM", prefix .. "active", 1, jobId) == 1 then
+ return "active"
+ end
+ return "unknown"
+end
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+--[[
+ Check if this job has a parent. If so we will just remove it from
+ the parent child list, but if it is the last child we should move the parent to "wait/paused"
+ which requires code from "moveToFinished"
+]]
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+local function _moveParentToWait(parentPrefix, parentId, emitEvent)
+ local parentTarget, isPausedOrMaxed = getTargetQueueList(parentPrefix .. "meta", parentPrefix .. "active",
+ parentPrefix .. "wait", parentPrefix .. "paused")
+ addJobInTargetList(parentTarget, parentPrefix .. "marker", "RPUSH", isPausedOrMaxed, parentId)
+ if emitEvent then
+ local parentEventStream = parentPrefix .. "events"
+ rcall("XADD", parentEventStream, "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
+ end
+end
+local function removeParentDependencyKey(jobKey, hard, parentKey, baseKey, debounceId)
+ if parentKey then
+ local parentDependenciesKey = parentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(parentKey)
+ local parentPrefix = getJobKeyPrefix(parentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then -- remove parent in same queue
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(parentKey, hard, nil, baseKey, nil)
+ removeJobKeys(parentKey)
+ if debounceId then
+ rcall("DEL", parentPrefix .. "de:" .. debounceId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ else
+ local parentAttributes = rcall("HMGET", jobKey, "parentKey", "deid")
+ local missedParentKey = parentAttributes[1]
+ if( (type(missedParentKey) == "string") and missedParentKey ~= ""
+ and (rcall("EXISTS", missedParentKey) == 1)) then
+ local parentDependenciesKey = missedParentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(missedParentKey)
+ local parentPrefix = getJobKeyPrefix(missedParentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(missedParentKey, hard, nil, baseKey, nil)
+ removeJobKeys(missedParentKey)
+ if parentAttributes[2] then
+ rcall("DEL", parentPrefix .. "de:" .. parentAttributes[2])
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ end
+ end
+ return false
+end
+local removeJobChildren
+local removeJobWithChildren
+removeJobChildren = function(prefix, jobKey, options)
+ -- Check if this job has children
+ -- If so, we are going to try to remove the children recursively in a depth-first way
+ -- because if some job is locked, we must exit with an error.
+ if not options.ignoreProcessed then
+ local processed = rcall("HGETALL", jobKey .. ":processed")
+ if #processed > 0 then
+ for i = 1, #processed, 2 do
+ local childJobId = getJobIdFromKey(processed[i])
+ local childJobPrefix = getJobKeyPrefix(processed[i], childJobId)
+ removeJobWithChildren(childJobPrefix, childJobId, jobKey, options)
+ end
+ end
+ local failed = rcall("HGETALL", jobKey .. ":failed")
+ if #failed > 0 then
+ for i = 1, #failed, 2 do
+ local childJobId = getJobIdFromKey(failed[i])
+ local childJobPrefix = getJobKeyPrefix(failed[i], childJobId)
+ removeJobWithChildren(childJobPrefix, childJobId, jobKey, options)
+ end
+ end
+ local unsuccessful = rcall("ZRANGE", jobKey .. ":unsuccessful", 0, -1)
+ if #unsuccessful > 0 then
+ for i = 1, #unsuccessful, 1 do
+ local childJobId = getJobIdFromKey(unsuccessful[i])
+ local childJobPrefix = getJobKeyPrefix(unsuccessful[i], childJobId)
+ removeJobWithChildren(childJobPrefix, childJobId, jobKey, options)
+ end
+ end
+ end
+ local dependencies = rcall("SMEMBERS", jobKey .. ":dependencies")
+ if #dependencies > 0 then
+ for i, childJobKey in ipairs(dependencies) do
+ local childJobId = getJobIdFromKey(childJobKey)
+ local childJobPrefix = getJobKeyPrefix(childJobKey, childJobId)
+ removeJobWithChildren(childJobPrefix, childJobId, jobKey, options)
+ end
+ end
+end
+removeJobWithChildren = function(prefix, jobId, parentKey, options)
+ local jobKey = prefix .. jobId
+ if options.ignoreLocked then
+ if isLocked(prefix, jobId) then
+ return
+ end
+ end
+ -- Check if job is in the failed zset
+ local failedSet = prefix .. "failed"
+ if not (options.ignoreProcessed and rcall("ZSCORE", failedSet, jobId)) then
+ removeParentDependencyKey(jobKey, false, parentKey, nil)
+ if options.removeChildren then
+ removeJobChildren(prefix, jobKey, options)
+ end
+ local prev = removeJobFromAnyState(prefix, jobId)
+ local deduplicationId = rcall("HGET", jobKey, "deid")
+ removeDeduplicationKeyIfNeededOnRemoval(prefix, jobId, deduplicationId)
+ if removeJobKeys(jobKey) > 0 then
+ local metaKey = prefix .. "meta"
+ local maxEvents = getOrSetMaxEvents(metaKey)
+ rcall("XADD", prefix .. "events", "MAXLEN", "~", maxEvents, "*", "event", "removed",
+ "jobId", jobId, "prev", prev)
+ end
+ end
+end
+local jobId = ARGV[1]
+local shouldRemoveChildren = ARGV[2]
+local prefix = ARGV[3]
+local jobKey = KEYS[1]
+local repeatKey = KEYS[2]
+if isJobSchedulerJob(jobId, jobKey, repeatKey) then
+ return -8
+end
+if not isLocked(prefix, jobId, shouldRemoveChildren) then
+ local options = {
+ removeChildren = shouldRemoveChildren == "1",
+ ignoreProcessed = false,
+ ignoreLocked = false
}
- },
- files: [
- "dist-*/**"
- ],
- author: {
- name: "AWS SDK for JavaScript Team",
- url: "https://aws.amazon.com/javascript/"
- },
- license: "Apache-2.0",
- browser: {
- "./dist-es/runtimeConfig": "./dist-es/runtimeConfig.browser"
- },
- "react-native": {
- "./dist-es/runtimeConfig": "./dist-es/runtimeConfig.native"
- },
- homepage: "https://github.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3",
- repository: {
- type: "git",
- url: "https://github.com/aws/aws-sdk-js-v3.git",
- directory: "clients/client-s3"
- }
+ removeJobWithChildren(prefix, jobId, nil, options)
+ return 1
+end
+return 0
+`;
+var removeJob = {
+ name: "removeJob",
+ content: content40,
+ keys: 2
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/removeJobScheduler-3.js
+var content41 = `--[[
+ Removes a job scheduler and its next scheduled job.
+ Input:
+ KEYS[1] job schedulers key
+ KEYS[2] delayed jobs key
+ KEYS[3] events key
+ ARGV[1] job scheduler id
+ ARGV[2] prefix key
+ Output:
+ 0 - OK
+ 1 - Missing repeat job
+ Events:
+ 'removed'
+]]
+local rcall = redis.call
+-- Includes
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+local jobSchedulerId = ARGV[1]
+local prefix = ARGV[2]
+local millis = rcall("ZSCORE", KEYS[1], jobSchedulerId)
+if millis then
+ -- Delete next programmed job.
+ local delayedJobId = "repeat:" .. jobSchedulerId .. ":" .. millis
+ if(rcall("ZREM", KEYS[2], delayedJobId) == 1) then
+ removeJobKeys(prefix .. delayedJobId)
+ rcall("XADD", KEYS[3], "*", "event", "removed", "jobId", delayedJobId, "prev", "delayed")
+ end
+end
+if(rcall("ZREM", KEYS[1], jobSchedulerId) == 1) then
+ rcall("DEL", KEYS[1] .. ":" .. jobSchedulerId)
+ return 0
+end
+return 1
+`;
+var removeJobScheduler = {
+ name: "removeJobScheduler",
+ content: content41,
+ keys: 3
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/removeOrphanedJobs-1.js
+var content42 = `--[[
+ Removes orphaned job keys that exist in Redis but are not referenced
+ in any queue state set. Checks each candidate atomically.
+ Input:
+ KEYS[1] base prefix key including trailing colon (e.g. bull:queueName:)
+ ARGV[1] number of state key suffixes
+ ARGV[2 .. 1+N] state key suffixes (e.g. active, wait, completed, ...)
+ ARGV[2+N] number of job sub-key suffixes
+ ARGV[3+N .. 2+N+M] job sub-key suffixes (e.g. logs, dependencies, ...)
+ ARGV[3+N+M .. end] candidate job IDs to check
+ Output:
+ number of removed jobs
+]]
+local rcall = redis.call
+local basePrefix = KEYS[1]
+-- Parse state key suffixes and cache their full key names + types.
+local stateKeyCount = tonumber(ARGV[1])
+local stateKeys = {}
+local stateKeyTypes = {}
+for i = 1, stateKeyCount do
+ local fullKey = basePrefix .. ARGV[1 + i]
+ stateKeys[i] = fullKey
+ stateKeyTypes[i] = rcall('TYPE', fullKey)['ok']
+end
+-- Parse job sub-key suffixes.
+local subKeyCountIdx = 2 + stateKeyCount
+local subKeyCount = tonumber(ARGV[subKeyCountIdx])
+local subKeySuffixes = {}
+for i = 1, subKeyCount do
+ subKeySuffixes[i] = ARGV[subKeyCountIdx + i]
+end
+-- Process candidate job IDs.
+local candidateStart = subKeyCountIdx + subKeyCount + 1
+local removedCount = 0
+for c = candidateStart, #ARGV do
+ local jobId = ARGV[c]
+ local found = false
+ for i = 1, stateKeyCount do
+ local kt = stateKeyTypes[i]
+ if kt == 'list' then
+ if rcall('LPOS', stateKeys[i], jobId) then
+ found = true
+ break
+ end
+ elseif kt == 'zset' then
+ if rcall('ZSCORE', stateKeys[i], jobId) then
+ found = true
+ break
+ end
+ elseif kt == 'set' then
+ if rcall('SISMEMBER', stateKeys[i], jobId) == 1 then
+ found = true
+ break
+ end
+ end
+ end
+ if not found then
+ local jobKey = basePrefix .. jobId
+ local keysToDelete = { jobKey }
+ for _, suffix in ipairs(subKeySuffixes) do
+ keysToDelete[#keysToDelete + 1] = jobKey .. ':' .. suffix
+ end
+ rcall('DEL', unpack(keysToDelete))
+ removedCount = removedCount + 1
+ end
+end
+return removedCount
+`;
+var removeOrphanedJobs = {
+ name: "removeOrphanedJobs",
+ content: content42,
+ keys: 1
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/removeRepeatable-3.js
+var content43 = `--[[
+ Removes a repeatable job
+ Input:
+ KEYS[1] repeat jobs key
+ KEYS[2] delayed jobs key
+ KEYS[3] events key
+ ARGV[1] old repeat job id
+ ARGV[2] options concat
+ ARGV[3] repeat job key
+ ARGV[4] prefix key
+ Output:
+ 0 - OK
+ 1 - Missing repeat job
+ Events:
+ 'removed'
+]]
+local rcall = redis.call
+local millis = rcall("ZSCORE", KEYS[1], ARGV[2])
+-- Includes
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+-- legacy removal TODO: remove in next breaking change
+if millis then
+ -- Delete next programmed job.
+ local repeatJobId = ARGV[1] .. millis
+ if(rcall("ZREM", KEYS[2], repeatJobId) == 1) then
+ removeJobKeys(ARGV[4] .. repeatJobId)
+ rcall("XADD", KEYS[3], "*", "event", "removed", "jobId", repeatJobId, "prev", "delayed");
+ end
+end
+if(rcall("ZREM", KEYS[1], ARGV[2]) == 1) then
+ return 0
+end
+-- new removal
+millis = rcall("ZSCORE", KEYS[1], ARGV[3])
+if millis then
+ -- Delete next programmed job.
+ local repeatJobId = "repeat:" .. ARGV[3] .. ":" .. millis
+ if(rcall("ZREM", KEYS[2], repeatJobId) == 1) then
+ removeJobKeys(ARGV[4] .. repeatJobId)
+ rcall("XADD", KEYS[3], "*", "event", "removed", "jobId", repeatJobId, "prev", "delayed")
+ end
+end
+if(rcall("ZREM", KEYS[1], ARGV[3]) == 1) then
+ rcall("DEL", KEYS[1] .. ":" .. ARGV[3])
+ return 0
+end
+return 1
+`;
+var removeRepeatable = {
+ name: "removeRepeatable",
+ content: content43,
+ keys: 3
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/removeUnprocessedChildren-2.js
+var content44 = `--[[
+ Remove a job from all the statuses it may be in as well as all its data.
+ In order to be able to remove a job, it cannot be active.
+ Input:
+ KEYS[1] jobKey
+ KEYS[2] meta key
+ ARGV[1] prefix
+ ARGV[2] jobId
+ Events:
+ 'removed' for every children removed
+]]
+-- Includes
+--[[
+ Remove a job from all the statuses it may be in as well as all its data,
+ including its children. Active children can be ignored.
+ Events:
+ 'removed'
+]]
+local rcall = redis.call
+-- Includes
+--[[
+ Functions to destructure job key.
+ Just a bit of warning, these functions may be a bit slow and affect performance significantly.
+]]
+local getJobIdFromKey = function (jobKey)
+ return string.match(jobKey, ".*:(.*)")
+end
+local getJobKeyPrefix = function (jobKey, jobId)
+ return string.sub(jobKey, 0, #jobKey - #jobId)
+end
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+--[[
+ Function to check if the job belongs to a job scheduler and
+ current delayed job matches with jobId
+]]
+local function isJobSchedulerJob(jobId, jobKey, jobSchedulersKey)
+ local repeatJobKey = rcall("HGET", jobKey, "rjk")
+ if repeatJobKey then
+ local prevMillis = rcall("ZSCORE", jobSchedulersKey, repeatJobKey)
+ if prevMillis then
+ local currentDelayedJobId = "repeat:" .. repeatJobKey .. ":" .. prevMillis
+ return jobId == currentDelayedJobId
+ end
+ end
+ return false
+end
+--[[
+ Function to remove deduplication key if needed
+ when a job is being removed.
+]]
+local function removeDeduplicationKeyIfNeededOnRemoval(prefixKey,
+ jobId, deduplicationId)
+ if deduplicationId then
+ local deduplicationKey = prefixKey .. "de:" .. deduplicationId
+ local currentJobId = rcall('GET', deduplicationKey)
+ if currentJobId and currentJobId == jobId then
+ rcall("DEL", deduplicationKey)
+ -- Also clean up any pending dedup-next data for this dedup ID
+ rcall("DEL", prefixKey .. "dn:" .. deduplicationId)
+ return 1
+ end
+ end
+end
+--[[
+ Function to remove from any state.
+ returns:
+ prev state
+]]
+local function removeJobFromAnyState( prefix, jobId)
+ -- We start with the ZSCORE checks, since they have O(1) complexity
+ if rcall("ZSCORE", prefix .. "completed", jobId) then
+ rcall("ZREM", prefix .. "completed", jobId)
+ return "completed"
+ elseif rcall("ZSCORE", prefix .. "waiting-children", jobId) then
+ rcall("ZREM", prefix .. "waiting-children", jobId)
+ return "waiting-children"
+ elseif rcall("ZSCORE", prefix .. "delayed", jobId) then
+ rcall("ZREM", prefix .. "delayed", jobId)
+ return "delayed"
+ elseif rcall("ZSCORE", prefix .. "failed", jobId) then
+ rcall("ZREM", prefix .. "failed", jobId)
+ return "failed"
+ elseif rcall("ZSCORE", prefix .. "prioritized", jobId) then
+ rcall("ZREM", prefix .. "prioritized", jobId)
+ return "prioritized"
+ -- We remove only 1 element from the list, since we assume they are not added multiple times
+ elseif rcall("LREM", prefix .. "wait", 1, jobId) == 1 then
+ return "wait"
+ elseif rcall("LREM", prefix .. "paused", 1, jobId) == 1 then
+ return "paused"
+ elseif rcall("LREM", prefix .. "active", 1, jobId) == 1 then
+ return "active"
+ end
+ return "unknown"
+end
+--[[
+ Function to remove job keys.
+]]
+local function removeJobKeys(jobKey)
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
+end
+--[[
+ Check if this job has a parent. If so we will just remove it from
+ the parent child list, but if it is the last child we should move the parent to "wait/paused"
+ which requires code from "moveToFinished"
+]]
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+local function _moveParentToWait(parentPrefix, parentId, emitEvent)
+ local parentTarget, isPausedOrMaxed = getTargetQueueList(parentPrefix .. "meta", parentPrefix .. "active",
+ parentPrefix .. "wait", parentPrefix .. "paused")
+ addJobInTargetList(parentTarget, parentPrefix .. "marker", "RPUSH", isPausedOrMaxed, parentId)
+ if emitEvent then
+ local parentEventStream = parentPrefix .. "events"
+ rcall("XADD", parentEventStream, "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
+ end
+end
+local function removeParentDependencyKey(jobKey, hard, parentKey, baseKey, debounceId)
+ if parentKey then
+ local parentDependenciesKey = parentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(parentKey)
+ local parentPrefix = getJobKeyPrefix(parentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then -- remove parent in same queue
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(parentKey, hard, nil, baseKey, nil)
+ removeJobKeys(parentKey)
+ if debounceId then
+ rcall("DEL", parentPrefix .. "de:" .. debounceId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ else
+ local parentAttributes = rcall("HMGET", jobKey, "parentKey", "deid")
+ local missedParentKey = parentAttributes[1]
+ if( (type(missedParentKey) == "string") and missedParentKey ~= ""
+ and (rcall("EXISTS", missedParentKey) == 1)) then
+ local parentDependenciesKey = missedParentKey .. ":dependencies"
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
+ if result > 0 then
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
+ if pendingDependencies == 0 then
+ local parentId = getJobIdFromKey(missedParentKey)
+ local parentPrefix = getJobKeyPrefix(missedParentKey, parentId)
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
+ if numRemovedElements == 1 then
+ if hard then
+ if parentPrefix == baseKey then
+ removeParentDependencyKey(missedParentKey, hard, nil, baseKey, nil)
+ removeJobKeys(missedParentKey)
+ if parentAttributes[2] then
+ rcall("DEL", parentPrefix .. "de:" .. parentAttributes[2])
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId)
+ end
+ else
+ _moveParentToWait(parentPrefix, parentId, true)
+ end
+ end
+ end
+ return true
+ end
+ end
+ end
+ return false
+end
+--[[
+ Function to recursively check if there are no locks
+ on the jobs to be removed.
+ returns:
+ boolean
+]]
+local function isLocked( prefix, jobId, removeChildren)
+ local jobKey = prefix .. jobId;
+ -- Check if this job is locked
+ local lockKey = jobKey .. ':lock'
+ local lock = rcall("GET", lockKey)
+ if not lock then
+ if removeChildren == "1" then
+ local dependencies = rcall("SMEMBERS", jobKey .. ":dependencies")
+ if (#dependencies > 0) then
+ for i, childJobKey in ipairs(dependencies) do
+ -- We need to get the jobId for this job.
+ local childJobId = getJobIdFromKey(childJobKey)
+ local childJobPrefix = getJobKeyPrefix(childJobKey, childJobId)
+ local result = isLocked( childJobPrefix, childJobId, removeChildren )
+ if result then
+ return true
+ end
+ end
+ end
+ end
+ return false
+ end
+ return true
+end
+local removeJobChildren
+local removeJobWithChildren
+removeJobChildren = function(prefix, jobKey, options)
+ -- Check if this job has children
+ -- If so, we are going to try to remove the children recursively in a depth-first way
+ -- because if some job is locked, we must exit with an error.
+ if not options.ignoreProcessed then
+ local processed = rcall("HGETALL", jobKey .. ":processed")
+ if #processed > 0 then
+ for i = 1, #processed, 2 do
+ local childJobId = getJobIdFromKey(processed[i])
+ local childJobPrefix = getJobKeyPrefix(processed[i], childJobId)
+ removeJobWithChildren(childJobPrefix, childJobId, jobKey, options)
+ end
+ end
+ local failed = rcall("HGETALL", jobKey .. ":failed")
+ if #failed > 0 then
+ for i = 1, #failed, 2 do
+ local childJobId = getJobIdFromKey(failed[i])
+ local childJobPrefix = getJobKeyPrefix(failed[i], childJobId)
+ removeJobWithChildren(childJobPrefix, childJobId, jobKey, options)
+ end
+ end
+ local unsuccessful = rcall("ZRANGE", jobKey .. ":unsuccessful", 0, -1)
+ if #unsuccessful > 0 then
+ for i = 1, #unsuccessful, 1 do
+ local childJobId = getJobIdFromKey(unsuccessful[i])
+ local childJobPrefix = getJobKeyPrefix(unsuccessful[i], childJobId)
+ removeJobWithChildren(childJobPrefix, childJobId, jobKey, options)
+ end
+ end
+ end
+ local dependencies = rcall("SMEMBERS", jobKey .. ":dependencies")
+ if #dependencies > 0 then
+ for i, childJobKey in ipairs(dependencies) do
+ local childJobId = getJobIdFromKey(childJobKey)
+ local childJobPrefix = getJobKeyPrefix(childJobKey, childJobId)
+ removeJobWithChildren(childJobPrefix, childJobId, jobKey, options)
+ end
+ end
+end
+removeJobWithChildren = function(prefix, jobId, parentKey, options)
+ local jobKey = prefix .. jobId
+ if options.ignoreLocked then
+ if isLocked(prefix, jobId) then
+ return
+ end
+ end
+ -- Check if job is in the failed zset
+ local failedSet = prefix .. "failed"
+ if not (options.ignoreProcessed and rcall("ZSCORE", failedSet, jobId)) then
+ removeParentDependencyKey(jobKey, false, parentKey, nil)
+ if options.removeChildren then
+ removeJobChildren(prefix, jobKey, options)
+ end
+ local prev = removeJobFromAnyState(prefix, jobId)
+ local deduplicationId = rcall("HGET", jobKey, "deid")
+ removeDeduplicationKeyIfNeededOnRemoval(prefix, jobId, deduplicationId)
+ if removeJobKeys(jobKey) > 0 then
+ local metaKey = prefix .. "meta"
+ local maxEvents = getOrSetMaxEvents(metaKey)
+ rcall("XADD", prefix .. "events", "MAXLEN", "~", maxEvents, "*", "event", "removed",
+ "jobId", jobId, "prev", prev)
+ end
+ end
+end
+local prefix = ARGV[1]
+local jobId = ARGV[2]
+local jobKey = KEYS[1]
+local metaKey = KEYS[2]
+local options = {
+ removeChildren = "1",
+ ignoreProcessed = true,
+ ignoreLocked = true
+}
+removeJobChildren(prefix, jobKey, options)
+`;
+var removeUnprocessedChildren = {
+ name: "removeUnprocessedChildren",
+ content: content44,
+ keys: 2
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/reprocessJob-8.js
+var content45 = `--[[
+ Attempts to reprocess a job
+ Input:
+ KEYS[1] job key
+ KEYS[2] events stream
+ KEYS[3] job state
+ KEYS[4] wait key
+ KEYS[5] meta
+ KEYS[6] paused key
+ KEYS[7] active key
+ KEYS[8] marker key
+ ARGV[1] job.id
+ ARGV[2] (job.opts.lifo ? 'R' : 'L') + 'PUSH'
+ ARGV[3] propVal - failedReason/returnvalue
+ ARGV[4] prev state - failed/completed
+ ARGV[5] reset attemptsMade - "1" or "0"
+ ARGV[6] reset attemptsStarted - "1" or "0"
+ Output:
+ 1 means the operation was a success
+ -1 means the job does not exist
+ -3 means the job was not found in the expected set.
+]]
+local rcall = redis.call;
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+local jobKey = KEYS[1]
+if rcall("EXISTS", jobKey) == 1 then
+ local jobId = ARGV[1]
+ if (rcall("ZREM", KEYS[3], jobId) == 1) then
+ local attributesToRemove = {}
+ if ARGV[5] == "1" then
+ table.insert(attributesToRemove, "atm")
+ end
+ if ARGV[6] == "1" then
+ table.insert(attributesToRemove, "ats")
+ end
+ rcall("HDEL", jobKey, "finishedOn", "processedOn", ARGV[3], unpack(attributesToRemove))
+ local target, isPausedOrMaxed = getTargetQueueList(KEYS[5], KEYS[7], KEYS[4], KEYS[6])
+ addJobInTargetList(target, KEYS[8], ARGV[2], isPausedOrMaxed, jobId)
+ local parentKey = rcall("HGET", jobKey, "parentKey")
+ if parentKey and rcall("EXISTS", parentKey) == 1 then
+ if ARGV[4] == "failed" then
+ if rcall("ZREM", parentKey .. ":unsuccessful", jobKey) == 1 or
+ rcall("ZREM", parentKey .. ":failed", jobKey) == 1 then
+ rcall("SADD", parentKey .. ":dependencies", jobKey)
+ end
+ else
+ if rcall("HDEL", parentKey .. ":processed", jobKey) == 1 then
+ rcall("SADD", parentKey .. ":dependencies", jobKey)
+ end
+ end
+ end
+ local maxEvents = getOrSetMaxEvents(KEYS[5])
+ -- Emit waiting event
+ rcall("XADD", KEYS[2], "MAXLEN", "~", maxEvents, "*", "event", "waiting",
+ "jobId", jobId, "prev", ARGV[4]);
+ return 1
+ else
+ return -3
+ end
+else
+ return -1
+end
+`;
+var reprocessJob = {
+ name: "reprocessJob",
+ content: content45,
+ keys: 8
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/retryJob-11.js
+var content46 = `--[[
+ Retries a failed job by moving it back to the wait queue.
+ Input:
+ KEYS[1] 'active',
+ KEYS[2] 'wait'
+ KEYS[3] 'paused'
+ KEYS[4] job key
+ KEYS[5] 'meta'
+ KEYS[6] events stream
+ KEYS[7] delayed key
+ KEYS[8] prioritized key
+ KEYS[9] 'pc' priority counter
+ KEYS[10] 'marker'
+ KEYS[11] 'stalled'
+ ARGV[1] key prefix
+ ARGV[2] timestamp
+ ARGV[3] pushCmd
+ ARGV[4] jobId
+ ARGV[5] token
+ ARGV[6] optional job fields to update
+ Events:
+ 'waiting'
+ Output:
+ 0 - OK
+ -1 - Missing key
+ -2 - Missing lock
+ -3 - Job not in active set
+]]
+local rcall = redis.call
+-- Includes
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to add job considering priority.
+]]
+-- Includes
+--[[
+ Function to get priority score.
+]]
+local function getPriorityScore(priority, priorityCounterKey)
+ local prioCounter = rcall("INCR", priorityCounterKey)
+ return priority * 0x100000000 + prioCounter % 0x100000000
+end
+local function addJobWithPriority(markerKey, prioritizedKey, priority, jobId, priorityCounterKey,
+ isPausedOrMaxed)
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+--[[
+ Function to check if queue is paused or maxed
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function isQueuePausedOrMaxed(queueMetaKey, activeKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency")
+ if queueAttributes[1] then
+ return true
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ return activeCount >= tonumber(queueAttributes[2])
+ end
+ end
+ return false
+end
+--[[
+ Updates the delay set, by moving delayed jobs that should
+ be processed now to "wait".
+ Events:
+ 'waiting'
+]]
+-- Includes
+-- Try to get as much as 1000 jobs at once
+local function promoteDelayedJobs(delayedKey, markerKey, targetKey, prioritizedKey,
+ eventStreamKey, prefix, timestamp, priorityCounterKey, isPaused)
+ local jobs = rcall("ZRANGEBYSCORE", delayedKey, 0, (timestamp + 1) * 0x1000 - 1, "LIMIT", 0, 1000)
+ if (#jobs > 0) then
+ rcall("ZREM", delayedKey, unpack(jobs))
+ for _, jobId in ipairs(jobs) do
+ local jobKey = prefix .. jobId
+ local priority =
+ tonumber(rcall("HGET", jobKey, "priority")) or 0
+ if priority == 0 then
+ -- LIFO or FIFO
+ rcall("LPUSH", targetKey, jobId)
+ else
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ end
+ -- Emit waiting event
+ rcall("XADD", eventStreamKey, "*", "event", "waiting", "jobId",
+ jobId, "prev", "delayed")
+ rcall("HSET", jobKey, "delay", 0)
+ end
+ addBaseMarkerIfNeeded(markerKey, isPaused)
+ end
+end
+local function removeLock(jobKey, stalledKey, token, jobId)
+ if token ~= "0" then
+ local lockKey = jobKey .. ':lock'
+ local lockToken = rcall("GET", lockKey)
+ if lockToken == token then
+ rcall("DEL", lockKey)
+ rcall("SREM", stalledKey, jobId)
+ else
+ if lockToken then
+ -- Lock exists but token does not match
+ return -6
+ else
+ -- Lock is missing completely
+ return -2
+ end
+ end
+ end
+ return 0
+end
+--[[
+ Function to update a bunch of fields in a job.
+]]
+local function updateJobFields(jobKey, msgpackedFields)
+ if msgpackedFields and #msgpackedFields > 0 then
+ local fieldsToUpdate = cmsgpack.unpack(msgpackedFields)
+ if fieldsToUpdate then
+ rcall("HMSET", jobKey, unpack(fieldsToUpdate))
+ end
+ end
+end
+local target, isPausedOrMaxed = getTargetQueueList(KEYS[5], KEYS[1], KEYS[2], KEYS[3])
+local markerKey = KEYS[10]
+-- Check if there are delayed jobs that we can move to wait.
+-- test example: when there are delayed jobs between retries
+promoteDelayedJobs(KEYS[7], markerKey, target, KEYS[8], KEYS[6], ARGV[1], ARGV[2], KEYS[9], isPausedOrMaxed)
+local jobKey = KEYS[4]
+if rcall("EXISTS", jobKey) == 1 then
+ local errorCode = removeLock(jobKey, KEYS[11], ARGV[5], ARGV[4])
+ if errorCode < 0 then
+ return errorCode
+ end
+ updateJobFields(jobKey, ARGV[6])
+ local numRemovedElements = rcall("LREM", KEYS[1], -1, ARGV[4])
+ if (numRemovedElements < 1) then return -3 end
+ local priority = tonumber(rcall("HGET", jobKey, "priority")) or 0
+ --need to re-evaluate after removing job from active
+ isPausedOrMaxed = isQueuePausedOrMaxed(KEYS[5], KEYS[1])
+ -- Standard or priority add
+ if priority == 0 then
+ addJobInTargetList(target, markerKey, ARGV[3], isPausedOrMaxed, ARGV[4])
+ else
+ addJobWithPriority(markerKey, KEYS[8], priority, ARGV[4], KEYS[9], isPausedOrMaxed)
+ end
+ rcall("HINCRBY", jobKey, "atm", 1)
+ local maxEvents = getOrSetMaxEvents(KEYS[5])
+ -- Emit waiting event
+ rcall("XADD", KEYS[6], "MAXLEN", "~", maxEvents, "*", "event", "waiting",
+ "jobId", ARGV[4], "prev", "active")
+ return 0
+else
+ return -1
+end
+`;
+var retryJob = {
+ name: "retryJob",
+ content: content46,
+ keys: 11
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/saveStacktrace-1.js
+var content47 = `--[[
+ Save stacktrace and failedReason.
+ Input:
+ KEYS[1] job key
+ ARGV[1] stacktrace
+ ARGV[2] failedReason
+ Output:
+ 0 - OK
+ -1 - Missing key
+]]
+local rcall = redis.call
+if rcall("EXISTS", KEYS[1]) == 1 then
+ rcall("HMSET", KEYS[1], "stacktrace", ARGV[1], "failedReason", ARGV[2])
+ return 0
+else
+ return -1
+end
+`;
+var saveStacktrace = {
+ name: "saveStacktrace",
+ content: content47,
+ keys: 1
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/updateData-1.js
+var content48 = `--[[
+ Update job data
+ Input:
+ KEYS[1] Job id key
+ ARGV[1] data
+ Output:
+ 0 - OK
+ -1 - Missing job.
+]]
+local rcall = redis.call
+if rcall("EXISTS",KEYS[1]) == 1 then -- // Make sure job exists
+ rcall("HSET", KEYS[1], "data", ARGV[1])
+ return 0
+else
+ return -1
+end
+`;
+var updateData = {
+ name: "updateData",
+ content: content48,
+ keys: 1
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/updateJobScheduler-12.js
+var content49 = `--[[
+ Updates a job scheduler and adds next delayed job
+ Input:
+ KEYS[1] 'repeat' key
+ KEYS[2] 'delayed'
+ KEYS[3] 'wait' key
+ KEYS[4] 'paused' key
+ KEYS[5] 'meta'
+ KEYS[6] 'prioritized' key
+ KEYS[7] 'marker',
+ KEYS[8] 'id'
+ KEYS[9] events stream key
+ KEYS[10] 'pc' priority counter
+ KEYS[11] producer key
+ KEYS[12] 'active' key
+ ARGV[1] next milliseconds
+ ARGV[2] jobs scheduler id
+ ARGV[3] Json stringified delayed data
+ ARGV[4] msgpacked delayed opts
+ ARGV[5] timestamp
+ ARGV[6] prefix key
+ ARGV[7] producer id
+ Output:
+ next delayed job id - OK
+]] local rcall = redis.call
+local repeatKey = KEYS[1]
+local delayedKey = KEYS[2]
+local waitKey = KEYS[3]
+local pausedKey = KEYS[4]
+local metaKey = KEYS[5]
+local prioritizedKey = KEYS[6]
+local nextMillis = tonumber(ARGV[1])
+local jobSchedulerId = ARGV[2]
+local timestamp = tonumber(ARGV[5])
+local prefixKey = ARGV[6]
+local producerId = ARGV[7]
+local jobOpts = cmsgpack.unpack(ARGV[4])
+-- Includes
+--[[
+ Add delay marker if needed.
+]]
+-- Includes
+--[[
+ Shared helper to store a job and enqueue it into the appropriate list/set.
+ Handles delayed, prioritized, and standard (LIFO/FIFO) jobs.
+ Emits the appropriate event after enqueuing ("delayed" or "waiting").
+ Returns delay, priority from storeJob.
+]]
+-- Includes
+--[[
+ Adds a delayed job to the queue by doing the following:
+ - Creates a new job key with the job data.
+ - adds to delayed zset.
+ - Emits a global event 'delayed' if the job is delayed.
+]]
+-- Includes
+--[[
+ Add delay marker if needed.
+]]
+-- Includes
+--[[
+ Function to return the next delayed job timestamp.
+]]
+local function getNextDelayedTimestamp(delayedKey)
+ local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
+ if #result then
+ local nextTimestamp = tonumber(result[2])
+ if nextTimestamp ~= nil then
+ return nextTimestamp / 0x1000
+ end
+ end
+end
+local function addDelayMarkerIfNeeded(markerKey, delayedKey)
+ local nextTimestamp = getNextDelayedTimestamp(delayedKey)
+ if nextTimestamp ~= nil then
+ -- Replace the score of the marker with the newest known
+ -- next timestamp.
+ rcall("ZADD", markerKey, nextTimestamp, "1")
+ end
+end
+--[[
+ Bake in the job id first 12 bits into the timestamp
+ to guarantee correct execution order of delayed jobs
+ (up to 4096 jobs per given timestamp or 4096 jobs apart per timestamp)
+ WARNING: Jobs that are so far apart that they wrap around will cause FIFO to fail
+]]
+local function getDelayedScore(delayedKey, timestamp, delay)
+ local delayedTimestamp = (delay > 0 and (tonumber(timestamp) + delay)) or tonumber(timestamp)
+ local minScore = delayedTimestamp * 0x1000
+ local maxScore = (delayedTimestamp + 1 ) * 0x1000 - 1
+ local result = rcall("ZREVRANGEBYSCORE", delayedKey, maxScore,
+ minScore, "WITHSCORES","LIMIT", 0, 1)
+ if #result then
+ local currentMaxScore = tonumber(result[2])
+ if currentMaxScore ~= nil then
+ if currentMaxScore >= maxScore then
+ return maxScore, delayedTimestamp
+ else
+ return currentMaxScore + 1, delayedTimestamp
+ end
+ end
+ end
+ return minScore, delayedTimestamp
+end
+local function addDelayedJob(jobId, delayedKey, eventsKey, timestamp,
+ maxEvents, markerKey, delay)
+ local score, delayedTimestamp = getDelayedScore(delayedKey, timestamp, tonumber(delay))
+ rcall("ZADD", delayedKey, score, jobId)
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "delayed",
+ "jobId", jobId, "delay", delayedTimestamp)
+ -- mark that a delayed job is available
+ addDelayMarkerIfNeeded(markerKey, delayedKey)
+end
+--[[
+ Function to add job in target list and add marker if needed.
+]]
+-- Includes
+--[[
+ Add marker if needed when a job is available.
+]]
+local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+ if not isPausedOrMaxed then
+ rcall("ZADD", markerKey, 0, "0")
+ end
+end
+local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ rcall(pushCmd, targetKey, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to add job considering priority.
+]]
+-- Includes
+--[[
+ Function to get priority score.
+]]
+local function getPriorityScore(priority, priorityCounterKey)
+ local prioCounter = rcall("INCR", priorityCounterKey)
+ return priority * 0x100000000 + prioCounter % 0x100000000
+end
+local function addJobWithPriority(markerKey, prioritizedKey, priority, jobId, priorityCounterKey,
+ isPausedOrMaxed)
+ local score = getPriorityScore(priority, priorityCounterKey)
+ rcall("ZADD", prioritizedKey, score, jobId)
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
+end
+--[[
+ Function to check for the meta.paused key to decide if we are paused or not
+ (since an empty list and !EXISTS are not really the same).
+]]
+local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency", "max", "duration")
+ if queueAttributes[1] then
+ return pausedKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ if queueAttributes[2] then
+ local activeCount = rcall("LLEN", activeKey)
+ if activeCount >= tonumber(queueAttributes[2]) then
+ return waitKey, true, queueAttributes[3], queueAttributes[4]
+ else
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+ end
+ end
+ end
+ return waitKey, false, queueAttributes[3], queueAttributes[4]
+end
+--[[
+ Function to store a job
+]]
+local function storeJob(eventsKey, jobIdKey, jobId, name, data, opts, timestamp,
+ parentKey, parentData, repeatJobKey)
+ local jsonOpts = cjson.encode(opts)
+ local delay = opts['delay'] or 0
+ local priority = opts['priority'] or 0
+ local debounceId = opts['de'] and opts['de']['id']
+ local optionalValues = {}
+ if parentKey ~= nil then
+ table.insert(optionalValues, "parentKey")
+ table.insert(optionalValues, parentKey)
+ table.insert(optionalValues, "parent")
+ table.insert(optionalValues, parentData)
+ end
+ if repeatJobKey then
+ table.insert(optionalValues, "rjk")
+ table.insert(optionalValues, repeatJobKey)
+ end
+ if debounceId then
+ table.insert(optionalValues, "deid")
+ table.insert(optionalValues, debounceId)
+ end
+ rcall("HMSET", jobIdKey, "name", name, "data", data, "opts", jsonOpts,
+ "timestamp", timestamp, "delay", delay, "priority", priority,
+ unpack(optionalValues))
+ rcall("XADD", eventsKey, "*", "event", "added", "jobId", jobId, "name", name)
+ return delay, priority
+end
+local function storeAndEnqueueJob(eventsKey, jobIdKey, jobId, name, data, opts,
+ timestamp, parentKey, parentData, repeatJobKey, maxEvents,
+ waitKey, pausedKey, activeKey, metaKey, prioritizedKey,
+ priorityCounterKey, delayedKey, markerKey)
+ local delay, priority = storeJob(eventsKey, jobIdKey, jobId, name, data,
+ opts, timestamp, parentKey, parentData, repeatJobKey)
+ if delay ~= 0 and delayedKey then
+ addDelayedJob(jobId, delayedKey, eventsKey, timestamp, maxEvents, markerKey, delay)
+ else
+ local target, isPausedOrMaxed = getTargetQueueList(metaKey, activeKey, waitKey, pausedKey)
+ if priority > 0 then
+ addJobWithPriority(markerKey, prioritizedKey, priority, jobId,
+ priorityCounterKey, isPausedOrMaxed)
+ else
+ local pushCmd = opts['lifo'] and 'RPUSH' or 'LPUSH'
+ addJobInTargetList(target, markerKey, pushCmd, isPausedOrMaxed, jobId)
+ end
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "waiting",
+ "jobId", jobId)
+ end
+ return delay, priority
+end
+local function addJobFromScheduler(jobKey, jobId, opts, waitKey, pausedKey, activeKey, metaKey,
+ prioritizedKey, priorityCounter, delayedKey, markerKey, eventsKey, name, maxEvents, timestamp,
+ data, jobSchedulerId, repeatDelay)
+ opts['delay'] = repeatDelay
+ opts['jobId'] = jobId
+ storeAndEnqueueJob(eventsKey, jobKey, jobId, name, data, opts,
+ timestamp, nil, nil, jobSchedulerId, maxEvents,
+ waitKey, pausedKey, activeKey, metaKey, prioritizedKey,
+ priorityCounter, delayedKey, markerKey)
+end
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+local function getJobSchedulerEveryNextMillis(prevMillis, every, now, offset, startDate)
+ local nextMillis
+ if not prevMillis then
+ if startDate then
+ -- Assuming startDate is passed as milliseconds from JavaScript
+ nextMillis = tonumber(startDate)
+ nextMillis = nextMillis > now and nextMillis or now
+ else
+ nextMillis = now
+ end
+ else
+ nextMillis = prevMillis + every
+ -- check if we may have missed some iterations
+ if nextMillis < now then
+ nextMillis = math.floor(now / every) * every + every + (offset or 0)
+ end
+ end
+ if not offset or offset == 0 then
+ local timeSlot = math.floor(nextMillis / every) * every;
+ offset = nextMillis - timeSlot;
+ end
+ -- Return a tuple nextMillis, offset
+ return math.floor(nextMillis), math.floor(offset)
+end
+local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
+-- Validate that scheduler exists.
+-- If it does not exist we should not iterate anymore.
+if prevMillis then
+ prevMillis = tonumber(prevMillis)
+ local schedulerKey = repeatKey .. ":" .. jobSchedulerId
+ local schedulerAttributes = rcall("HMGET", schedulerKey, "name", "data", "every", "startDate", "offset")
+ local every = tonumber(schedulerAttributes[3])
+ local now = tonumber(timestamp)
+ -- If every is not found in scheduler attributes, try to get it from job options
+ if not every and jobOpts['repeat'] and jobOpts['repeat']['every'] then
+ every = tonumber(jobOpts['repeat']['every'])
+ end
+ if every then
+ local startDate = schedulerAttributes[4]
+ local jobOptsOffset = jobOpts['repeat'] and jobOpts['repeat']['offset'] or 0
+ local offset = schedulerAttributes[5] or jobOptsOffset or 0
+ local newOffset
+ nextMillis, newOffset = getJobSchedulerEveryNextMillis(prevMillis, every, now, offset, startDate)
+ if not offset then
+ rcall("HSET", schedulerKey, "offset", newOffset)
+ jobOpts['repeat']['offset'] = newOffset
+ end
+ end
+ local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
+ local nextDelayedJobKey = schedulerKey .. ":" .. nextMillis
+ local currentDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. prevMillis
+ if producerId == currentDelayedJobId then
+ local eventsKey = KEYS[9]
+ local maxEvents = getOrSetMaxEvents(metaKey)
+ if rcall("EXISTS", nextDelayedJobKey) ~= 1 then
+ rcall("ZADD", repeatKey, nextMillis, jobSchedulerId)
+ rcall("HINCRBY", schedulerKey, "ic", 1)
+ rcall("INCR", KEYS[8])
+ -- TODO: remove this workaround in next breaking change,
+ -- all job-schedulers must save job data
+ local templateData = schedulerAttributes[2] or ARGV[3]
+ if templateData and templateData ~= '{}' then
+ rcall("HSET", schedulerKey, "data", templateData)
+ end
+ local delay = nextMillis - now
+ -- Fast Clamp delay to minimum of 0
+ if delay < 0 then
+ delay = 0
+ end
+ jobOpts["delay"] = delay
+ addJobFromScheduler(nextDelayedJobKey, nextDelayedJobId, jobOpts, waitKey, pausedKey, KEYS[12], metaKey,
+ prioritizedKey, KEYS[10], delayedKey, KEYS[7], eventsKey, schedulerAttributes[1], maxEvents, ARGV[5],
+ templateData or '{}', jobSchedulerId, delay)
+ -- TODO: remove this workaround in next breaking change
+ if KEYS[11] ~= "" then
+ rcall("HSET", KEYS[11], "nrjid", nextDelayedJobId)
+ end
+ return nextDelayedJobId .. "" -- convert to string
+ else
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "duplicated", "jobId", nextDelayedJobId)
+ end
+ end
+end
+`;
+var updateJobScheduler = {
+ name: "updateJobScheduler",
+ content: content49,
+ keys: 12
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/updateProgress-3.js
+var content50 = `--[[
+ Update job progress
+ Input:
+ KEYS[1] Job id key
+ KEYS[2] event stream key
+ KEYS[3] meta key
+ ARGV[1] id
+ ARGV[2] progress
+ Output:
+ 0 - OK
+ -1 - Missing job.
+ Event:
+ progress(jobId, progress)
+]]
+local rcall = redis.call
+-- Includes
+--[[
+ Function to get max events value or set by default 10000.
+]]
+local function getOrSetMaxEvents(metaKey)
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
+ if not maxEvents then
+ maxEvents = 10000
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
+ end
+ return maxEvents
+end
+if rcall("EXISTS", KEYS[1]) == 1 then -- // Make sure job exists
+ local maxEvents = getOrSetMaxEvents(KEYS[3])
+ rcall("HSET", KEYS[1], "progress", ARGV[2])
+ rcall("XADD", KEYS[2], "MAXLEN", "~", maxEvents, "*", "event", "progress",
+ "jobId", ARGV[1], "data", ARGV[2]);
+ return 0
+else
+ return -1
+end
+`;
+var updateProgress = {
+ name: "updateProgress",
+ content: content50,
+ keys: 3
};
-
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.js
-var import_client17 = __toESM(require_client3(), 1);
-var import_httpAuthSchemes3 = __toESM(require_httpAuthSchemes(), 1);
-
-// node_modules/.pnpm/@aws-sdk+credential-provider-node@3.972.32/node_modules/@aws-sdk/credential-provider-node/dist-es/defaultProvider.js
-init_dist_es();
-var import_property_provider23 = __toESM(require_dist_cjs34(), 1);
-var import_shared_ini_file_loader12 = __toESM(require_dist_cjs35(), 1);
-
-// node_modules/.pnpm/@aws-sdk+credential-provider-node@3.972.32/node_modules/@aws-sdk/credential-provider-node/dist-es/remoteProvider.js
-var import_property_provider9 = __toESM(require_dist_cjs34(), 1);
-var ENV_IMDS_DISABLED = "AWS_EC2_METADATA_DISABLED";
-var remoteProvider = async (init3) => {
- const { ENV_CMDS_FULL_URI: ENV_CMDS_FULL_URI2, ENV_CMDS_RELATIVE_URI: ENV_CMDS_RELATIVE_URI2, fromContainerMetadata: fromContainerMetadata3, fromInstanceMetadata: fromInstanceMetadata3 } = await Promise.resolve().then(() => (init_dist_es2(), exports_dist_es2));
- if (process.env[ENV_CMDS_RELATIVE_URI2] || process.env[ENV_CMDS_FULL_URI2]) {
- init3.logger?.debug("@aws-sdk/credential-provider-node - remoteProvider::fromHttp/fromContainerMetadata");
- const { fromHttp: fromHttp2 } = await Promise.resolve().then(() => (init_dist_es3(), exports_dist_es3));
- return import_property_provider9.chain(fromHttp2(init3), fromContainerMetadata3(init3));
- }
- if (process.env[ENV_IMDS_DISABLED] && process.env[ENV_IMDS_DISABLED] !== "false") {
- return async () => {
- throw new import_property_provider9.CredentialsProviderError("EC2 Instance Metadata Service access disabled", { logger: init3.logger });
- };
- }
- init3.logger?.debug("@aws-sdk/credential-provider-node - remoteProvider::fromInstanceMetadata");
- return fromInstanceMetadata3(init3);
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/scripts/updateRepeatableJobMillis-1.js
+var content51 = `--[[
+ Adds a repeatable job
+ Input:
+ KEYS[1] 'repeat' key
+ ARGV[1] next milliseconds
+ ARGV[2] custom key
+ ARGV[3] legacy custom key TODO: remove this logic in next breaking change
+ Output:
+ repeatableKey - OK
+]]
+local rcall = redis.call
+local repeatKey = KEYS[1]
+local nextMillis = ARGV[1]
+local customKey = ARGV[2]
+local legacyCustomKey = ARGV[3]
+if rcall("ZSCORE", repeatKey, customKey) then
+ rcall("ZADD", repeatKey, nextMillis, customKey)
+ return customKey
+elseif rcall("ZSCORE", repeatKey, legacyCustomKey) ~= false then
+ rcall("ZADD", repeatKey, nextMillis, legacyCustomKey)
+ return legacyCustomKey
+end
+return ''
+`;
+var updateRepeatableJobMillis = {
+ name: "updateRepeatableJobMillis",
+ content: content51,
+ keys: 1
};
-
-// node_modules/.pnpm/@aws-sdk+credential-provider-node@3.972.32/node_modules/@aws-sdk/credential-provider-node/dist-es/runtime/memoize-chain.js
-function memoizeChain(providers, treatAsExpired) {
- const chain2 = internalCreateChain(providers);
- let activeLock;
- let passiveLock;
- let credentials;
- const provider = async (options) => {
- if (options?.forceRefresh) {
- return await chain2(options);
- }
- if (credentials?.expiration) {
- if (credentials?.expiration?.getTime() < Date.now()) {
- credentials = undefined;
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/redis-connection.js
+var overrideMessage = [
+ "BullMQ: WARNING! Your redis options maxRetriesPerRequest must be null",
+ "and will be overridden by BullMQ."
+].join(" ");
+var deprecationMessage = "BullMQ: Your redis options maxRetriesPerRequest must be null.";
+
+class RedisConnection extends EventEmitter {
+ constructor(opts, extraOptions) {
+ super();
+ this.extraOptions = extraOptions;
+ this.capabilities = {
+ canDoubleTimeout: false,
+ canBlockFor1Ms: true
+ };
+ this.status = "initializing";
+ this.dbType = "redis";
+ this.packageVersion = version3;
+ this.extraOptions = Object.assign({ shared: false, blocking: true, skipVersionCheck: false, skipWaitingForReady: false }, extraOptions);
+ if (!isRedisInstance(opts)) {
+ this.checkBlockingOptions(overrideMessage, opts);
+ this.opts = Object.assign({ port: 6379, host: "127.0.0.1", retryStrategy: function(times) {
+ return Math.max(Math.min(Math.exp(times), 20000), 1000);
+ } }, opts);
+ if (this.extraOptions.blocking) {
+ this.opts.maxRetriesPerRequest = null;
}
- }
- if (activeLock) {
- await activeLock;
- } else if (!credentials || treatAsExpired?.(credentials)) {
- if (credentials) {
- if (!passiveLock) {
- passiveLock = chain2(options).then((c2) => {
- credentials = c2;
- }).finally(() => {
- passiveLock = undefined;
- });
- }
- } else {
- activeLock = chain2(options).then((c2) => {
- credentials = c2;
- }).finally(() => {
- activeLock = undefined;
- });
- return provider(options);
+ } else {
+ this._client = opts;
+ if (this._client.options.keyPrefix) {
+ throw new Error("BullMQ: ioredis does not support ioredis prefixes, use the prefix option instead.");
}
- }
- return credentials;
- };
- return provider;
-}
-var internalCreateChain = (providers) => async (awsIdentityProperties) => {
- let lastProviderError;
- for (const provider of providers) {
- try {
- return await provider(awsIdentityProperties);
- } catch (err) {
- lastProviderError = err;
- if (err?.tryNextLink) {
- continue;
+ if (isRedisCluster(this._client)) {
+ this.opts = this._client.options.redisOptions;
+ } else {
+ this.opts = this._client.options;
}
- throw err;
+ this.checkBlockingOptions(deprecationMessage, this.opts, true);
}
+ this.skipVersionCheck = (extraOptions === null || extraOptions === undefined ? undefined : extraOptions.skipVersionCheck) || !!(this.opts && this.opts.skipVersionCheck);
+ this.handleClientError = (err) => {
+ this.emit("error", err);
+ };
+ this.handleClientClose = () => {
+ this.emit("close");
+ };
+ this.handleClientReady = () => {
+ this.emit("ready");
+ };
+ this.initializing = this.init();
+ this.initializing.catch((err) => this.emit("error", err));
}
- throw lastProviderError;
-};
-
-// node_modules/.pnpm/@aws-sdk+credential-provider-node@3.972.32/node_modules/@aws-sdk/credential-provider-node/dist-es/defaultProvider.js
-var multipleCredentialSourceWarningEmitted = false;
-var defaultProvider = (init3 = {}) => memoizeChain([
- async () => {
- const profile = init3.profile ?? process.env[import_shared_ini_file_loader12.ENV_PROFILE];
- if (profile) {
- const envStaticCredentialsAreSet = process.env[ENV_KEY] && process.env[ENV_SECRET];
- if (envStaticCredentialsAreSet) {
- if (!multipleCredentialSourceWarningEmitted) {
- const warnFn = init3.logger?.warn && init3.logger?.constructor?.name !== "NoOpLogger" ? init3.logger.warn.bind(init3.logger) : console.warn;
- warnFn(`@aws-sdk/credential-provider-node - defaultProvider::fromEnv WARNING:
- Multiple credential sources detected:
- Both AWS_PROFILE and the pair AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY static credentials are set.
- This SDK will proceed with the AWS_PROFILE value.
-
- However, a future version may change this behavior to prefer the ENV static credentials.
- Please ensure that your environment only sets either the AWS_PROFILE or the
- AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY pair.
-`);
- multipleCredentialSourceWarningEmitted = true;
- }
+ checkBlockingOptions(msg, options, throwError = false) {
+ if (this.extraOptions.blocking && options && options.maxRetriesPerRequest) {
+ if (throwError) {
+ throw new Error(msg);
+ } else {
+ console.error(msg);
}
- throw new import_property_provider23.CredentialsProviderError("AWS_PROFILE is set, skipping fromEnv provider.", {
- logger: init3.logger,
- tryNextLink: true
- });
- }
- init3.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromEnv");
- return fromEnv(init3)();
- },
- async (awsIdentityProperties) => {
- init3.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromSSO");
- const { ssoStartUrl, ssoAccountId, ssoRegion, ssoRoleName, ssoSession } = init3;
- if (!ssoStartUrl && !ssoAccountId && !ssoRegion && !ssoRoleName && !ssoSession) {
- throw new import_property_provider23.CredentialsProviderError("Skipping SSO provider in default chain (inputs do not include SSO fields).", { logger: init3.logger });
- }
- const { fromSSO: fromSSO3 } = await Promise.resolve().then(() => (init_dist_es5(), exports_dist_es4));
- return fromSSO3(init3)(awsIdentityProperties);
- },
- async (awsIdentityProperties) => {
- init3.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromIni");
- const { fromIni: fromIni3 } = await Promise.resolve().then(() => (init_dist_es9(), exports_dist_es7));
- return fromIni3(init3)(awsIdentityProperties);
- },
- async (awsIdentityProperties) => {
- init3.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromProcess");
- const { fromProcess: fromProcess3 } = await Promise.resolve().then(() => (init_dist_es7(), exports_dist_es5));
- return fromProcess3(init3)(awsIdentityProperties);
- },
- async (awsIdentityProperties) => {
- init3.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromTokenFile");
- const { fromTokenFile: fromTokenFile3 } = await Promise.resolve().then(() => (init_dist_es8(), exports_dist_es6));
- return fromTokenFile3(init3)(awsIdentityProperties);
- },
- async () => {
- init3.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::remoteProvider");
- return (await remoteProvider(init3))();
- },
- async () => {
- throw new import_property_provider23.CredentialsProviderError("Could not load credentials from any providers", {
- tryNextLink: false,
- logger: init3.logger
- });
- }
-], credentialsTreatedAsExpired);
-var credentialsTreatedAsExpired = (credentials) => credentials?.expiration !== undefined && credentials.expiration.getTime() - Date.now() < 300000;
-
-// node_modules/.pnpm/@aws-sdk+middleware-bucket-endpoint@3.972.10/node_modules/@aws-sdk/middleware-bucket-endpoint/dist-es/NodeUseArnRegionConfigOptions.js
-var import_util_config_provider2 = __toESM(require_dist_cjs23(), 1);
-var NODE_USE_ARN_REGION_ENV_NAME = "AWS_S3_USE_ARN_REGION";
-var NODE_USE_ARN_REGION_INI_NAME = "s3_use_arn_region";
-var NODE_USE_ARN_REGION_CONFIG_OPTIONS = {
- environmentVariableSelector: (env2) => import_util_config_provider2.booleanSelector(env2, NODE_USE_ARN_REGION_ENV_NAME, import_util_config_provider2.SelectorType.ENV),
- configFileSelector: (profile) => import_util_config_provider2.booleanSelector(profile, NODE_USE_ARN_REGION_INI_NAME, import_util_config_provider2.SelectorType.CONFIG),
- default: undefined
-};
-
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.js
-var import_util_user_agent_node = __toESM(require_dist_cjs40(), 1);
-var import_config_resolver = __toESM(require_dist_cjs32(), 1);
-
-// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/HeaderMarshaller.js
-var import_util_hex_encoding2 = __toESM(require_dist_cjs11(), 1);
-
-// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/Int64.js
-var import_util_hex_encoding = __toESM(require_dist_cjs11(), 1);
-
-class Int64 {
- bytes;
- constructor(bytes) {
- this.bytes = bytes;
- if (bytes.byteLength !== 8) {
- throw new Error("Int64 buffers must be exactly 8 bytes");
- }
- }
- static fromNumber(number2) {
- if (number2 > 9223372036854776000 || number2 < -9223372036854776000) {
- throw new Error(`${number2} is too large (or, if negative, too small) to represent as an Int64`);
- }
- const bytes = new Uint8Array(8);
- for (let i2 = 7, remaining = Math.abs(Math.round(number2));i2 > -1 && remaining > 0; i2--, remaining /= 256) {
- bytes[i2] = remaining;
- }
- if (number2 < 0) {
- negate(bytes);
- }
- return new Int64(bytes);
- }
- valueOf() {
- const bytes = this.bytes.slice(0);
- const negative = bytes[0] & 128;
- if (negative) {
- negate(bytes);
}
- return parseInt(import_util_hex_encoding.toHex(bytes), 16) * (negative ? -1 : 1);
- }
- toString() {
- return String(this.valueOf());
- }
-}
-function negate(bytes) {
- for (let i2 = 0;i2 < 8; i2++) {
- bytes[i2] ^= 255;
- }
- for (let i2 = 7;i2 > -1; i2--) {
- bytes[i2]++;
- if (bytes[i2] !== 0)
- break;
- }
-}
-
-// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/HeaderMarshaller.js
-class HeaderMarshaller {
- toUtf8;
- fromUtf8;
- constructor(toUtf82, fromUtf84) {
- this.toUtf8 = toUtf82;
- this.fromUtf8 = fromUtf84;
}
- format(headers) {
- const chunks = [];
- for (const headerName of Object.keys(headers)) {
- const bytes = this.fromUtf8(headerName);
- chunks.push(Uint8Array.from([bytes.byteLength]), bytes, this.formatHeaderValue(headers[headerName]));
+ static async waitUntilReady(client) {
+ if (client.status === "ready") {
+ return;
}
- const out = new Uint8Array(chunks.reduce((carry, bytes) => carry + bytes.byteLength, 0));
- let position = 0;
- for (const chunk of chunks) {
- out.set(chunk, position);
- position += chunk.byteLength;
+ if (client.status === "connect" && isRedisCluster(client)) {
+ return;
}
- return out;
- }
- formatHeaderValue(header) {
- switch (header.type) {
- case "boolean":
- return Uint8Array.from([header.value ? 0 : 1]);
- case "byte":
- return Uint8Array.from([2, header.value]);
- case "short":
- const shortView = new DataView(new ArrayBuffer(3));
- shortView.setUint8(0, 3);
- shortView.setInt16(1, header.value, false);
- return new Uint8Array(shortView.buffer);
- case "integer":
- const intView = new DataView(new ArrayBuffer(5));
- intView.setUint8(0, 4);
- intView.setInt32(1, header.value, false);
- return new Uint8Array(intView.buffer);
- case "long":
- const longBytes = new Uint8Array(9);
- longBytes[0] = 5;
- longBytes.set(header.value.bytes, 1);
- return longBytes;
- case "binary":
- const binView = new DataView(new ArrayBuffer(3 + header.value.byteLength));
- binView.setUint8(0, 6);
- binView.setUint16(1, header.value.byteLength, false);
- const binBytes = new Uint8Array(binView.buffer);
- binBytes.set(header.value, 3);
- return binBytes;
- case "string":
- const utf8Bytes = this.fromUtf8(header.value);
- const strView = new DataView(new ArrayBuffer(3 + utf8Bytes.byteLength));
- strView.setUint8(0, 7);
- strView.setUint16(1, utf8Bytes.byteLength, false);
- const strBytes = new Uint8Array(strView.buffer);
- strBytes.set(utf8Bytes, 3);
- return strBytes;
- case "timestamp":
- const tsBytes = new Uint8Array(9);
- tsBytes[0] = 8;
- tsBytes.set(Int64.fromNumber(header.value.valueOf()).bytes, 1);
- return tsBytes;
- case "uuid":
- if (!UUID_PATTERN.test(header.value)) {
- throw new Error(`Invalid UUID received: ${header.value}`);
- }
- const uuidBytes = new Uint8Array(17);
- uuidBytes[0] = 9;
- uuidBytes.set(import_util_hex_encoding2.fromHex(header.value.replace(/\-/g, "")), 1);
- return uuidBytes;
+ if (client.status === "wait") {
+ return client.connect();
}
- }
- parse(headers) {
- const out = {};
- let position = 0;
- while (position < headers.byteLength) {
- const nameLength = headers.getUint8(position++);
- const name = this.toUtf8(new Uint8Array(headers.buffer, headers.byteOffset + position, nameLength));
- position += nameLength;
- switch (headers.getUint8(position++)) {
- case 0:
- out[name] = {
- type: BOOLEAN_TAG,
- value: true
- };
- break;
- case 1:
- out[name] = {
- type: BOOLEAN_TAG,
- value: false
- };
- break;
- case 2:
- out[name] = {
- type: BYTE_TAG,
- value: headers.getInt8(position++)
- };
- break;
- case 3:
- out[name] = {
- type: SHORT_TAG,
- value: headers.getInt16(position, false)
- };
- position += 2;
- break;
- case 4:
- out[name] = {
- type: INT_TAG,
- value: headers.getInt32(position, false)
- };
- position += 4;
- break;
- case 5:
- out[name] = {
- type: LONG_TAG,
- value: new Int64(new Uint8Array(headers.buffer, headers.byteOffset + position, 8))
- };
- position += 8;
- break;
- case 6:
- const binaryLength = headers.getUint16(position, false);
- position += 2;
- out[name] = {
- type: BINARY_TAG,
- value: new Uint8Array(headers.buffer, headers.byteOffset + position, binaryLength)
- };
- position += binaryLength;
- break;
- case 7:
- const stringLength = headers.getUint16(position, false);
- position += 2;
- out[name] = {
- type: STRING_TAG,
- value: this.toUtf8(new Uint8Array(headers.buffer, headers.byteOffset + position, stringLength))
- };
- position += stringLength;
- break;
- case 8:
- out[name] = {
- type: TIMESTAMP_TAG,
- value: new Date(new Int64(new Uint8Array(headers.buffer, headers.byteOffset + position, 8)).valueOf())
- };
- position += 8;
- break;
- case 9:
- const uuidBytes = new Uint8Array(headers.buffer, headers.byteOffset + position, 16);
- position += 16;
- out[name] = {
- type: UUID_TAG,
- value: `${import_util_hex_encoding2.toHex(uuidBytes.subarray(0, 4))}-${import_util_hex_encoding2.toHex(uuidBytes.subarray(4, 6))}-${import_util_hex_encoding2.toHex(uuidBytes.subarray(6, 8))}-${import_util_hex_encoding2.toHex(uuidBytes.subarray(8, 10))}-${import_util_hex_encoding2.toHex(uuidBytes.subarray(10))}`
- };
- break;
- default:
- throw new Error(`Unrecognized header type tag`);
- }
+ if (client.status === "end") {
+ throw new Error(import_utils58.CONNECTION_CLOSED_ERROR_MSG);
}
- return out;
- }
-}
-var HEADER_VALUE_TYPE;
-(function(HEADER_VALUE_TYPE2) {
- HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["boolTrue"] = 0] = "boolTrue";
- HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["boolFalse"] = 1] = "boolFalse";
- HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["byte"] = 2] = "byte";
- HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["short"] = 3] = "short";
- HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["integer"] = 4] = "integer";
- HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["long"] = 5] = "long";
- HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["byteArray"] = 6] = "byteArray";
- HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["string"] = 7] = "string";
- HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["timestamp"] = 8] = "timestamp";
- HEADER_VALUE_TYPE2[HEADER_VALUE_TYPE2["uuid"] = 9] = "uuid";
-})(HEADER_VALUE_TYPE || (HEADER_VALUE_TYPE = {}));
-var BOOLEAN_TAG = "boolean";
-var BYTE_TAG = "byte";
-var SHORT_TAG = "short";
-var INT_TAG = "integer";
-var LONG_TAG = "long";
-var BINARY_TAG = "binary";
-var STRING_TAG = "string";
-var TIMESTAMP_TAG = "timestamp";
-var UUID_TAG = "uuid";
-var UUID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
-
-// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/splitMessage.js
-var PRELUDE_MEMBER_LENGTH = 4;
-var PRELUDE_LENGTH = PRELUDE_MEMBER_LENGTH * 2;
-var CHECKSUM_LENGTH = 4;
-var MINIMUM_MESSAGE_LENGTH = PRELUDE_LENGTH + CHECKSUM_LENGTH * 2;
-function splitMessage({ byteLength, byteOffset, buffer }) {
- if (byteLength < MINIMUM_MESSAGE_LENGTH) {
- throw new Error("Provided message too short to accommodate event stream message overhead");
- }
- const view = new DataView(buffer, byteOffset, byteLength);
- const messageLength = view.getUint32(0, false);
- if (byteLength !== messageLength) {
- throw new Error("Reported message length does not match received message length");
- }
- const headerLength = view.getUint32(PRELUDE_MEMBER_LENGTH, false);
- const expectedPreludeChecksum = view.getUint32(PRELUDE_LENGTH, false);
- const expectedMessageChecksum = view.getUint32(byteLength - CHECKSUM_LENGTH, false);
- const checksummer = new Crc32().update(new Uint8Array(buffer, byteOffset, PRELUDE_LENGTH));
- if (expectedPreludeChecksum !== checksummer.digest()) {
- throw new Error(`The prelude checksum specified in the message (${expectedPreludeChecksum}) does not match the calculated CRC32 checksum (${checksummer.digest()})`);
- }
- checksummer.update(new Uint8Array(buffer, byteOffset + PRELUDE_LENGTH, byteLength - (PRELUDE_LENGTH + CHECKSUM_LENGTH)));
- if (expectedMessageChecksum !== checksummer.digest()) {
- throw new Error(`The message checksum (${checksummer.digest()}) did not match the expected value of ${expectedMessageChecksum}`);
- }
- return {
- headers: new DataView(buffer, byteOffset + PRELUDE_LENGTH + CHECKSUM_LENGTH, headerLength),
- body: new Uint8Array(buffer, byteOffset + PRELUDE_LENGTH + CHECKSUM_LENGTH + headerLength, messageLength - headerLength - (PRELUDE_LENGTH + CHECKSUM_LENGTH + CHECKSUM_LENGTH))
- };
-}
-
-// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/EventStreamCodec.js
-class EventStreamCodec {
- headerMarshaller;
- messageBuffer;
- isEndOfStream;
- constructor(toUtf82, fromUtf84) {
- this.headerMarshaller = new HeaderMarshaller(toUtf82, fromUtf84);
- this.messageBuffer = [];
- this.isEndOfStream = false;
- }
- feed(message) {
- this.messageBuffer.push(this.decode(message));
- }
- endOfStream() {
- this.isEndOfStream = true;
- }
- getMessage() {
- const message = this.messageBuffer.pop();
- const isEndOfStream = this.isEndOfStream;
- return {
- getMessage() {
- return message;
- },
- isEndOfStream() {
- return isEndOfStream;
- }
- };
- }
- getAvailableMessages() {
- const messages = this.messageBuffer;
- this.messageBuffer = [];
- const isEndOfStream = this.isEndOfStream;
- return {
- getMessages() {
- return messages;
- },
- isEndOfStream() {
- return isEndOfStream;
+ let handleReady;
+ let handleEnd;
+ let handleError;
+ try {
+ await new Promise((resolve, reject) => {
+ let lastError;
+ handleError = (err) => {
+ lastError = err;
+ };
+ handleReady = () => {
+ resolve();
+ };
+ handleEnd = () => {
+ if (client.status !== "end") {
+ reject(lastError || new Error(import_utils58.CONNECTION_CLOSED_ERROR_MSG));
+ } else {
+ if (lastError) {
+ reject(lastError);
+ } else {
+ resolve();
+ }
+ }
+ };
+ increaseMaxListeners(client, 3);
+ client.once("ready", handleReady);
+ client.on("end", handleEnd);
+ client.once("error", handleError);
+ });
+ } finally {
+ client.removeListener("end", handleEnd);
+ client.removeListener("error", handleError);
+ client.removeListener("ready", handleReady);
+ decreaseMaxListeners(client, 3);
+ }
+ }
+ get client() {
+ return this.initializing;
+ }
+ loadCommands(packageVersion, providedScripts) {
+ const finalScripts = providedScripts || exports_scripts;
+ for (const property in finalScripts) {
+ const commandName = `${finalScripts[property].name}:${packageVersion}`;
+ if (!this._client[commandName]) {
+ this._client.defineCommand(commandName, {
+ numberOfKeys: finalScripts[property].keys,
+ lua: finalScripts[property].content
+ });
}
- };
- }
- encode({ headers: rawHeaders, body }) {
- const headers = this.headerMarshaller.format(rawHeaders);
- const length = headers.byteLength + body.byteLength + 16;
- const out = new Uint8Array(length);
- const view = new DataView(out.buffer, out.byteOffset, out.byteLength);
- const checksum = new Crc32;
- view.setUint32(0, length, false);
- view.setUint32(4, headers.byteLength, false);
- view.setUint32(8, checksum.update(out.subarray(0, 8)).digest(), false);
- out.set(headers, 12);
- out.set(body, headers.byteLength + 12);
- view.setUint32(length - 4, checksum.update(out.subarray(8, length - 4)).digest(), false);
- return out;
- }
- decode(message) {
- const { headers, body } = splitMessage(message);
- return { headers: this.headerMarshaller.parse(headers), body };
- }
- formatHeaders(rawHeaders) {
- return this.headerMarshaller.format(rawHeaders);
- }
-}
-
-// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/MessageDecoderStream.js
-class MessageDecoderStream {
- options;
- constructor(options) {
- this.options = options;
- }
- [Symbol.asyncIterator]() {
- return this.asyncIterator();
- }
- async* asyncIterator() {
- for await (const bytes of this.options.inputStream) {
- const decoded = this.options.decoder.decode(bytes);
- yield decoded;
- }
- }
-}
-
-// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/MessageEncoderStream.js
-class MessageEncoderStream {
- options;
- constructor(options) {
- this.options = options;
- }
- [Symbol.asyncIterator]() {
- return this.asyncIterator();
- }
- async* asyncIterator() {
- for await (const msg of this.options.messageStream) {
- const encoded = this.options.encoder.encode(msg);
- yield encoded;
- }
- if (this.options.includeEndFrame) {
- yield new Uint8Array(0);
- }
- }
-}
-
-// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/SmithyMessageDecoderStream.js
-class SmithyMessageDecoderStream {
- options;
- constructor(options) {
- this.options = options;
- }
- [Symbol.asyncIterator]() {
- return this.asyncIterator();
- }
- async* asyncIterator() {
- for await (const message of this.options.messageStream) {
- const deserialized = await this.options.deserializer(message);
- if (deserialized === undefined)
- continue;
- yield deserialized;
}
}
-}
-
-// node_modules/.pnpm/@smithy+eventstream-codec@4.2.14/node_modules/@smithy/eventstream-codec/dist-es/SmithyMessageEncoderStream.js
-class SmithyMessageEncoderStream {
- options;
- constructor(options) {
- this.options = options;
- }
- [Symbol.asyncIterator]() {
- return this.asyncIterator();
- }
- async* asyncIterator() {
- for await (const chunk of this.options.inputStream) {
- const payloadBuf = this.options.serializer(chunk);
- yield payloadBuf;
+ async init() {
+ if (!this._client) {
+ const _a = this.opts, { url } = _a, rest = __rest(_a, ["url"]);
+ this._client = url ? new import_ioredis3.default(url, rest) : new import_ioredis3.default(rest);
}
- }
-}
-
-// node_modules/.pnpm/@smithy+eventstream-serde-universal@4.2.14/node_modules/@smithy/eventstream-serde-universal/dist-es/getChunkedStream.js
-function getChunkedStream(source) {
- let currentMessageTotalLength = 0;
- let currentMessagePendingLength = 0;
- let currentMessage = null;
- let messageLengthBuffer = null;
- const allocateMessage = (size) => {
- if (typeof size !== "number") {
- throw new Error("Attempted to allocate an event message where size was not a number: " + size);
+ increaseMaxListeners(this._client, 3);
+ this._client.on("error", this.handleClientError);
+ this._client.on("close", this.handleClientClose);
+ this._client.on("ready", this.handleClientReady);
+ if (!this.extraOptions.skipWaitingForReady) {
+ await RedisConnection.waitUntilReady(this._client);
}
- currentMessageTotalLength = size;
- currentMessagePendingLength = 4;
- currentMessage = new Uint8Array(size);
- const currentMessageView = new DataView(currentMessage.buffer);
- currentMessageView.setUint32(0, size, false);
- };
- const iterator = async function* () {
- const sourceIterator = source[Symbol.asyncIterator]();
- while (true) {
- const { value, done } = await sourceIterator.next();
- if (done) {
- if (!currentMessageTotalLength) {
- return;
- } else if (currentMessageTotalLength === currentMessagePendingLength) {
- yield currentMessage;
- } else {
- throw new Error("Truncated event message received.");
- }
- return;
- }
- const chunkLength = value.length;
- let currentOffset = 0;
- while (currentOffset < chunkLength) {
- if (!currentMessage) {
- const bytesRemaining = chunkLength - currentOffset;
- if (!messageLengthBuffer) {
- messageLengthBuffer = new Uint8Array(4);
- }
- const numBytesForTotal = Math.min(4 - currentMessagePendingLength, bytesRemaining);
- messageLengthBuffer.set(value.slice(currentOffset, currentOffset + numBytesForTotal), currentMessagePendingLength);
- currentMessagePendingLength += numBytesForTotal;
- currentOffset += numBytesForTotal;
- if (currentMessagePendingLength < 4) {
- break;
- }
- allocateMessage(new DataView(messageLengthBuffer.buffer).getUint32(0, false));
- messageLengthBuffer = null;
+ this.loadCommands(this.packageVersion);
+ if (this._client["status"] !== "end") {
+ const versionResult = await this.getRedisVersionAndType();
+ this.version = versionResult.version;
+ this.dbType = versionResult.databaseType;
+ if (this.skipVersionCheck !== true && !this.closing) {
+ if (isRedisVersionLowerThan(this.version, RedisConnection.minimumVersion, this.dbType)) {
+ throw new Error(`Redis version needs to be greater or equal than ${RedisConnection.minimumVersion} ` + `Current: ${this.version}`);
}
- const numBytesToWrite = Math.min(currentMessageTotalLength - currentMessagePendingLength, chunkLength - currentOffset);
- currentMessage.set(value.slice(currentOffset, currentOffset + numBytesToWrite), currentMessagePendingLength);
- currentMessagePendingLength += numBytesToWrite;
- currentOffset += numBytesToWrite;
- if (currentMessageTotalLength && currentMessageTotalLength === currentMessagePendingLength) {
- yield currentMessage;
- currentMessage = null;
- currentMessageTotalLength = 0;
- currentMessagePendingLength = 0;
+ if (isRedisVersionLowerThan(this.version, RedisConnection.recommendedMinimumVersion, this.dbType)) {
+ console.warn(`It is highly recommended to use a minimum Redis version of ${RedisConnection.recommendedMinimumVersion}
+ Current: ${this.version}`);
}
}
- }
- };
- return {
- [Symbol.asyncIterator]: iterator
- };
-}
-
-// node_modules/.pnpm/@smithy+eventstream-serde-universal@4.2.14/node_modules/@smithy/eventstream-serde-universal/dist-es/getUnmarshalledStream.js
-function getMessageUnmarshaller(deserializer, toUtf82) {
- return async function(message) {
- const { value: messageType } = message.headers[":message-type"];
- if (messageType === "error") {
- const unmodeledError = new Error(message.headers[":error-message"].value || "UnknownError");
- unmodeledError.name = message.headers[":error-code"].value;
- throw unmodeledError;
- } else if (messageType === "exception") {
- const code = message.headers[":exception-type"].value;
- const exception = { [code]: message };
- const deserializedException = await deserializer(exception);
- if (deserializedException.$unknown) {
- const error = new Error(toUtf82(message.body));
- error.name = code;
- throw error;
- }
- throw deserializedException[code];
- } else if (messageType === "event") {
- const event = {
- [message.headers[":event-type"].value]: message
+ this.capabilities = {
+ canDoubleTimeout: !isRedisVersionLowerThan(this.version, "6.0.0", this.dbType),
+ canBlockFor1Ms: !isRedisVersionLowerThan(this.version, "7.0.8", this.dbType)
};
- const deserialized = await deserializer(event);
- if (deserialized.$unknown)
- return;
- return deserialized;
- } else {
- throw Error(`Unrecognizable event type: ${message.headers[":event-type"].value}`);
- }
- };
-}
-
-// node_modules/.pnpm/@smithy+eventstream-serde-universal@4.2.14/node_modules/@smithy/eventstream-serde-universal/dist-es/EventStreamMarshaller.js
-class EventStreamMarshaller {
- eventStreamCodec;
- utfEncoder;
- constructor({ utf8Encoder, utf8Decoder }) {
- this.eventStreamCodec = new EventStreamCodec(utf8Encoder, utf8Decoder);
- this.utfEncoder = utf8Encoder;
- }
- deserialize(body, deserializer) {
- const inputStream = getChunkedStream(body);
- return new SmithyMessageDecoderStream({
- messageStream: new MessageDecoderStream({ inputStream, decoder: this.eventStreamCodec }),
- deserializer: getMessageUnmarshaller(deserializer, this.utfEncoder)
- });
- }
- serialize(inputStream, serializer) {
- return new MessageEncoderStream({
- messageStream: new SmithyMessageEncoderStream({ inputStream, serializer }),
- encoder: this.eventStreamCodec,
- includeEndFrame: true
- });
- }
-}
-
-// node_modules/.pnpm/@smithy+eventstream-serde-node@4.2.14/node_modules/@smithy/eventstream-serde-node/dist-es/EventStreamMarshaller.js
-import { Readable } from "stream";
-
-// node_modules/.pnpm/@smithy+eventstream-serde-node@4.2.14/node_modules/@smithy/eventstream-serde-node/dist-es/utils.js
-async function* readabletoIterable(readStream) {
- let streamEnded = false;
- let generationEnded = false;
- const records = new Array;
- readStream.on("error", (err) => {
- if (!streamEnded) {
- streamEnded = true;
- }
- if (err) {
- throw err;
- }
- });
- readStream.on("data", (data) => {
- records.push(data);
- });
- readStream.on("end", () => {
- streamEnded = true;
- });
- while (!generationEnded) {
- const value = await new Promise((resolve) => setTimeout(() => resolve(records.shift()), 0));
- if (value) {
- yield value;
- }
- generationEnded = streamEnded && records.length === 0;
- }
-}
-
-// node_modules/.pnpm/@smithy+eventstream-serde-node@4.2.14/node_modules/@smithy/eventstream-serde-node/dist-es/EventStreamMarshaller.js
-class EventStreamMarshaller2 {
- universalMarshaller;
- constructor({ utf8Encoder, utf8Decoder }) {
- this.universalMarshaller = new EventStreamMarshaller({
- utf8Decoder,
- utf8Encoder
- });
- }
- deserialize(body, deserializer) {
- const bodyIterable = typeof body[Symbol.asyncIterator] === "function" ? body : readabletoIterable(body);
- return this.universalMarshaller.deserialize(bodyIterable, deserializer);
- }
- serialize(input, serializer) {
- return Readable.from(this.universalMarshaller.serialize(input, serializer));
- }
-}
-
-// node_modules/.pnpm/@smithy+eventstream-serde-node@4.2.14/node_modules/@smithy/eventstream-serde-node/dist-es/provider.js
-var eventStreamSerdeProvider = (options) => new EventStreamMarshaller2(options);
-
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.js
-var import_hash_node = __toESM(require_dist_cjs41(), 1);
-
-// node_modules/.pnpm/@smithy+hash-stream-node@4.2.14/node_modules/@smithy/hash-stream-node/dist-es/HashCalculator.js
-var import_util_utf83 = __toESM(require_dist_cjs5(), 1);
-import { Writable } from "stream";
-
-class HashCalculator extends Writable {
- hash;
- constructor(hash4, options) {
- super(options);
- this.hash = hash4;
- }
- _write(chunk, encoding, callback) {
- try {
- this.hash.update(import_util_utf83.toUint8Array(chunk));
- } catch (err) {
- return callback(err);
+ this.status = "ready";
}
- callback();
- }
-}
-
-// node_modules/.pnpm/@smithy+hash-stream-node@4.2.14/node_modules/@smithy/hash-stream-node/dist-es/readableStreamHasher.js
-var readableStreamHasher = (hashCtor, readableStream) => {
- if (readableStream.readableFlowing !== null) {
- throw new Error("Unable to calculate hash for flowing readable stream");
+ return this._client;
}
- const hash4 = new hashCtor;
- const hashCalculator = new HashCalculator(hash4);
- readableStream.pipe(hashCalculator);
- return new Promise((resolve, reject) => {
- readableStream.on("error", (err) => {
- hashCalculator.end();
- reject(err);
- });
- hashCalculator.on("error", reject);
- hashCalculator.on("finish", () => {
- hash4.digest().then(resolve).catch(reject);
- });
- });
-};
-
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.js
-var import_middleware_retry = __toESM(require_dist_cjs39(), 1);
-var import_node_config_provider3 = __toESM(require_dist_cjs36(), 1);
-var import_node_http_handler2 = __toESM(require_dist_cjs9(), 1);
-var import_smithy_client7 = __toESM(require_dist_cjs21(), 1);
-var import_util_body_length_node = __toESM(require_dist_cjs42(), 1);
-var import_util_defaults_mode_node = __toESM(require_dist_cjs43(), 1);
-var import_util_retry = __toESM(require_dist_cjs30(), 1);
-
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.shared.js
-var import_httpAuthSchemes2 = __toESM(require_httpAuthSchemes(), 1);
-var import_smithy_client6 = __toESM(require_dist_cjs21(), 1);
-var import_url_parser2 = __toESM(require_dist_cjs19(), 1);
-var import_util_base64 = __toESM(require_dist_cjs6(), 1);
-var import_util_stream5 = __toESM(require_dist_cjs12(), 1);
-var import_util_utf84 = __toESM(require_dist_cjs5(), 1);
-var getRuntimeConfig = (config) => {
- return {
- apiVersion: "2006-03-01",
- base64Decoder: config?.base64Decoder ?? import_util_base64.fromBase64,
- base64Encoder: config?.base64Encoder ?? import_util_base64.toBase64,
- disableHostPrefix: config?.disableHostPrefix ?? false,
- endpointProvider: config?.endpointProvider ?? defaultEndpointResolver,
- extensions: config?.extensions ?? [],
- getAwsChunkedEncodingStream: config?.getAwsChunkedEncodingStream ?? import_util_stream5.getAwsChunkedEncodingStream,
- httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? defaultS3HttpAuthSchemeProvider,
- httpAuthSchemes: config?.httpAuthSchemes ?? [
- {
- schemeId: "aws.auth#sigv4",
- identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4"),
- signer: new import_httpAuthSchemes2.AwsSdkSigV4Signer
- },
- {
- schemeId: "aws.auth#sigv4a",
- identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4a"),
- signer: new import_httpAuthSchemes2.AwsSdkSigV4ASigner
+ async disconnect(wait = true) {
+ const client = await this.client;
+ if (client.status !== "end") {
+ let _resolve, _reject;
+ if (!wait) {
+ return client.disconnect();
}
- ],
- logger: config?.logger ?? new import_smithy_client6.NoOpLogger,
- protocol: config?.protocol ?? S3RestXmlProtocol,
- protocolSettings: config?.protocolSettings ?? {
- defaultNamespace: "com.amazonaws.s3",
- errorTypeRegistries,
- xmlNamespace: "http://s3.amazonaws.com/doc/2006-03-01/",
- version: "2006-03-01",
- serviceTarget: "AmazonS3"
- },
- sdkStreamMixin: config?.sdkStreamMixin ?? import_util_stream5.sdkStreamMixin,
- serviceId: config?.serviceId ?? "S3",
- signerConstructor: config?.signerConstructor ?? SignatureV4MultiRegion,
- signingEscapePath: config?.signingEscapePath ?? false,
- urlParser: config?.urlParser ?? import_url_parser2.parseUrl,
- useArnRegion: config?.useArnRegion ?? undefined,
- utf8Decoder: config?.utf8Decoder ?? import_util_utf84.fromUtf8,
- utf8Encoder: config?.utf8Encoder ?? import_util_utf84.toUtf8
- };
-};
-
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.js
-var getRuntimeConfig2 = (config) => {
- import_smithy_client7.emitWarningIfUnsupportedVersion(process.version);
- const defaultsMode = import_util_defaults_mode_node.resolveDefaultsModeConfig(config);
- const defaultConfigProvider = () => defaultsMode().then(import_smithy_client7.loadConfigsForDefaultMode);
- const clientSharedValues = getRuntimeConfig(config);
- import_client17.emitWarningIfUnsupportedVersion(process.version);
- const loaderConfig = {
- profile: config?.profile,
- logger: clientSharedValues.logger
- };
- return {
- ...clientSharedValues,
- ...config,
- runtime: "node",
- defaultsMode,
- authSchemePreference: config?.authSchemePreference ?? import_node_config_provider3.loadConfig(import_httpAuthSchemes3.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig),
- bodyLengthChecker: config?.bodyLengthChecker ?? import_util_body_length_node.calculateBodyLength,
- credentialDefaultProvider: config?.credentialDefaultProvider ?? defaultProvider,
- defaultUserAgentProvider: config?.defaultUserAgentProvider ?? import_util_user_agent_node.createDefaultUserAgentProvider({ serviceId: clientSharedValues.serviceId, clientVersion: package_default.version }),
- disableS3ExpressSessionAuth: config?.disableS3ExpressSessionAuth ?? import_node_config_provider3.loadConfig(NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_OPTIONS, loaderConfig),
- eventStreamSerdeProvider: config?.eventStreamSerdeProvider ?? eventStreamSerdeProvider,
- maxAttempts: config?.maxAttempts ?? import_node_config_provider3.loadConfig(import_middleware_retry.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config),
- md5: config?.md5 ?? import_hash_node.Hash.bind(null, "md5"),
- region: config?.region ?? import_node_config_provider3.loadConfig(import_config_resolver.NODE_REGION_CONFIG_OPTIONS, { ...import_config_resolver.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }),
- requestChecksumCalculation: config?.requestChecksumCalculation ?? import_node_config_provider3.loadConfig(NODE_REQUEST_CHECKSUM_CALCULATION_CONFIG_OPTIONS, loaderConfig),
- requestHandler: import_node_http_handler2.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider),
- responseChecksumValidation: config?.responseChecksumValidation ?? import_node_config_provider3.loadConfig(NODE_RESPONSE_CHECKSUM_VALIDATION_CONFIG_OPTIONS, loaderConfig),
- retryMode: config?.retryMode ?? import_node_config_provider3.loadConfig({
- ...import_middleware_retry.NODE_RETRY_MODE_CONFIG_OPTIONS,
- default: async () => (await defaultConfigProvider()).retryMode || import_util_retry.DEFAULT_RETRY_MODE
- }, config),
- sha1: config?.sha1 ?? import_hash_node.Hash.bind(null, "sha1"),
- sha256: config?.sha256 ?? import_hash_node.Hash.bind(null, "sha256"),
- sigv4aSigningRegionSet: config?.sigv4aSigningRegionSet ?? import_node_config_provider3.loadConfig(import_httpAuthSchemes3.NODE_SIGV4A_CONFIG_OPTIONS, loaderConfig),
- streamCollector: config?.streamCollector ?? import_node_http_handler2.streamCollector,
- streamHasher: config?.streamHasher ?? readableStreamHasher,
- useArnRegion: config?.useArnRegion ?? import_node_config_provider3.loadConfig(NODE_USE_ARN_REGION_CONFIG_OPTIONS, loaderConfig),
- useDualstackEndpoint: config?.useDualstackEndpoint ?? import_node_config_provider3.loadConfig(import_config_resolver.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
- useFipsEndpoint: config?.useFipsEndpoint ?? import_node_config_provider3.loadConfig(import_config_resolver.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
- userAgentAppId: config?.userAgentAppId ?? import_node_config_provider3.loadConfig(import_util_user_agent_node.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig)
- };
-};
-
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeExtensions.js
-var import_region_config_resolver = __toESM(require_dist_cjs44(), 1);
-var import_protocol_http11 = __toESM(require_dist_cjs2(), 1);
-var import_smithy_client8 = __toESM(require_dist_cjs21(), 1);
-
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/auth/httpAuthExtensionConfiguration.js
-var getHttpAuthExtensionConfiguration = (runtimeConfig) => {
- const _httpAuthSchemes = runtimeConfig.httpAuthSchemes;
- let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider;
- let _credentials = runtimeConfig.credentials;
- return {
- setHttpAuthScheme(httpAuthScheme) {
- const index2 = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId);
- if (index2 === -1) {
- _httpAuthSchemes.push(httpAuthScheme);
- } else {
- _httpAuthSchemes.splice(index2, 1, httpAuthScheme);
+ const disconnecting = new Promise((resolve, reject) => {
+ increaseMaxListeners(client, 2);
+ client.once("end", resolve);
+ client.once("error", reject);
+ _resolve = resolve;
+ _reject = reject;
+ });
+ client.disconnect();
+ try {
+ await disconnecting;
+ } finally {
+ decreaseMaxListeners(client, 2);
+ client.removeListener("end", _resolve);
+ client.removeListener("error", _reject);
}
- },
- httpAuthSchemes() {
- return _httpAuthSchemes;
- },
- setHttpAuthSchemeProvider(httpAuthSchemeProvider) {
- _httpAuthSchemeProvider = httpAuthSchemeProvider;
- },
- httpAuthSchemeProvider() {
- return _httpAuthSchemeProvider;
- },
- setCredentials(credentials) {
- _credentials = credentials;
- },
- credentials() {
- return _credentials;
}
- };
-};
-var resolveHttpAuthRuntimeConfig = (config) => {
- return {
- httpAuthSchemes: config.httpAuthSchemes(),
- httpAuthSchemeProvider: config.httpAuthSchemeProvider(),
- credentials: config.credentials()
- };
-};
-
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeExtensions.js
-var resolveRuntimeExtensions = (runtimeConfig, extensions) => {
- const extensionConfiguration = Object.assign(import_region_config_resolver.getAwsRegionExtensionConfiguration(runtimeConfig), import_smithy_client8.getDefaultExtensionConfiguration(runtimeConfig), import_protocol_http11.getHttpHandlerExtensionConfiguration(runtimeConfig), getHttpAuthExtensionConfiguration(runtimeConfig));
- extensions.forEach((extension) => extension.configure(extensionConfiguration));
- return Object.assign(runtimeConfig, import_region_config_resolver.resolveAwsRegionExtensionConfiguration(extensionConfiguration), import_smithy_client8.resolveDefaultRuntimeConfig(extensionConfiguration), import_protocol_http11.resolveHttpHandlerRuntimeConfig(extensionConfiguration), resolveHttpAuthRuntimeConfig(extensionConfiguration));
-};
-
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/S3Client.js
-class S3Client extends import_smithy_client9.Client {
- config;
- constructor(...[configuration]) {
- const _config_0 = getRuntimeConfig2(configuration || {});
- super(_config_0);
- this.initConfig = _config_0;
- const _config_1 = resolveClientEndpointParameters(_config_0);
- const _config_2 = import_middleware_user_agent.resolveUserAgentConfig(_config_1);
- const _config_3 = resolveFlexibleChecksumsConfig(_config_2);
- const _config_4 = import_middleware_retry2.resolveRetryConfig(_config_3);
- const _config_5 = import_config_resolver2.resolveRegionConfig(_config_4);
- const _config_6 = import_middleware_host_header.resolveHostHeaderConfig(_config_5);
- const _config_7 = import_middleware_endpoint3.resolveEndpointConfig(_config_6);
- const _config_8 = resolveEventStreamSerdeConfig(_config_7);
- const _config_9 = resolveHttpAuthSchemeConfig(_config_8);
- const _config_10 = resolveS3Config(_config_9, { session: [() => this, CreateSessionCommand] });
- const _config_11 = resolveRuntimeExtensions(_config_10, configuration?.extensions || []);
- this.config = _config_11;
- this.middlewareStack.use(import_schema8.getSchemaSerdePlugin(this.config));
- this.middlewareStack.use(import_middleware_user_agent.getUserAgentPlugin(this.config));
- this.middlewareStack.use(import_middleware_retry2.getRetryPlugin(this.config));
- this.middlewareStack.use(import_middleware_content_length.getContentLengthPlugin(this.config));
- this.middlewareStack.use(import_middleware_host_header.getHostHeaderPlugin(this.config));
- this.middlewareStack.use(import_middleware_logger.getLoggerPlugin(this.config));
- this.middlewareStack.use(import_middleware_recursion_detection.getRecursionDetectionPlugin(this.config));
- this.middlewareStack.use(import_core3.getHttpAuthSchemeEndpointRuleSetPlugin(this.config, {
- httpAuthSchemeParametersProvider: defaultS3HttpAuthSchemeParametersProvider,
- identityProviderConfigProvider: async (config) => new import_core3.DefaultIdentityProviderConfig({
- "aws.auth#sigv4": config.credentials,
- "aws.auth#sigv4a": config.credentials
- })
- }));
- this.middlewareStack.use(import_core3.getHttpSigningPlugin(this.config));
- this.middlewareStack.use(getValidateBucketNamePlugin(this.config));
- this.middlewareStack.use(getAddExpectContinuePlugin(this.config));
- this.middlewareStack.use(getRegionRedirectMiddlewarePlugin(this.config));
- this.middlewareStack.use(getS3ExpressPlugin(this.config));
- this.middlewareStack.use(getS3ExpressHttpSigningPlugin(this.config));
}
- destroy() {
- super.destroy();
+ async reconnect() {
+ const client = await this.client;
+ return client.connect();
}
-}
-
-// node_modules/.pnpm/@aws-sdk+middleware-ssec@3.972.10/node_modules/@aws-sdk/middleware-ssec/dist-es/index.js
-function ssecMiddleware(options) {
- return (next) => async (args) => {
- const input = { ...args.input };
- const properties = [
- {
- target: "SSECustomerKey",
- hash: "SSECustomerKeyMD5"
- },
- {
- target: "CopySourceSSECustomerKey",
- hash: "CopySourceSSECustomerKeyMD5"
- }
- ];
- for (const prop of properties) {
- const value = input[prop.target];
- if (value) {
- let valueForHash;
- if (typeof value === "string") {
- if (isValidBase64EncodedSSECustomerKey(value, options)) {
- valueForHash = options.base64Decoder(value);
+ async close(force = false) {
+ if (!this.closing) {
+ const status = this.status;
+ this.status = "closing";
+ this.closing = true;
+ try {
+ if (status === "ready") {
+ await this.initializing;
+ }
+ if (!this.extraOptions.shared) {
+ if (status == "initializing" || force) {
+ this._client.disconnect();
} else {
- valueForHash = options.utf8Decoder(value);
- input[prop.target] = options.base64Encoder(valueForHash);
+ await this._client.quit();
}
- } else {
- valueForHash = ArrayBuffer.isView(value) ? new Uint8Array(value.buffer, value.byteOffset, value.byteLength) : new Uint8Array(value);
- input[prop.target] = options.base64Encoder(valueForHash);
+ this._client["status"] = "end";
}
- const hash4 = new options.md5;
- hash4.update(valueForHash);
- input[prop.hash] = options.base64Encoder(await hash4.digest());
+ } catch (error) {
+ if (isNotConnectionError(error)) {
+ throw error;
+ }
+ } finally {
+ this._client.off("error", this.handleClientError);
+ this._client.off("close", this.handleClientClose);
+ this._client.off("ready", this.handleClientReady);
+ decreaseMaxListeners(this._client, 3);
+ this.removeAllListeners();
+ this.status = "closed";
}
}
- return next({
- ...args,
- input
- });
- };
-}
-var ssecMiddlewareOptions = {
- name: "ssecMiddleware",
- step: "initialize",
- tags: ["SSE"],
- override: true
-};
-var getSsecPlugin = (config) => ({
- applyToStack: (clientStack) => {
- clientStack.add(ssecMiddleware(config), ssecMiddlewareOptions);
}
-});
-function isValidBase64EncodedSSECustomerKey(str, options) {
- const base64Regex = /^(?:[A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
- if (!base64Regex.test(str))
- return false;
- try {
- const decodedBytes = options.base64Decoder(str);
- return decodedBytes.length === 32;
- } catch {
- return false;
+ async getRedisVersionAndType() {
+ if (this.skipVersionCheck) {
+ return {
+ version: RedisConnection.minimumVersion,
+ databaseType: "redis"
+ };
+ }
+ const doc = await this._client.info();
+ const redisPrefix = "redis_version:";
+ const maxMemoryPolicyPrefix = "maxmemory_policy:";
+ const lines = doc.split(/\r?\n/);
+ let redisVersion;
+ let databaseType = "redis";
+ for (let i2 = 0;i2 < lines.length; i2++) {
+ const line3 = lines[i2];
+ if (line3.includes("dragonfly_version:") || line3.includes("server:Dragonfly")) {
+ databaseType = "dragonfly";
+ if (line3.indexOf("dragonfly_version:") === 0) {
+ redisVersion = line3.substr("dragonfly_version:".length);
+ }
+ } else if (line3.includes("valkey_version:") || line3.includes("server:Valkey")) {
+ databaseType = "valkey";
+ if (line3.indexOf("valkey_version:") === 0) {
+ redisVersion = line3.substr("valkey_version:".length);
+ }
+ } else if (line3.indexOf(redisPrefix) === 0) {
+ redisVersion = line3.substr(redisPrefix.length);
+ if (databaseType === "redis") {
+ databaseType = "redis";
+ }
+ }
+ if (line3.indexOf(maxMemoryPolicyPrefix) === 0) {
+ const maxMemoryPolicy = line3.substr(maxMemoryPolicyPrefix.length);
+ if (maxMemoryPolicy !== "noeviction") {
+ console.warn(`IMPORTANT! Eviction policy is ${maxMemoryPolicy}. It should be "noeviction"`);
+ }
+ }
+ }
+ if (!redisVersion) {
+ for (const line3 of lines) {
+ if (line3.includes("version:")) {
+ const parts = line3.split(":");
+ if (parts.length >= 2) {
+ redisVersion = parts[1];
+ break;
+ }
+ }
+ }
+ }
+ return {
+ version: redisVersion || RedisConnection.minimumVersion,
+ databaseType
+ };
+ }
+ get redisVersion() {
+ return this.version;
+ }
+ get databaseType() {
+ return this.dbType;
}
}
+RedisConnection.minimumVersion = "5.0.0";
+RedisConnection.recommendedMinimumVersion = "6.2.0";
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/job-scheduler.js
+var import_cron_parser = __toESM(require_parser3(), 1);
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/commands/GetObjectCommand.js
-var import_middleware_endpoint4 = __toESM(require_dist_cjs38(), 1);
-var import_smithy_client10 = __toESM(require_dist_cjs21(), 1);
-class GetObjectCommand extends import_smithy_client10.Command.classBuilder().ep({
- ...commonParams,
- Bucket: { type: "contextParams", name: "Bucket" },
- Key: { type: "contextParams", name: "Key" }
-}).m(function(Command, cs2, config, o2) {
- return [
- import_middleware_endpoint4.getEndpointPlugin(config, Command.getEndpointParameterInstructions()),
- getFlexibleChecksumsPlugin(config, {
- requestChecksumRequired: false,
- requestValidationModeMember: "ChecksumMode",
- responseAlgorithms: ["CRC64NVME", "CRC32", "CRC32C", "SHA256", "SHA1"]
- }),
- getSsecPlugin(config),
- getS3ExpiresMiddlewarePlugin(config)
- ];
-}).s("AmazonS3", "GetObject", {}).n("S3Client", "GetObjectCommand").sc(GetObject$).build() {
-}
-
-// node_modules/.pnpm/@aws-sdk+client-s3@3.1032.0/node_modules/@aws-sdk/client-s3/dist-es/commands/PutObjectCommand.js
-var import_middleware_endpoint5 = __toESM(require_dist_cjs38(), 1);
-var import_smithy_client11 = __toESM(require_dist_cjs21(), 1);
-class PutObjectCommand extends import_smithy_client11.Command.classBuilder().ep({
- ...commonParams,
- Bucket: { type: "contextParams", name: "Bucket" },
- Key: { type: "contextParams", name: "Key" }
-}).m(function(Command, cs2, config, o2) {
- return [
- import_middleware_endpoint5.getEndpointPlugin(config, Command.getEndpointParameterInstructions()),
- getFlexibleChecksumsPlugin(config, {
- requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" },
- requestChecksumRequired: false
- }),
- getCheckContentLengthHeaderPlugin(config),
- getThrow200ExceptionsPlugin(config),
- getSsecPlugin(config)
- ];
-}).s("AmazonS3", "PutObject", {}).n("S3Client", "PutObjectCommand").sc(PutObject$).build() {
-}
-
-// node_modules/.pnpm/@aws-sdk+util-format-url@3.972.10/node_modules/@aws-sdk/util-format-url/dist-es/index.js
-var import_querystring_builder = __toESM(require_dist_cjs8(), 1);
-function formatUrl(request2) {
- const { port, query } = request2;
- let { protocol, path: path2, hostname } = request2;
- if (protocol && protocol.slice(-1) !== ":") {
- protocol += ":";
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/queue-base.js
+import { EventEmitter as EventEmitter2 } from "events";
+class QueueBase extends EventEmitter2 {
+ constructor(name, opts = { connection: {} }, Connection2 = RedisConnection, hasBlockingConnection = false) {
+ super();
+ this.name = name;
+ this.opts = opts;
+ this.closed = false;
+ this.hasBlockingConnection = false;
+ this.hasBlockingConnection = hasBlockingConnection;
+ this.opts = Object.assign({ prefix: "bull" }, opts);
+ if (!name) {
+ throw new Error("Queue name must be provided");
+ }
+ if (name.includes(":")) {
+ throw new Error("Queue name cannot contain :");
+ }
+ this.connection = new Connection2(opts.connection, {
+ shared: isRedisInstance(opts.connection),
+ blocking: hasBlockingConnection,
+ skipVersionCheck: opts.skipVersionCheck,
+ skipWaitingForReady: opts.skipWaitingForReady
+ });
+ this.connection.on("error", (error) => this.emit("error", error));
+ this.connection.on("close", () => {
+ if (!this.closing) {
+ this.emit("ioredis:close");
+ }
+ });
+ const queueKeys = new QueueKeys(opts.prefix);
+ this.qualifiedName = queueKeys.getQueueQualifiedName(name);
+ this.keys = queueKeys.getKeys(name);
+ this.toKey = (type) => queueKeys.toKey(name, type);
+ this.createScripts();
}
- if (port) {
- hostname += `:${port}`;
+ get client() {
+ return this.connection.client;
}
- if (path2 && path2.charAt(0) !== "/") {
- path2 = `/${path2}`;
+ createScripts() {
+ this.scripts = createScripts(this);
}
- let queryString = query ? import_querystring_builder.buildQueryString(query) : "";
- if (queryString && queryString[0] !== "?") {
- queryString = `?${queryString}`;
+ get redisVersion() {
+ return this.connection.redisVersion;
}
- let auth = "";
- if (request2.username != null || request2.password != null) {
- const username = request2.username ?? "";
- const password = request2.password ?? "";
- auth = `${username}:${password}@`;
+ get databaseType() {
+ return this.connection.databaseType;
}
- let fragment = "";
- if (request2.fragment) {
- fragment = `#${request2.fragment}`;
+ get Job() {
+ return Job;
}
- return `${protocol}//${auth}${hostname}${path2}${queryString}${fragment}`;
-}
-
-// node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1032.0/node_modules/@aws-sdk/s3-request-presigner/dist-es/getSignedUrl.js
-var import_middleware_endpoint6 = __toESM(require_dist_cjs38(), 1);
-var import_protocol_http12 = __toESM(require_dist_cjs2(), 1);
-
-// node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1032.0/node_modules/@aws-sdk/s3-request-presigner/dist-es/constants.js
-var UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD";
-var SHA256_HEADER = "X-Amz-Content-Sha256";
-
-// node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1032.0/node_modules/@aws-sdk/s3-request-presigner/dist-es/presigner.js
-class S3RequestPresigner {
- signer;
- constructor(options) {
- const resolvedOptions = {
- service: options.signingName || options.service || "s3",
- uriEscapePath: options.uriEscapePath || false,
- applyChecksum: options.applyChecksum || false,
- ...options
- };
- this.signer = new SignatureV4MultiRegion(resolvedOptions);
+ emit(event, ...args) {
+ try {
+ return super.emit(event, ...args);
+ } catch (err) {
+ try {
+ return super.emit("error", err);
+ } catch (err2) {
+ console.error(err2);
+ return false;
+ }
+ }
}
- presign(requestToSign, { unsignableHeaders = new Set, hoistableHeaders = new Set, unhoistableHeaders = new Set, ...options } = {}) {
- this.prepareRequest(requestToSign, {
- unsignableHeaders,
- unhoistableHeaders,
- hoistableHeaders
- });
- return this.signer.presign(requestToSign, {
- expiresIn: 900,
- unsignableHeaders,
- unhoistableHeaders,
- ...options
- });
+ waitUntilReady() {
+ return this.client;
}
- presignWithCredentials(requestToSign, credentials, { unsignableHeaders = new Set, hoistableHeaders = new Set, unhoistableHeaders = new Set, ...options } = {}) {
- this.prepareRequest(requestToSign, {
- unsignableHeaders,
- unhoistableHeaders,
- hoistableHeaders
- });
- return this.signer.presignWithCredentials(requestToSign, credentials, {
- expiresIn: 900,
- unsignableHeaders,
- unhoistableHeaders,
- ...options
- });
+ base64Name() {
+ return Buffer.from(this.name).toString("base64");
}
- prepareRequest(requestToSign, { unsignableHeaders = new Set, unhoistableHeaders = new Set, hoistableHeaders = new Set } = {}) {
- unsignableHeaders.add("content-type");
- Object.keys(requestToSign.headers).map((header) => header.toLowerCase()).filter((header) => header.startsWith("x-amz-server-side-encryption")).forEach((header) => {
- if (!hoistableHeaders.has(header)) {
- unhoistableHeaders.add(header);
+ clientName(suffix = "") {
+ const queueNameBase64 = this.base64Name();
+ return `${this.opts.prefix}:${queueNameBase64}${suffix}`;
+ }
+ async close() {
+ if (!this.closing) {
+ this.closing = this.connection.close();
+ }
+ await this.closing;
+ this.closed = true;
+ }
+ disconnect() {
+ return this.connection.disconnect();
+ }
+ async checkConnectionError(fn, delayInMs = DELAY_TIME_5) {
+ try {
+ return await fn();
+ } catch (error) {
+ if (isNotConnectionError(error)) {
+ this.emit("error", error);
+ }
+ if (!this.closing && delayInMs) {
+ await delay(delayInMs);
+ } else {
+ return;
}
- });
- requestToSign.headers[SHA256_HEADER] = UNSIGNED_PAYLOAD;
- const currentHostHeader = requestToSign.headers.host;
- const port = requestToSign.port;
- const expectedHostHeader = `${requestToSign.hostname}${requestToSign.port != null ? ":" + port : ""}`;
- if (!currentHostHeader || currentHostHeader === requestToSign.hostname && requestToSign.port != null) {
- requestToSign.headers.host = expectedHostHeader;
}
}
+ trace(spanKind, operation, destination, callback, srcPropagationMetadata) {
+ return trace(this.opts.telemetry, spanKind, this.name, operation, destination, callback, srcPropagationMetadata);
+ }
}
-// node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1032.0/node_modules/@aws-sdk/s3-request-presigner/dist-es/getSignedUrl.js
-var getSignedUrl = async (client, command, options = {}) => {
- let s3Presigner;
- let region;
- if (typeof client.config.endpointProvider === "function") {
- const endpointV2 = await import_middleware_endpoint6.getEndpointFromInstructions(command.input, command.constructor, client.config);
- const authScheme = endpointV2.properties?.authSchemes?.[0];
- if (authScheme?.name === "sigv4a") {
- region = authScheme?.signingRegionSet?.join(",");
- } else {
- region = authScheme?.signingRegion;
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/job-scheduler.js
+class JobScheduler extends QueueBase {
+ constructor(name, opts, Connection2) {
+ super(name, opts, Connection2);
+ this.repeatStrategy = opts.settings && opts.settings.repeatStrategy || defaultRepeatStrategy;
+ }
+ async upsertJobScheduler(jobSchedulerId, repeatOpts, jobName, jobData, opts, { override, producerId }) {
+ const { every, limit, pattern, offset } = repeatOpts;
+ if (pattern && every) {
+ throw new Error("Both .pattern and .every options are defined for this repeatable job");
}
- s3Presigner = new S3RequestPresigner({
- ...client.config,
- signingName: authScheme?.signingName,
- region: async () => region
+ if (!pattern && !every) {
+ throw new Error("Either .pattern or .every options must be defined for this repeatable job");
+ }
+ if (repeatOpts.immediately && repeatOpts.startDate) {
+ throw new Error("Both .immediately and .startDate options are defined for this repeatable job");
+ }
+ if (repeatOpts.immediately && repeatOpts.every) {
+ console.warn("Using option immediately with every does not affect the job's schedule. Job will run immediately anyway.");
+ }
+ const iterationCount = repeatOpts.count ? repeatOpts.count + 1 : 1;
+ if (typeof repeatOpts.limit !== "undefined" && iterationCount > repeatOpts.limit) {
+ return;
+ }
+ let now = Date.now();
+ const { endDate } = repeatOpts;
+ if (endDate && now > new Date(endDate).getTime()) {
+ return;
+ }
+ const prevMillis = opts.prevMillis || 0;
+ now = prevMillis < now ? now : prevMillis;
+ const { immediately } = repeatOpts, filteredRepeatOpts = __rest(repeatOpts, ["immediately"]);
+ let nextMillis;
+ const newOffset = null;
+ if (pattern) {
+ nextMillis = await this.repeatStrategy(now, repeatOpts, jobName);
+ if (nextMillis < now) {
+ nextMillis = now;
+ }
+ }
+ if (nextMillis || every) {
+ return this.trace(SpanKind.PRODUCER, "add", `${this.name}.${jobName}`, async (span, srcPropagationMetadata) => {
+ var _a, _b;
+ let telemetry = opts.telemetry;
+ if (srcPropagationMetadata) {
+ const omitContext = (_a = opts.telemetry) === null || _a === undefined ? undefined : _a.omitContext;
+ const telemetryMetadata = ((_b = opts.telemetry) === null || _b === undefined ? undefined : _b.metadata) || !omitContext && srcPropagationMetadata;
+ if (telemetryMetadata || omitContext) {
+ telemetry = {
+ metadata: telemetryMetadata,
+ omitContext
+ };
+ }
+ }
+ const mergedOpts = this.getNextJobOpts(nextMillis, jobSchedulerId, Object.assign(Object.assign({}, opts), { repeat: filteredRepeatOpts, telemetry }), iterationCount, newOffset);
+ if (override) {
+ if (nextMillis < now) {
+ nextMillis = now;
+ }
+ const [jobId, delay2] = await this.scripts.addJobScheduler(jobSchedulerId, nextMillis, JSON.stringify(typeof jobData === "undefined" ? {} : jobData), Job.optsAsJSON(opts), {
+ name: jobName,
+ startDate: repeatOpts.startDate ? new Date(repeatOpts.startDate).getTime() : undefined,
+ endDate: endDate ? new Date(endDate).getTime() : undefined,
+ tz: repeatOpts.tz,
+ pattern,
+ every,
+ limit,
+ offset: newOffset
+ }, Job.optsAsJSON(mergedOpts), producerId);
+ const numericDelay = typeof delay2 === "string" ? parseInt(delay2, 10) : delay2;
+ const job = new this.Job(this, jobName, jobData, Object.assign(Object.assign({}, mergedOpts), { delay: numericDelay }), jobId);
+ job.id = jobId;
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.JobSchedulerId]: jobSchedulerId,
+ [TelemetryAttributes.JobId]: job.id
+ });
+ return job;
+ } else {
+ const jobId = await this.scripts.updateJobSchedulerNextMillis(jobSchedulerId, nextMillis, JSON.stringify(typeof jobData === "undefined" ? {} : jobData), Job.optsAsJSON(mergedOpts), producerId);
+ if (jobId) {
+ const job = new this.Job(this, jobName, jobData, mergedOpts, jobId);
+ job.id = jobId;
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.JobSchedulerId]: jobSchedulerId,
+ [TelemetryAttributes.JobId]: job.id
+ });
+ return job;
+ }
+ }
+ });
+ }
+ }
+ getNextJobOpts(nextMillis, jobSchedulerId, opts, currentCount, offset) {
+ var _a, _b;
+ const jobId = this.getSchedulerNextJobId({
+ jobSchedulerId,
+ nextMillis
});
- } else {
- s3Presigner = new S3RequestPresigner(client.config);
+ const now = Date.now();
+ const delay2 = nextMillis + offset - now;
+ const mergedOpts = Object.assign(Object.assign({}, opts), { jobId, delay: delay2 < 0 ? 0 : delay2, timestamp: now, prevMillis: nextMillis, repeatJobKey: jobSchedulerId });
+ mergedOpts.repeat = Object.assign(Object.assign({}, opts.repeat), { offset, count: currentCount, startDate: ((_a = opts.repeat) === null || _a === undefined ? undefined : _a.startDate) ? new Date(opts.repeat.startDate).getTime() : undefined, endDate: ((_b = opts.repeat) === null || _b === undefined ? undefined : _b.endDate) ? new Date(opts.repeat.endDate).getTime() : undefined });
+ return mergedOpts;
}
- const presignInterceptMiddleware = (next, context) => async (args) => {
- const { request: request2 } = args;
- if (!import_protocol_http12.HttpRequest.isInstance(request2)) {
- throw new Error("Request to be presigned is not an valid HTTP request.");
+ async removeJobScheduler(jobSchedulerId) {
+ return this.scripts.removeJobScheduler(jobSchedulerId);
+ }
+ async getSchedulerData(client, key, next) {
+ const jobData = await client.hgetall(this.toKey("repeat:" + key));
+ return this.transformSchedulerData(key, jobData, next);
+ }
+ transformSchedulerData(key, jobData, next) {
+ if (jobData && Object.keys(jobData).length > 0) {
+ const jobSchedulerData = {
+ key,
+ name: jobData.name,
+ next
+ };
+ if (jobData.ic) {
+ jobSchedulerData.iterationCount = parseInt(jobData.ic);
+ }
+ if (jobData.limit) {
+ jobSchedulerData.limit = parseInt(jobData.limit);
+ }
+ if (jobData.startDate) {
+ jobSchedulerData.startDate = parseInt(jobData.startDate);
+ }
+ if (jobData.endDate) {
+ jobSchedulerData.endDate = parseInt(jobData.endDate);
+ }
+ if (jobData.tz) {
+ jobSchedulerData.tz = jobData.tz;
+ }
+ if (jobData.pattern) {
+ jobSchedulerData.pattern = jobData.pattern;
+ }
+ if (jobData.every) {
+ jobSchedulerData.every = parseInt(jobData.every);
+ }
+ if (jobData.offset) {
+ jobSchedulerData.offset = parseInt(jobData.offset);
+ }
+ if (jobData.data || jobData.opts) {
+ jobSchedulerData.template = this.getTemplateFromJSON(jobData.data, jobData.opts);
+ }
+ return jobSchedulerData;
}
- delete request2.headers["amz-sdk-invocation-id"];
- delete request2.headers["amz-sdk-request"];
- delete request2.headers["x-amz-user-agent"];
- let presigned2;
- const presignerOptions = {
- ...options,
- signingRegion: options.signingRegion ?? context["signing_region"] ?? region,
- signingService: options.signingService ?? context["signing_service"]
- };
- if (context.s3ExpressIdentity) {
- presigned2 = await s3Presigner.presignWithCredentials(request2, context.s3ExpressIdentity, presignerOptions);
- } else {
- presigned2 = await s3Presigner.presign(request2, presignerOptions);
+ if (key.includes(":")) {
+ return this.keyToData(key, next);
}
- return {
- response: {},
- output: {
- $metadata: { httpStatusCode: 200 },
- presigned: presigned2
- }
- };
- };
- const middlewareName = "presignInterceptMiddleware";
- const clientStack = client.middlewareStack.clone();
- clientStack.addRelativeTo(presignInterceptMiddleware, {
- name: middlewareName,
- relation: "before",
- toMiddleware: "awsAuthMiddleware",
- override: true
- });
- const handler = command.resolveMiddleware(clientStack, client.config, {});
- const { output } = await handler({ input: command.input });
- const { presigned } = output;
- return formatUrl(presigned);
-};
-
-// src/config/index.js
-var import_dotenv2 = __toESM(require_main(), 1);
-import_dotenv2.default.config({});
-var envSchema2 = create$3({
- API_VERSION: create$6().required(),
- ACCESS_TOKEN_EXPIRY: create$6().required(),
- ACCESS_TOKEN_SECRET: create$6().required(),
- REFRESH_TOKEN_EXPIRY: create$6().required(),
- REFRESH_TOKEN_SECRET: create$6().required(),
- PORT: create$5().default(5000),
- DATABASE_URL: create$6().required(),
- MONGO_URI: create$6().required(),
- CLIENT_URL: create$6().required(),
- VITE_API_URL: create$6().required(),
- AWS_ACCESS_KEY_ID: create$6().required(),
- AWS_SECRET_ACCESS_KEY: create$6().required(),
- AWS_REGION: create$6().required(),
- AWS_BUCKET_NAME: create$6().required(),
- CLOUDINARY_API_KEY: create$6().required(),
- CLOUDINARY_API_SECRET: create$6().required(),
- GOOGLE_CLIENT_ID: create$6().required(),
- GOOGLE_CLIENT_SECRET: create$6().required(),
- GOOGLE_CALLBACK_URL: create$6().required(),
- GEMINI_API_KEY: create$6().required(),
- MURF_API_KEY: create$6().required(),
- REDIS_HOST: create$6().required(),
- REDIS_PORT: create$5().required(),
- REDIS_URL: create$6().required(),
- REDIS_USER: create$6().required(),
- ALLOWED_ORIGINS: create$6().required(),
- SMTP_VERIFY_URL: create$6().required(),
- EMAIL_FROM: create$6().required(),
- EMAIL_HOST: create$6().required(),
- EMAIL_PORT: create$5().required(),
- EMAIL_USER: create$6().required(),
- EMAIL_PASS: create$6().required(),
- IDEMPOTENCY_SUBMIT_TTL_SEC: create$5().required()
-});
-var parsedEnv2 = envSchema2.validateSync(process.env, {
- abortEarly: false,
- stripUnknown: true
-});
-var env2 = parsedEnv2;
-var config_default2 = env2;
-
-// src/services/aws.service.js
-var s3Client = new S3Client({
- region: config_default2.AWS_REGION,
- credentials: {
- accessKeyId: config_default2.AWS_ACCESS_KEY_ID,
- secretAccessKey: config_default2.AWS_SECRET_ACCESS_KEY
}
-});
-async function generateUploadURL(key, filename) {
- const params = new PutObjectCommand({
- Bucket: config_default2.AWS_BUCKET_NAME,
- Key: `${key}/${filename}`,
- ContentType: "application/json"
- });
- const url = await getSignedUrl(s3Client, params, { expiresIn: 3600 });
- return url;
-}
-var streamToString = (stream) => new Promise((resolve, reject) => {
- const chunks = [];
- stream.on("data", (chunk) => chunks.push(chunk));
- stream.on("error", reject);
- stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
-});
-async function fetchTestcasesFromS3(s3Key) {
+ keyToData(key, next) {
+ const data = key.split(":");
+ const pattern = data.slice(4).join(":") || null;
+ return {
+ key,
+ name: data[0],
+ id: data[1] || null,
+ endDate: parseInt(data[2]) || null,
+ tz: data[3] || null,
+ pattern,
+ next
+ };
+ }
+ async isJobScheduler(id) {
+ const client = await this.client;
+ const exists2 = await client.hexists(`${this.keys.repeat}:${id}`, "ic");
+ return exists2 === 1;
+ }
+ async getScheduler(id) {
+ const [rawJobData, next] = await this.scripts.getJobScheduler(id);
+ return this.transformSchedulerData(id, rawJobData ? array2obj(rawJobData) : null, next ? parseInt(next) : null);
+ }
+ getTemplateFromJSON(rawData, rawOpts) {
+ const template = {};
+ if (rawData) {
+ template.data = JSON.parse(rawData);
+ }
+ if (rawOpts) {
+ template.opts = Job.optsFromJSON(rawOpts);
+ }
+ return template;
+ }
+ async getJobSchedulers(start = 0, end = -1, asc2 = false) {
+ const client = await this.client;
+ const jobSchedulersKey = this.keys.repeat;
+ const result = asc2 ? await client.zrange(jobSchedulersKey, start, end, "WITHSCORES") : await client.zrevrange(jobSchedulersKey, start, end, "WITHSCORES");
+ const jobs = [];
+ for (let i2 = 0;i2 < result.length; i2 += 2) {
+ jobs.push(this.getSchedulerData(client, result[i2], parseInt(result[i2 + 1])));
+ }
+ return Promise.all(jobs);
+ }
+ async getSchedulersCount() {
+ const jobSchedulersKey = this.keys.repeat;
+ const client = await this.client;
+ return client.zcard(jobSchedulersKey);
+ }
+ getSchedulerNextJobId({ nextMillis, jobSchedulerId }) {
+ return `repeat:${jobSchedulerId}:${nextMillis}`;
+ }
+}
+var defaultRepeatStrategy = (millis, opts) => {
+ const { pattern } = opts;
+ const dateFromMillis = new Date(millis);
+ const startDate = opts.startDate && new Date(opts.startDate);
+ const currentDate = startDate > dateFromMillis ? startDate : dateFromMillis;
+ const interval3 = import_cron_parser.parseExpression(pattern, Object.assign(Object.assign({}, opts), { currentDate }));
try {
- const command = new GetObjectCommand({
- Bucket: config_default2.AWS_BUCKET_NAME,
- Key: s3Key
+ if (opts.immediately) {
+ return new Date().getTime();
+ } else {
+ return interval3.next().getTime();
+ }
+ } catch (e3) {}
+};
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/queue-getters.js
+class QueueGetters extends QueueBase {
+ getJob(jobId) {
+ return this.Job.fromId(this, jobId);
+ }
+ commandByType(types6, count2, callback) {
+ return types6.map((type) => {
+ type = type === "waiting" ? "wait" : type;
+ const key = this.toKey(type);
+ switch (type) {
+ case "completed":
+ case "failed":
+ case "delayed":
+ case "prioritized":
+ case "repeat":
+ case "waiting-children":
+ return callback(key, count2 ? "zcard" : "zrange");
+ case "active":
+ case "wait":
+ case "paused":
+ return callback(key, count2 ? "llen" : "lrange");
+ }
});
- const response = await s3Client.send(command);
- const jsonString = await streamToString(response.Body);
- const data = JSON.parse(jsonString);
- return data;
- } catch (err) {
- console.error("Error fetching testcases:", err);
- return null;
}
-}
-async function fetchFileFromS3(s3Key) {
- try {
- const command = new GetObjectCommand({
- Bucket: config_default2.AWS_BUCKET_NAME,
- Key: s3Key
- });
- const response = await s3Client.send(command);
- const text2 = await streamToString(response.Body);
- return text2;
- } catch (err) {
- console.error("Error fetching file from S3:", err);
+ sanitizeJobTypes(types6) {
+ const currentTypes = typeof types6 === "string" ? [types6] : types6;
+ if (Array.isArray(currentTypes) && currentTypes.length > 0) {
+ const sanitizedTypes = [...currentTypes];
+ if (sanitizedTypes.indexOf("waiting") !== -1) {
+ sanitizedTypes.push("paused");
+ }
+ return [...new Set(sanitizedTypes)];
+ }
+ return [
+ "active",
+ "completed",
+ "delayed",
+ "failed",
+ "paused",
+ "prioritized",
+ "waiting",
+ "waiting-children"
+ ];
+ }
+ async count() {
+ const count2 = await this.getJobCountByTypes("waiting", "paused", "delayed", "prioritized", "waiting-children");
+ return count2;
+ }
+ async getRateLimitTtl(maxJobs) {
+ return this.scripts.getRateLimitTtl(maxJobs);
+ }
+ async getDebounceJobId(id) {
+ const client = await this.client;
+ return client.get(`${this.keys.de}:${id}`);
+ }
+ async getDeduplicationJobId(id) {
+ const client = await this.client;
+ return client.get(`${this.keys.de}:${id}`);
+ }
+ async getGlobalConcurrency() {
+ const client = await this.client;
+ const concurrency = await client.hget(this.keys.meta, "concurrency");
+ if (concurrency) {
+ return Number(concurrency);
+ }
return null;
}
-}
-
-// src/api/problem/problem-service.ts
-var handleCreateProblem = async (userId, input) => {
- await verifyProblemCreationPermission(userId);
- try {
- const existingProblem = await db.select().from(problem).where(eq(problem.slug, input.slug));
- if (existingProblem.length > 0) {
- throw new ApiError_default("Problem already exists", E.BAD_REQUEST);
+ async getGlobalRateLimit() {
+ const client = await this.client;
+ const [max, duration] = await client.hmget(this.keys.meta, "max", "duration");
+ if (max && duration) {
+ return {
+ max: Number(max),
+ duration: Number(duration)
+ };
}
- const problemId = createId();
- const key = `problems/${problemId}`;
- const testcasePromises = Array.from({ length: input.testcases }).map((_, i2) => {
- const fileName = `testcase_${i2}.json`;
- return generateUploadURL(key, fileName).then((url) => ({
- url,
- fileName,
- order: i2,
- isSample: false,
- isHidden: i2 >= Math.min(3, input.testcases)
- }));
- });
- const samplePromises = Array.from({ length: input.sampleTestcases }).map((_, i2) => {
- const fileName = `sampleTestcase_${i2}.json`;
- return generateUploadURL(key, fileName).then((url) => ({
- url,
- fileName,
- order: i2,
- isSample: true,
- isHidden: false
- }));
+ return null;
+ }
+ async getJobCountByTypes(...types6) {
+ const result = await this.getJobCounts(...types6);
+ return Object.values(result).reduce((sum, count2) => sum + count2, 0);
+ }
+ async getJobCounts(...types6) {
+ const currentTypes = this.sanitizeJobTypes(types6);
+ const responses = await this.scripts.getCounts(currentTypes);
+ const counts = {};
+ responses.forEach((res, index3) => {
+ counts[currentTypes[index3]] = res || 0;
});
- const allTestData = await Promise.all([...testcasePromises, ...samplePromises]);
- const uploadUrls = allTestData.map((d2) => d2.url);
- await db.transaction(async (tx) => {
- await tx.insert(problem).values({
- id: problemId,
- title: input.title,
- description: input.description,
- slug: input.slug,
- difficulty: input.difficulty,
- authorId: userId,
- inputFormat: input.inputFormat,
- outputFormat: input.outputFormat,
- constraints: input.constraints,
- timeLimit: input.timeLimit,
- memoryLimit: input.memoryLimit
- });
- await tx.insert(editorial).values({
- problemId,
- contentS3Key: `${key}/content.md`,
- solutionS3Key: `${key}/solution.md`,
- editorialLink: input.editorialLink
- });
- if (input.tags && input.tags.length > 0) {
- const uniqueTagNames = [...new Set(input.tags)];
- const tagIds = [];
- for (const tagName of uniqueTagNames) {
- const insertedTag = await tx.insert(tag).values({ name: tagName }).onConflictDoUpdate({
- target: tag.name,
- set: { name: tagName }
- }).returning({ id: tag.id });
- tagIds.push(insertedTag[0].id);
- }
- if (tagIds.length > 0) {
- await tx.insert(problemTag).values(tagIds.map((tagId) => ({
- problemId,
- tagId
- }))).onConflictDoNothing();
- }
- }
- if (allTestData.length > 0) {
- await tx.insert(testcase).values(allTestData.map((td) => ({
- problemId,
- order: td.order,
- isHidden: td.isHidden,
- s3Key: `${key}/${td.fileName}`,
- isSample: td.isSample
- })));
+ return counts;
+ }
+ async recordJobCountsMetric(...types6) {
+ var _a;
+ const counts = await this.getJobCounts(...types6);
+ const meter = (_a = this.opts.telemetry) === null || _a === undefined ? undefined : _a.meter;
+ if (meter && typeof meter.createGauge === "function") {
+ const gauge = meter.createGauge(MetricNames.QueueJobsCount, {
+ description: "Number of jobs in the queue by state",
+ unit: "{jobs}"
+ });
+ for (const [state, jobCount] of Object.entries(counts)) {
+ gauge.record(jobCount, {
+ [TelemetryAttributes.QueueName]: this.name,
+ [TelemetryAttributes.QueueJobsState]: state
+ });
}
- });
- return {
- message: "Problem created successfully",
- problemId,
- uploadUrls,
- uploadContentUrl: await generateUploadURL(key, "content.md"),
- uploadSolutionUrl: await generateUploadURL(key, "solution.md")
- };
- } catch (error) {
- if (error instanceof ApiError_default) {
- throw error;
}
- console.error("Error creating problem:", error);
- throw new ApiError_default("Failed to create problem", E.INTERNAL_SERVER_ERROR);
+ return counts;
}
-};
-var handleFinalizeProblem = async (userId, problemId) => {
- try {
- const problemResult = await db.select().from(problem).where(eq(problem.id, problemId));
- if (problemResult.length === 0) {
- throw new ApiError_default("Problem not found", E.NOT_FOUND);
- }
- if (problemResult[0].authorId !== userId) {
- throw new ApiError_default("You do not have permission to finalize this problem", E.FORBIDDEN);
+ getJobState(jobId) {
+ return this.scripts.getState(jobId);
+ }
+ async getMeta() {
+ const client = await this.client;
+ const config = await client.hgetall(this.keys.meta);
+ const { concurrency, max, duration, paused, "opts.maxLenEvents": maxLenEvents } = config, rest = __rest(config, ["concurrency", "max", "duration", "paused", "opts.maxLenEvents"]);
+ const parsedConfig = rest;
+ if (concurrency) {
+ parsedConfig["concurrency"] = Number(concurrency);
}
- const testcasesResult = await db.select().from(testcase).where(eq(testcase.problemId, problemId));
- if (testcasesResult.length === 0) {
- throw new ApiError_default("No testcases found. Please upload testcases before finalizing.", E.BAD_REQUEST);
+ if (maxLenEvents) {
+ parsedConfig["maxLenEvents"] = Number(maxLenEvents);
}
- const sampleTestcases = testcasesResult.filter((tc) => tc.isSample);
- const hiddenTestcases = testcasesResult.filter((tc) => !tc.isSample);
- if (sampleTestcases.length === 0) {
- throw new ApiError_default("At least one sample testcase is required.", E.BAD_REQUEST);
+ if (max) {
+ parsedConfig["max"] = Number(max);
}
- if (hiddenTestcases.length === 0) {
- throw new ApiError_default("At least one hidden testcase is required.", E.BAD_REQUEST);
+ if (duration) {
+ parsedConfig["duration"] = Number(duration);
}
- await Promise.all(testcasesResult.map(async (tc) => {
- const response = await fetchTestcasesFromS3(tc.s3Key);
- if (!response) {
- throw new ApiError_default(`Testcase file not found in storage: ${tc.s3Key}`, E.BAD_REQUEST);
+ parsedConfig["paused"] = paused === "1";
+ return parsedConfig;
+ }
+ getCompletedCount() {
+ return this.getJobCountByTypes("completed");
+ }
+ getFailedCount() {
+ return this.getJobCountByTypes("failed");
+ }
+ getDelayedCount() {
+ return this.getJobCountByTypes("delayed");
+ }
+ getActiveCount() {
+ return this.getJobCountByTypes("active");
+ }
+ getPrioritizedCount() {
+ return this.getJobCountByTypes("prioritized");
+ }
+ async getCountsPerPriority(priorities) {
+ const uniquePriorities = [...new Set(priorities)];
+ const responses = await this.scripts.getCountsPerPriority(uniquePriorities);
+ const counts = {};
+ responses.forEach((res, index3) => {
+ counts[`${uniquePriorities[index3]}`] = res || 0;
+ });
+ return counts;
+ }
+ getWaitingCount() {
+ return this.getJobCountByTypes("waiting");
+ }
+ getWaitingChildrenCount() {
+ return this.getJobCountByTypes("waiting-children");
+ }
+ getWaiting(start = 0, end = -1) {
+ return this.getJobs(["waiting"], start, end, true);
+ }
+ getWaitingChildren(start = 0, end = -1) {
+ return this.getJobs(["waiting-children"], start, end, true);
+ }
+ getActive(start = 0, end = -1) {
+ return this.getJobs(["active"], start, end, true);
+ }
+ getDelayed(start = 0, end = -1) {
+ return this.getJobs(["delayed"], start, end, true);
+ }
+ getPrioritized(start = 0, end = -1) {
+ return this.getJobs(["prioritized"], start, end, true);
+ }
+ getCompleted(start = 0, end = -1) {
+ return this.getJobs(["completed"], start, end, false);
+ }
+ getFailed(start = 0, end = -1) {
+ return this.getJobs(["failed"], start, end, false);
+ }
+ async getDependencies(parentId, type, start, end) {
+ const key = this.toKey(type == "processed" ? `${parentId}:processed` : `${parentId}:dependencies`);
+ const { items, total, jobs } = await this.scripts.paginate(key, {
+ start,
+ end,
+ fetchJobs: true
+ });
+ return {
+ items,
+ jobs,
+ total
+ };
+ }
+ async getRanges(types6, start = 0, end = 1, asc2 = false) {
+ const multiCommands = [];
+ this.commandByType(types6, false, (key, command) => {
+ switch (command) {
+ case "lrange":
+ multiCommands.push("lrange");
+ break;
+ case "zrange":
+ multiCommands.push("zrange");
+ break;
}
- }));
- const editorialResult = await db.select({
- solutionS3Key: editorial.solutionS3Key,
- contentS3Key: editorial.contentS3Key
- }).from(editorial).where(eq(editorial.problemId, problemId)).limit(1);
- if (editorialResult.length === 0) {
- throw new ApiError_default("Editorial not found. Please upload editorial before finalizing.", E.BAD_REQUEST);
- }
- const editorialData = editorialResult[0];
- const contentResponse = await fetchTestcasesFromS3(editorialData.contentS3Key);
- if (!contentResponse) {
- throw new ApiError_default("Content file not found in storage: /content.md", E.BAD_REQUEST);
+ });
+ const responses = await this.scripts.getRanges(types6, start, end, asc2);
+ let results = [];
+ responses.forEach((response, index3) => {
+ const result = response || [];
+ if (asc2 && multiCommands[index3] === "lrange") {
+ results = results.concat(result.reverse());
+ } else {
+ results = results.concat(result);
+ }
+ });
+ return [...new Set(results)];
+ }
+ async getJobs(types6, start = 0, end = -1, asc2 = false) {
+ const currentTypes = this.sanitizeJobTypes(types6);
+ const jobIds = await this.getRanges(currentTypes, start, end, asc2);
+ return Promise.all(jobIds.map((jobId) => this.Job.fromId(this, jobId)));
+ }
+ async getJobLogs(jobId, start = 0, end = -1, asc2 = true) {
+ const client = await this.client;
+ const multi = client.multi();
+ const logsKey = this.toKey(jobId + ":logs");
+ if (asc2) {
+ multi.lrange(logsKey, start, end);
+ } else {
+ multi.lrange(logsKey, -(end + 1), -(start + 1));
}
- const solutionResponse = await fetchTestcasesFromS3(editorialData.solutionS3Key);
- if (!solutionResponse) {
- throw new ApiError_default("Solution file not found in storage: /solution.md", E.BAD_REQUEST);
+ multi.llen(logsKey);
+ const result = await multi.exec();
+ if (!asc2) {
+ result[0][1].reverse();
}
- await db.update(problem).set({
- status: "DONE"
- }).where(eq(problem.id, problemId));
return {
- message: "Problem finalized successfully",
- status: true
+ logs: result[0][1],
+ count: result[1][1]
};
- } catch (error) {
- if (error instanceof ApiError_default) {
- throw error;
- }
- console.error("Error finalizing problem:", error);
- throw new ApiError_default("Failed to finalize problem", E.INTERNAL_SERVER_ERROR);
}
-};
-var handleGetProblems = async (input) => {
- try {
- let cursorCreatedAt = null;
- let cursorId = null;
- if (input.cursor) {
- try {
- const decoded = Buffer.from(input.cursor, "base64").toString("utf-8");
- const [timeStr, id] = decoded.split(":");
- cursorCreatedAt = new Date(parseInt(timeStr));
- cursorId = id;
- } catch (e3) {
- throw new ApiError_default("Invalid cursor", E.BAD_REQUEST);
+ async baseGetClients(matcher) {
+ const client = await this.client;
+ try {
+ if (client.isCluster) {
+ const clusterNodes = client.nodes();
+ const clientsPerNode = [];
+ for (let nodeIndex = 0;nodeIndex < clusterNodes.length; nodeIndex++) {
+ const node = clusterNodes[nodeIndex];
+ const clients = await node.client("LIST");
+ const list = this.parseClientList(clients, matcher);
+ clientsPerNode.push(list);
+ }
+ const clientsFromNodeWithMostConnections = clientsPerNode.reduce((prev, current) => {
+ return prev.length > current.length ? prev : current;
+ }, []);
+ return clientsFromNodeWithMostConnections;
+ } else {
+ const clients = await client.client("LIST");
+ const list = this.parseClientList(clients, matcher);
+ return list;
+ }
+ } catch (err) {
+ if (!clientCommandMessageReg.test(err.message)) {
+ throw err;
}
+ return [{ name: "GCP does not support client list" }];
}
- const problemsResult = await db.select({
- id: problem.id,
- title: problem.title,
- description: problem.description,
- slug: problem.slug,
- difficulty: problem.difficulty,
- createdAt: problem.createdAt,
- updatedAt: problem.updatedAt
- }).from(problem).where(and(eq(problem.status, "DONE"), cursorCreatedAt && cursorId ? or(lt(problem.createdAt, cursorCreatedAt), and(eq(problem.createdAt, cursorCreatedAt), lt(problem.id, cursorId))) : undefined)).limit(input.limit + 1).orderBy(desc(problem.createdAt), desc(problem.id));
- const hasNextPage = problemsResult.length > input.limit;
- const problems = hasNextPage ? problemsResult.slice(0, input.limit) : problemsResult;
- let nextCursor = null;
- if (hasNextPage && problems.length > 0) {
- const lastProblem = problems[problems.length - 1];
- const time2 = lastProblem.createdAt.getTime();
- nextCursor = Buffer.from(`${time2}:${lastProblem.id}`).toString("base64");
+ }
+ getWorkers() {
+ const unnamedWorkerClientName = `${this.clientName()}`;
+ const namedWorkerClientName = `${this.clientName()}:w:`;
+ const matcher = (name) => name && (name === unnamedWorkerClientName || name.startsWith(namedWorkerClientName));
+ return this.baseGetClients(matcher);
+ }
+ async getWorkersCount() {
+ const workers = await this.getWorkers();
+ return workers.length;
+ }
+ async getQueueEvents() {
+ const clientName = `${this.clientName()}${QUEUE_EVENT_SUFFIX}`;
+ return this.baseGetClients((name) => name === clientName);
+ }
+ async getMetrics(type, start = 0, end = -1) {
+ const [meta, data, count2] = await this.scripts.getMetrics(type, start, end);
+ return {
+ meta: {
+ count: parseInt(meta[0] || "0", 10),
+ prevTS: parseInt(meta[1] || "0", 10),
+ prevCount: parseInt(meta[2] || "0", 10)
+ },
+ data: data.map((point3) => +point3 || 0),
+ count: count2
+ };
+ }
+ parseClientList(list, matcher) {
+ const lines = list.split(/\r?\n/);
+ const clients = [];
+ lines.forEach((line3) => {
+ const client = {};
+ const keyValues = line3.split(" ");
+ keyValues.forEach(function(keyValue) {
+ const index3 = keyValue.indexOf("=");
+ const key = keyValue.substring(0, index3);
+ const value = keyValue.substring(index3 + 1);
+ client[key] = value;
+ });
+ const name = client["name"];
+ if (matcher(name)) {
+ client["name"] = this.name;
+ client["rawname"] = name;
+ clients.push(client);
+ }
+ });
+ return clients;
+ }
+ async exportPrometheusMetrics(globalVariables) {
+ const counts = await this.getJobCounts();
+ const metrics = [];
+ metrics.push("# HELP bullmq_job_count Number of jobs in the queue by state");
+ metrics.push("# TYPE bullmq_job_count gauge");
+ const variables = !globalVariables ? "" : Object.keys(globalVariables).reduce((acc, curr) => `${acc}, ${curr}="${globalVariables[curr]}"`, "");
+ for (const [state, count2] of Object.entries(counts)) {
+ metrics.push(`bullmq_job_count{queue="${this.name}", state="${state}"${variables}} ${count2}`);
+ }
+ return metrics.join(`
+`);
+ }
+}
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/repeat.js
+var import_cron_parser2 = __toESM(require_parser3(), 1);
+import { createHash as createHash2 } from "crypto";
+class Repeat extends QueueBase {
+ constructor(name, opts, Connection2) {
+ super(name, opts, Connection2);
+ this.repeatStrategy = opts.settings && opts.settings.repeatStrategy || getNextMillis;
+ this.repeatKeyHashAlgorithm = opts.settings && opts.settings.repeatKeyHashAlgorithm || "md5";
+ }
+ async updateRepeatableJob(name, data, opts, { override }) {
+ var _a, _b;
+ const repeatOpts = Object.assign({}, opts.repeat);
+ (_a = repeatOpts.pattern) !== null && _a !== undefined || (repeatOpts.pattern = repeatOpts.cron);
+ delete repeatOpts.cron;
+ const iterationCount = repeatOpts.count ? repeatOpts.count + 1 : 1;
+ if (typeof repeatOpts.limit !== "undefined" && iterationCount > repeatOpts.limit) {
+ return;
}
- if (problems.length === 0) {
- return { problems: [], nextCursor: null };
+ let now = Date.now();
+ const { endDate } = repeatOpts;
+ if (endDate && now > new Date(endDate).getTime()) {
+ return;
}
- const problemIds = problems.map((p2) => p2.id);
- const tagsResult = await db.select({
- problemId: problemTag.problemId,
- tagName: tag.name
- }).from(problemTag).innerJoin(tag, eq(problemTag.tagId, tag.id)).where(inArray(problemTag.problemId, problemIds));
- const assembledProblems = problems.map((p2) => {
- const pTags = tagsResult.filter((t9) => t9.problemId === p2.id).map((t9) => t9.tagName);
- return {
- ...p2,
- tags: pTags
- };
- });
- return {
- problems: assembledProblems,
- nextCursor
- };
- } catch (error) {
- if (error instanceof ApiError_default) {
- throw error;
+ const prevMillis = opts.prevMillis || 0;
+ now = prevMillis < now ? now : prevMillis;
+ const nextMillis = await this.repeatStrategy(now, repeatOpts, name);
+ const { every, pattern } = repeatOpts;
+ const hasImmediately = Boolean((every || pattern) && repeatOpts.immediately);
+ const offset = hasImmediately && every ? now - nextMillis : undefined;
+ if (nextMillis) {
+ if (!prevMillis && opts.jobId) {
+ repeatOpts.jobId = opts.jobId;
+ }
+ const legacyRepeatKey = getRepeatConcatOptions(name, repeatOpts);
+ const newRepeatKey = (_b = opts.repeat.key) !== null && _b !== undefined ? _b : this.hash(legacyRepeatKey);
+ let repeatJobKey;
+ if (override) {
+ repeatJobKey = await this.scripts.addRepeatableJob(newRepeatKey, nextMillis, {
+ name,
+ endDate: endDate ? new Date(endDate).getTime() : undefined,
+ tz: repeatOpts.tz,
+ pattern,
+ every
+ }, legacyRepeatKey);
+ } else {
+ const client = await this.client;
+ repeatJobKey = await this.scripts.updateRepeatableJobMillis(client, newRepeatKey, nextMillis, legacyRepeatKey);
+ }
+ const { immediately } = repeatOpts, filteredRepeatOpts = __rest(repeatOpts, ["immediately"]);
+ return this.createNextJob(name, nextMillis, repeatJobKey, Object.assign(Object.assign({}, opts), { repeat: Object.assign({ offset }, filteredRepeatOpts) }), data, iterationCount, hasImmediately);
}
- console.error("Error fetching problems:", error);
- throw new ApiError_default("Failed to fetch problems", E.INTERNAL_SERVER_ERROR);
}
-};
-var handleGetProblemById = async (problemId) => {
- try {
- const problemResult = await db.select().from(problem).where(and(eq(problem.id, problemId), eq(problem.status, "DONE"))).limit(1);
- if (problemResult.length === 0) {
- throw new ApiError_default("Problem not found", E.NOT_FOUND);
+ async createNextJob(name, nextMillis, repeatJobKey, opts, data, currentCount, hasImmediately) {
+ const jobId = this.getRepeatJobKey(name, nextMillis, repeatJobKey, data);
+ const now = Date.now();
+ const delay2 = nextMillis + (opts.repeat.offset ? opts.repeat.offset : 0) - now;
+ const mergedOpts = Object.assign(Object.assign({}, opts), { jobId, delay: delay2 < 0 || hasImmediately ? 0 : delay2, timestamp: now, prevMillis: nextMillis, repeatJobKey });
+ mergedOpts.repeat = Object.assign(Object.assign({}, opts.repeat), { count: currentCount });
+ return this.Job.create(this, name, data, mergedOpts);
+ }
+ getRepeatJobKey(name, nextMillis, repeatJobKey, data) {
+ if (repeatJobKey.split(":").length > 2) {
+ return this.getRepeatJobId({
+ name,
+ nextMillis,
+ namespace: this.hash(repeatJobKey),
+ jobId: data === null || data === undefined ? undefined : data.id
+ });
}
- const p2 = problemResult[0];
- const tagsResult = await db.select({
- tagName: tag.name
- }).from(problemTag).innerJoin(tag, eq(problemTag.tagId, tag.id)).where(eq(problemTag.problemId, problemId));
- const testcasesResult = await db.select({
- id: testcase.id,
- order: testcase.order,
- s3Key: testcase.s3Key
- }).from(testcase).where(and(eq(testcase.problemId, problemId), eq(testcase.isSample, true)));
- const sampleTestcases = await Promise.all(testcasesResult.map(async (tc) => {
- const response = await fetchTestcasesFromS3(tc.s3Key);
- if (!response) {
- throw new ApiError_default("Testcase file not found: " + tc.s3Key, E.INTERNAL_SERVER_ERROR);
- }
+ return this.getRepeatDelayedJobId({
+ customKey: repeatJobKey,
+ nextMillis
+ });
+ }
+ async removeRepeatable(name, repeat, jobId) {
+ var _a;
+ const repeatConcatOptions = getRepeatConcatOptions(name, Object.assign(Object.assign({}, repeat), { jobId }));
+ const repeatJobKey = (_a = repeat.key) !== null && _a !== undefined ? _a : this.hash(repeatConcatOptions);
+ const legacyRepeatJobId = this.getRepeatJobId({
+ name,
+ nextMillis: "",
+ namespace: this.hash(repeatConcatOptions),
+ jobId: jobId !== null && jobId !== undefined ? jobId : repeat.jobId,
+ key: repeat.key
+ });
+ return this.scripts.removeRepeatable(legacyRepeatJobId, repeatConcatOptions, repeatJobKey);
+ }
+ async removeRepeatableByKey(repeatJobKey) {
+ const data = this.keyToData(repeatJobKey);
+ const legacyRepeatJobId = this.getRepeatJobId({
+ name: data.name,
+ nextMillis: "",
+ namespace: this.hash(repeatJobKey),
+ jobId: data.id
+ });
+ return this.scripts.removeRepeatable(legacyRepeatJobId, "", repeatJobKey);
+ }
+ async getRepeatableData(client, key, next) {
+ const jobData = await client.hgetall(this.toKey("repeat:" + key));
+ if (jobData) {
return {
- id: tc.id,
- order: tc.order,
- input: response.input,
- output: response.output
+ key,
+ name: jobData.name,
+ endDate: parseInt(jobData.endDate) || null,
+ tz: jobData.tz || null,
+ pattern: jobData.pattern || null,
+ every: jobData.every || null,
+ next
};
- }));
+ }
+ return this.keyToData(key, next);
+ }
+ keyToData(key, next) {
+ const data = key.split(":");
+ const pattern = data.slice(4).join(":") || null;
return {
- ...p2,
- difficulty: p2.difficulty,
- tags: tagsResult.map((t9) => t9.tagName),
- sampleTestcases
+ key,
+ name: data[0],
+ id: data[1] || null,
+ endDate: parseInt(data[2]) || null,
+ tz: data[3] || null,
+ pattern,
+ next
};
- } catch (error) {
- if (error instanceof ApiError_default) {
- throw error;
- }
- console.error("Error fetching problem by id:", error);
- throw new ApiError_default("Failed to fetch problem details", E.INTERNAL_SERVER_ERROR);
}
-};
-var handleGetEditorialSolution = async (problemId) => {
- try {
- const editorialResult = await db.select().from(editorial).where(eq(editorial.problemId, problemId)).limit(1);
- if (editorialResult.length === 0) {
- throw new ApiError_default("Editorial not found", E.NOT_FOUND);
- }
- const editorials = editorialResult[0];
- const solutionResponse = await fetchFileFromS3(editorials.solutionS3Key);
- if (!solutionResponse) {
- throw new ApiError_default("Solution file not found in storage: " + editorials.solutionS3Key, E.INTERNAL_SERVER_ERROR);
- }
- return solutionResponse;
- } catch (error) {
- if (error instanceof ApiError_default) {
- throw error;
+ async getRepeatableJobs(start = 0, end = -1, asc2 = false) {
+ const client = await this.client;
+ const key = this.keys.repeat;
+ const result = asc2 ? await client.zrange(key, start, end, "WITHSCORES") : await client.zrevrange(key, start, end, "WITHSCORES");
+ const jobs = [];
+ for (let i2 = 0;i2 < result.length; i2 += 2) {
+ jobs.push(this.getRepeatableData(client, result[i2], parseInt(result[i2 + 1])));
}
- console.error("Error fetching editorial solution:", error);
- throw new ApiError_default("Failed to fetch editorial solution", E.INTERNAL_SERVER_ERROR);
+ return Promise.all(jobs);
}
-};
-var handleGetEditorialContent = async (problemId) => {
+ async getRepeatableCount() {
+ const client = await this.client;
+ return client.zcard(this.toKey("repeat"));
+ }
+ hash(str) {
+ return createHash2(this.repeatKeyHashAlgorithm).update(str).digest("hex");
+ }
+ getRepeatDelayedJobId({ nextMillis, customKey }) {
+ return `repeat:${customKey}:${nextMillis}`;
+ }
+ getRepeatJobId({ name, nextMillis, namespace, jobId, key }) {
+ const checksum = key !== null && key !== undefined ? key : this.hash(`${name}${jobId || ""}${namespace}`);
+ return `repeat:${checksum}:${nextMillis}`;
+ }
+}
+function getRepeatConcatOptions(name, repeat) {
+ const endDate = repeat.endDate ? new Date(repeat.endDate).getTime() : "";
+ const tz = repeat.tz || "";
+ const pattern = repeat.pattern;
+ const suffix = (pattern ? pattern : String(repeat.every)) || "";
+ const jobId = repeat.jobId ? repeat.jobId : "";
+ return `${name}:${jobId}:${endDate}:${tz}:${suffix}`;
+}
+var getNextMillis = (millis, opts) => {
+ const pattern = opts.pattern;
+ if (pattern && opts.every) {
+ throw new Error("Both .pattern and .every options are defined for this repeatable job");
+ }
+ if (opts.every) {
+ return Math.floor(millis / opts.every) * opts.every + (opts.immediately ? 0 : opts.every);
+ }
+ const currentDate = opts.startDate && new Date(opts.startDate) > new Date(millis) ? new Date(opts.startDate) : new Date(millis);
+ const interval3 = import_cron_parser2.parseExpression(pattern, Object.assign(Object.assign({}, opts), { currentDate }));
try {
- const editorialResult = await db.select({
- contentS3Key: editorial.contentS3Key,
- editorialLink: editorial.editorialLink
- }).from(editorial).where(eq(editorial.problemId, problemId)).limit(1);
- if (editorialResult.length === 0) {
- throw new ApiError_default("Editorial not found", E.NOT_FOUND);
- }
- const editorials = editorialResult[0];
- const editorialContentResponse = await fetchFileFromS3(editorials.contentS3Key);
- if (!editorialContentResponse) {
- throw new ApiError_default("Editorial content not found in storage: " + editorials.contentS3Key, E.INTERNAL_SERVER_ERROR);
+ if (opts.immediately) {
+ return new Date().getTime();
+ } else {
+ return interval3.next().getTime();
}
+ } catch (e3) {}
+};
+
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/classes/queue.js
+class Queue extends QueueGetters {
+ constructor(name, opts, Connection2) {
+ var _a;
+ super(name, Object.assign({}, opts), Connection2);
+ this.token = v4_default();
+ this.libName = "bullmq";
+ this.jobsOpts = (_a = opts === null || opts === undefined ? undefined : opts.defaultJobOptions) !== null && _a !== undefined ? _a : {};
+ this.waitUntilReady().then((client) => {
+ if (!this.closing && !(opts === null || opts === undefined ? undefined : opts.skipMetasUpdate)) {
+ return client.hmset(this.keys.meta, this.metaValues);
+ }
+ }).catch((err) => {});
+ }
+ emit(event, ...args) {
+ return super.emit(event, ...args);
+ }
+ off(eventName, listener) {
+ super.off(eventName, listener);
+ return this;
+ }
+ on(event, listener) {
+ super.on(event, listener);
+ return this;
+ }
+ once(event, listener) {
+ super.once(event, listener);
+ return this;
+ }
+ get defaultJobOptions() {
+ return Object.assign({}, this.jobsOpts);
+ }
+ get metaValues() {
+ var _a, _b, _c2, _d2;
return {
- editorialContent: editorialContentResponse,
- editorialLink: editorials.editorialLink
+ "opts.maxLenEvents": (_d2 = (_c2 = (_b = (_a = this.opts) === null || _a === undefined ? undefined : _a.streams) === null || _b === undefined ? undefined : _b.events) === null || _c2 === undefined ? undefined : _c2.maxLen) !== null && _d2 !== undefined ? _d2 : 1e4,
+ version: `${this.libName}:${version3}`
};
- } catch (error) {
- if (error instanceof ApiError_default) {
- throw error;
+ }
+ async getVersion() {
+ const client = await this.client;
+ return await client.hget(this.keys.meta, "version");
+ }
+ get repeat() {
+ return new Promise(async (resolve) => {
+ if (!this._repeat) {
+ this._repeat = new Repeat(this.name, Object.assign(Object.assign({}, this.opts), { connection: await this.client }));
+ this._repeat.on("error", this.emit.bind(this, "error"));
+ }
+ resolve(this._repeat);
+ });
+ }
+ get jobScheduler() {
+ return new Promise(async (resolve) => {
+ if (!this._jobScheduler) {
+ this._jobScheduler = new JobScheduler(this.name, Object.assign(Object.assign({}, this.opts), { connection: await this.client }));
+ this._jobScheduler.on("error", this.emit.bind(this, "error"));
+ }
+ resolve(this._jobScheduler);
+ });
+ }
+ async setGlobalConcurrency(concurrency) {
+ const client = await this.client;
+ return client.hset(this.keys.meta, "concurrency", concurrency);
+ }
+ async setGlobalRateLimit(max, duration) {
+ const client = await this.client;
+ return client.hset(this.keys.meta, "max", max, "duration", duration);
+ }
+ async removeGlobalConcurrency() {
+ const client = await this.client;
+ return client.hdel(this.keys.meta, "concurrency");
+ }
+ async removeGlobalRateLimit() {
+ const client = await this.client;
+ return client.hdel(this.keys.meta, "max", "duration");
+ }
+ async add(name, data, opts) {
+ return this.trace(SpanKind.PRODUCER, "add", `${this.name}.${name}`, async (span, srcPropagationMetadata) => {
+ var _a;
+ if (srcPropagationMetadata && !((_a = opts === null || opts === undefined ? undefined : opts.telemetry) === null || _a === undefined ? undefined : _a.omitContext)) {
+ const telemetry = {
+ metadata: srcPropagationMetadata
+ };
+ opts = Object.assign(Object.assign({}, opts), { telemetry });
+ }
+ const job = await this.addJob(name, data, opts);
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.JobName]: name,
+ [TelemetryAttributes.JobId]: job.id
+ });
+ return job;
+ });
+ }
+ async addJob(name, data, opts) {
+ if (opts && opts.repeat) {
+ if (opts.repeat.endDate) {
+ if (+new Date(opts.repeat.endDate) < Date.now()) {
+ throw new Error("End date must be greater than current timestamp");
+ }
+ }
+ return (await this.repeat).updateRepeatableJob(name, data, Object.assign(Object.assign({}, this.jobsOpts), opts), { override: true });
+ } else {
+ const jobId = opts === null || opts === undefined ? undefined : opts.jobId;
+ if (jobId == "0" || (jobId === null || jobId === undefined ? undefined : jobId.startsWith("0:"))) {
+ throw new Error("JobId cannot be '0' or start with 0:");
+ }
+ const mergedOpts = Object.assign(Object.assign(Object.assign({}, this.jobsOpts), opts), { jobId });
+ const job = await this.Job.create(this, name, data, mergedOpts);
+ this.emit("waiting", job);
+ return job;
}
- console.error("Error fetching editorial content:", error);
- throw new ApiError_default("Failed to fetch editorial content", E.INTERNAL_SERVER_ERROR);
}
+ async addBulk(jobs) {
+ return this.trace(SpanKind.PRODUCER, "addBulk", this.name, async (span, srcPropagationMetadata) => {
+ if (span) {
+ span.setAttributes({
+ [TelemetryAttributes.BulkNames]: jobs.map((job) => job.name),
+ [TelemetryAttributes.BulkCount]: jobs.length
+ });
+ }
+ return await this.Job.createBulk(this, jobs.map((job) => {
+ var _a, _b, _c2, _d2, _e2, _f;
+ let telemetry = (_a = job.opts) === null || _a === undefined ? undefined : _a.telemetry;
+ if (srcPropagationMetadata) {
+ const omitContext = (_c2 = (_b = job.opts) === null || _b === undefined ? undefined : _b.telemetry) === null || _c2 === undefined ? undefined : _c2.omitContext;
+ const telemetryMetadata = ((_e2 = (_d2 = job.opts) === null || _d2 === undefined ? undefined : _d2.telemetry) === null || _e2 === undefined ? undefined : _e2.metadata) || !omitContext && srcPropagationMetadata;
+ if (telemetryMetadata || omitContext) {
+ telemetry = {
+ metadata: telemetryMetadata,
+ omitContext
+ };
+ }
+ }
+ const mergedOpts = Object.assign(Object.assign(Object.assign({}, this.jobsOpts), job.opts), { jobId: (_f = job.opts) === null || _f === undefined ? undefined : _f.jobId, telemetry });
+ return {
+ name: job.name,
+ data: job.data,
+ opts: mergedOpts
+ };
+ }));
+ });
+ }
+ async upsertJobScheduler(jobSchedulerId, repeatOpts, jobTemplate) {
+ var _a, _b;
+ if (repeatOpts.endDate) {
+ if (+new Date(repeatOpts.endDate) < Date.now()) {
+ throw new Error("End date must be greater than current timestamp");
+ }
+ }
+ return (await this.jobScheduler).upsertJobScheduler(jobSchedulerId, repeatOpts, (_a = jobTemplate === null || jobTemplate === undefined ? undefined : jobTemplate.name) !== null && _a !== undefined ? _a : jobSchedulerId, (_b = jobTemplate === null || jobTemplate === undefined ? undefined : jobTemplate.data) !== null && _b !== undefined ? _b : {}, Object.assign(Object.assign({}, this.jobsOpts), jobTemplate === null || jobTemplate === undefined ? undefined : jobTemplate.opts), { override: true });
+ }
+ async pause() {
+ await this.trace(SpanKind.INTERNAL, "pause", this.name, async () => {
+ await this.scripts.pause(true);
+ this.emit("paused");
+ });
+ }
+ async close() {
+ await this.trace(SpanKind.INTERNAL, "close", this.name, async () => {
+ if (!this.closing) {
+ if (this._repeat) {
+ await this._repeat.close();
+ }
+ }
+ await super.close();
+ });
+ }
+ async rateLimit(expireTimeMs) {
+ await this.trace(SpanKind.INTERNAL, "rateLimit", this.name, async (span) => {
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.QueueRateLimit]: expireTimeMs
+ });
+ await this.client.then((client) => client.set(this.keys.limiter, Number.MAX_SAFE_INTEGER, "PX", expireTimeMs));
+ });
+ }
+ async resume() {
+ await this.trace(SpanKind.INTERNAL, "resume", this.name, async () => {
+ await this.scripts.pause(false);
+ this.emit("resumed");
+ });
+ }
+ async isPaused() {
+ const client = await this.client;
+ const pausedKeyExists = await client.hexists(this.keys.meta, "paused");
+ return pausedKeyExists === 1;
+ }
+ isMaxed() {
+ return this.scripts.isMaxed();
+ }
+ async getRepeatableJobs(start, end, asc2) {
+ return (await this.repeat).getRepeatableJobs(start, end, asc2);
+ }
+ async getJobScheduler(id) {
+ return (await this.jobScheduler).getScheduler(id);
+ }
+ async getJobSchedulers(start, end, asc2) {
+ return (await this.jobScheduler).getJobSchedulers(start, end, asc2);
+ }
+ async getJobSchedulersCount() {
+ return (await this.jobScheduler).getSchedulersCount();
+ }
+ async removeRepeatable(name, repeatOpts, jobId) {
+ return this.trace(SpanKind.INTERNAL, "removeRepeatable", `${this.name}.${name}`, async (span) => {
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.JobName]: name,
+ [TelemetryAttributes.JobId]: jobId
+ });
+ const repeat = await this.repeat;
+ const removed = await repeat.removeRepeatable(name, repeatOpts, jobId);
+ return !removed;
+ });
+ }
+ async removeJobScheduler(jobSchedulerId) {
+ const jobScheduler = await this.jobScheduler;
+ const removed = await jobScheduler.removeJobScheduler(jobSchedulerId);
+ return !removed;
+ }
+ async removeDebounceKey(id) {
+ return this.trace(SpanKind.INTERNAL, "removeDebounceKey", `${this.name}`, async (span) => {
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.JobKey]: id
+ });
+ const client = await this.client;
+ return await client.del(`${this.keys.de}:${id}`);
+ });
+ }
+ async removeDeduplicationKey(id) {
+ return this.trace(SpanKind.INTERNAL, "removeDeduplicationKey", `${this.name}`, async (span) => {
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.DeduplicationKey]: id
+ });
+ const client = await this.client;
+ return client.del(`${this.keys.de}:${id}`);
+ });
+ }
+ async removeRateLimitKey() {
+ const client = await this.client;
+ return client.del(this.keys.limiter);
+ }
+ async removeRepeatableByKey(key) {
+ return this.trace(SpanKind.INTERNAL, "removeRepeatableByKey", `${this.name}`, async (span) => {
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.JobKey]: key
+ });
+ const repeat = await this.repeat;
+ const removed = await repeat.removeRepeatableByKey(key);
+ return !removed;
+ });
+ }
+ async remove(jobId, { removeChildren = true } = {}) {
+ return this.trace(SpanKind.INTERNAL, "remove", this.name, async (span) => {
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.JobId]: jobId,
+ [TelemetryAttributes.JobOptions]: JSON.stringify({
+ removeChildren
+ })
+ });
+ const code = await this.scripts.remove(jobId, removeChildren);
+ if (code === 1) {
+ this.emit("removed", jobId);
+ }
+ return code;
+ });
+ }
+ async updateJobProgress(jobId, progress) {
+ await this.trace(SpanKind.INTERNAL, "updateJobProgress", this.name, async (span) => {
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.JobId]: jobId,
+ [TelemetryAttributes.JobProgress]: JSON.stringify(progress)
+ });
+ await this.scripts.updateProgress(jobId, progress);
+ this.emit("progress", jobId, progress);
+ });
+ }
+ async addJobLog(jobId, logRow, keepLogs) {
+ return Job.addJobLog(this, jobId, logRow, keepLogs);
+ }
+ async drain(delayed = false) {
+ await this.trace(SpanKind.INTERNAL, "drain", this.name, async (span) => {
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.QueueDrainDelay]: delayed
+ });
+ await this.scripts.drain(delayed);
+ });
+ }
+ async clean(grace, limit, type = "completed") {
+ return this.trace(SpanKind.INTERNAL, "clean", this.name, async (span) => {
+ const maxCount = limit || Infinity;
+ const maxCountPerCall = Math.min(1e4, maxCount);
+ const timestamp3 = Date.now() - grace;
+ let deletedCount = 0;
+ const deletedJobsIds = [];
+ const normalizedType = type === "waiting" ? "wait" : type;
+ while (deletedCount < maxCount) {
+ const jobsIds = await this.scripts.cleanJobsInSet(normalizedType, timestamp3, maxCountPerCall);
+ this.emit("cleaned", jobsIds, normalizedType);
+ deletedCount += jobsIds.length;
+ deletedJobsIds.push(...jobsIds);
+ if (jobsIds.length < maxCountPerCall) {
+ break;
+ }
+ }
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.QueueGrace]: grace,
+ [TelemetryAttributes.JobType]: type,
+ [TelemetryAttributes.QueueCleanLimit]: maxCount,
+ [TelemetryAttributes.JobIds]: deletedJobsIds
+ });
+ return deletedJobsIds;
+ });
+ }
+ async obliterate(opts) {
+ await this.trace(SpanKind.INTERNAL, "obliterate", this.name, async () => {
+ await this.pause();
+ let cursor = 0;
+ do {
+ cursor = await this.scripts.obliterate(Object.assign({ force: false, count: 1000 }, opts));
+ } while (cursor);
+ });
+ }
+ async retryJobs(opts = {}) {
+ await this.trace(SpanKind.PRODUCER, "retryJobs", this.name, async (span) => {
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.QueueOptions]: JSON.stringify(opts)
+ });
+ let cursor = 0;
+ do {
+ cursor = await this.scripts.retryJobs(opts.state, opts.count, opts.timestamp);
+ } while (cursor);
+ });
+ }
+ async promoteJobs(opts = {}) {
+ await this.trace(SpanKind.INTERNAL, "promoteJobs", this.name, async (span) => {
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.QueueOptions]: JSON.stringify(opts)
+ });
+ let cursor = 0;
+ do {
+ cursor = await this.scripts.promoteJobs(opts.count);
+ } while (cursor);
+ });
+ }
+ async trimEvents(maxLength) {
+ return this.trace(SpanKind.INTERNAL, "trimEvents", this.name, async (span) => {
+ span === null || span === undefined || span.setAttributes({
+ [TelemetryAttributes.QueueEventMaxLength]: maxLength
+ });
+ const client = await this.client;
+ return await client.xtrim(this.keys.events, "MAXLEN", "~", maxLength);
+ });
+ }
+ async removeDeprecatedPriorityKey() {
+ const client = await this.client;
+ return client.del(this.toKey("priority"));
+ }
+ async removeOrphanedJobs(count2 = 1000, limit = 0) {
+ const client = await this.client;
+ const knownSuffixes = new Set(Object.keys(this.keys));
+ const stateKeySuffixes = Object.keys(this.keys).filter((s2) => s2 !== "");
+ const jobSubKeySuffixes = [
+ "logs",
+ "dependencies",
+ "processed",
+ "failed",
+ "unsuccessful",
+ "lock"
+ ];
+ const basePrefix = this.qualifiedName + ":";
+ const scanPattern = basePrefix + "*";
+ let totalRemoved = 0;
+ let cursor = "0";
+ do {
+ const [nextCursor, keys] = await client.scan(cursor, "MATCH", scanPattern, "COUNT", count2);
+ cursor = nextCursor;
+ const candidateJobIds = new Set;
+ for (const key of keys) {
+ const suffix = key.slice(basePrefix.length);
+ if (knownSuffixes.has(suffix)) {
+ continue;
+ }
+ const colonIdx = suffix.indexOf(":");
+ if (colonIdx !== -1) {
+ const prefixPart = suffix.slice(0, colonIdx);
+ if (knownSuffixes.has(prefixPart)) {
+ continue;
+ }
+ }
+ const jobId = colonIdx === -1 ? suffix : suffix.slice(0, colonIdx);
+ if (colonIdx !== -1) {
+ const subKey = suffix.slice(colonIdx + 1);
+ if (!jobSubKeySuffixes.includes(subKey)) {
+ continue;
+ }
+ }
+ candidateJobIds.add(jobId);
+ }
+ if (candidateJobIds.size === 0) {
+ continue;
+ }
+ const result = await this.scripts.removeOrphanedJobs([...candidateJobIds], stateKeySuffixes, jobSubKeySuffixes);
+ totalRemoved += result || 0;
+ if (limit > 0 && totalRemoved >= limit) {
+ break;
+ }
+ } while (cursor !== "0");
+ return totalRemoved;
+ }
+}
+// node_modules/.pnpm/bullmq@5.76.1/node_modules/bullmq/dist/esm/interfaces/queue-options.js
+var ClientType;
+(function(ClientType2) {
+ ClientType2["blocking"] = "blocking";
+ ClientType2["normal"] = "normal";
+})(ClientType || (ClientType = {}));
+// src/loaders/queue.ts
+var connection2 = {
+ url: config_default.REDIS_URL
};
-
-// src/api/problem/problem-controller.ts
-var createProblem = asyncHandler_default(async (req, res) => {
- const response = await handleCreateProblem(req.user.id, req.body);
- return res.status(200).json({
- status: "success",
- message: "Problem created successfully",
- data: response
- });
-});
-var finalizeProblem = asyncHandler_default(async (req, res) => {
- const problemId = req.query.problemId;
- await handleFinalizeProblem(req.user.id, problemId);
- return res.status(200).json({
- status: "success",
- message: "Problem finalized successfully"
- });
-});
-var getProblems = asyncHandler_default(async (req, res) => {
- const limit = parseInt(req.query.limit) || 10;
- const cursor = req.query.cursor;
- const response = await handleGetProblems({ limit, cursor });
- return res.status(200).json({
- status: "success",
- message: "Problems fetched successfully",
- data: response
- });
-});
-var getProblemById = asyncHandler_default(async (req, res) => {
- const problemId = req.params.problemId;
- const response = await handleGetProblemById(problemId);
- return res.status(200).json({
- status: "success",
- message: "Problem fetched successfully",
- data: response
- });
-});
-var getEditorialSolution = asyncHandler_default(async (req, res) => {
- const problemId = req.params.problemId;
- const response = await handleGetEditorialSolution(problemId);
- return res.status(200).json({
- status: "success",
- message: "Editorial solution fetched successfully",
- data: response
+var runQueue = new Queue("run-queue", { connection: connection2 });
+var submitQueue = new Queue("submit-queue", { connection: connection2 });
+
+// src/api/submission/submission-helper.ts
+async function createRunQueue(submissionId, code, language, problemId, timeLimit, memoryLimit) {
+ return await runQueue.add("run-code", {
+ submissionId,
+ code,
+ language,
+ problemId,
+ timeLimit,
+ memoryLimit
+ }, {
+ jobId: submissionId,
+ attempts: 1,
+ priority: 1,
+ removeOnComplete: true,
+ removeOnFail: 50
});
-});
-var getEditorialContent = asyncHandler_default(async (req, res) => {
- const problemId = req.params.problemId;
- const response = await handleGetEditorialContent(problemId);
- return res.status(200).json({
- status: "success",
- message: "Editorial solution fetched successfully",
- data: response
+}
+async function createSubmitQueue(submissionId, code, language, problemId, timeLimit, memoryLimit) {
+ return await submitQueue.add("submit-code", {
+ submissionId,
+ code,
+ language,
+ problemId,
+ timeLimit,
+ memoryLimit
+ }, {
+ jobId: submissionId,
+ attempts: 2,
+ backoff: {
+ type: "exponential",
+ delay: 1000
+ },
+ priority: 2,
+ removeOnComplete: true,
+ removeOnFail: 50
});
-});
-
-// src/api/problem/problem-route.ts
-var router2 = import_express2.Router();
-router2.post("/create", validate("body", createProblemSchema), verifyJWT, createProblem);
-router2.post("/finalize", verifyJWT, finalizeProblem);
-router2.get("/", validate("query", getProblemsSchema), getProblems);
-router2.get("/:problemId", getProblemById);
-router2.get("/:problemId/editorial-solution", getEditorialSolution);
-router2.get("/:problemId/editorial-content", getEditorialContent);
-var problem_route_default = router2;
-
-// src/api/submission/submission-route.ts
-var import_express3 = __toESM(require_express(), 1);
-
-// src/api/submission/submission-schema.ts
-var createsubmissionSchema = create$3({
- code: create$6().required("Code is required"),
- language: create$6().required("Language is required")
-});
-var problemIdSchema = create$3({
- problemId: create$6().required("Problem ID is required")
-});
-
-// src/loaders/queue.ts
-var import_bull = __toESM(require_bull(), 1);
-var redis = config_default.REDIS_URL;
-var myQueue = new import_bull.default("job-queue", redis);
-
-// src/loaders/redis.ts
-var import_ioredis = __toESM(require_built3(), 1);
-var import_dotenv3 = __toESM(require_main(), 1);
-import_dotenv3.default.config();
-var redisUrl = process.env.REDIS_URL;
-if (!redisUrl) {
- throw new Error("REDIS_URL is not set");
}
-var redis2 = new import_ioredis.default(redisUrl);
-var redis_default = redis2;
// src/api/submission/submission-service.ts
var handleCreateSubmission = async (userId, problemId, code, language, mode) => {
@@ -173990,53 +171066,86 @@ var handleCreateSubmission = async (userId, problemId, code, language, mode) =>
status: "PENDING"
}).returning({ id: submission.id });
const submissionId = insertedSubmission.id;
- try {
- await myQueue.add({
+ const prob = await db.select({
+ timeLimit: problem.timeLimit,
+ memoryLimit: problem.memoryLimit
+ }).from(problem).where(eq(problem.id, problemId));
+ if (prob.length === 0) {
+ return {
submissionId,
- mode: normalizedMode
- });
+ status: "FAILED",
+ startedAt: new Date
+ };
+ }
+ try {
+ if (normalizedMode === "RUN") {
+ await createRunQueue(submissionId, code, language, problemId, prob[0].timeLimit, prob[0].memoryLimit);
+ } else {
+ await createSubmitQueue(submissionId, code, language, problemId, prob[0].timeLimit, prob[0].memoryLimit);
+ }
return {
submissionId,
- status: "PENDING"
+ status: "PENDING",
+ startedAt: new Date
};
} catch (queueError) {
console.error("Queue error:", queueError);
return {
submissionId,
- status: "FAILED"
+ status: "FAILED",
+ startedAt: new Date
};
}
} catch (dbError) {
console.error("Database error:", dbError);
return {
submissionId: "",
- status: "ERROR"
+ status: "ERROR",
+ startedAt: new Date
};
}
};
var handlegetSubmissionStatus = async (userId, submissionId) => {
try {
+ const [dbResult] = await db.select({
+ id: submission.id,
+ status: submission.status,
+ createdAt: submission.createdAt
+ }).from(submission).where(eq(submission.id, submissionId));
+ if (!dbResult) {
+ throw new ApiError_default("Submission not found", E.NOT_FOUND);
+ }
const redisStatus = await redis_default.get(`submission:${submissionId}`);
if (redisStatus) {
const parsed = JSON.parse(redisStatus);
+ const redisState = String(parsed?.status || "").toUpperCase();
+ const dbState = String(dbResult.status || "").toUpperCase();
+ const dbIsTerminal = dbState === "COMPLETED" || dbState === "FAILED";
+ const redisIsNonTerminal = redisState === "PENDING" || redisState === "RUNNING";
+ if (dbIsTerminal && redisIsNonTerminal) {
+ return {
+ submissionId: dbResult.id,
+ status: dbResult.status,
+ startedAt: new Date(dbResult.createdAt)
+ };
+ }
return {
submissionId,
- status: parsed.status
+ status: parsed.status,
+ startedAt: new Date(parsed.updatedAt || parsed.createdAt || dbResult.createdAt)
};
}
- const [result] = await db.select().from(submission).where(eq(submission.id, submissionId));
- if (!result) {
- throw new ApiError_default("Submission not found", E.NOT_FOUND);
- }
return {
- submissionId: result.id,
- status: result.status
+ submissionId: dbResult.id,
+ status: dbResult.status,
+ startedAt: new Date(dbResult.createdAt)
};
} catch (error) {
console.error("Database error:", error);
return {
submissionId: "",
- status: "ERROR"
+ status: "ERROR",
+ startedAt: null
};
}
};
@@ -174085,6 +171194,57 @@ var handleGetSubmissionResults = async (userId, submissionId) => {
};
}
};
+var handleGetUserDashboardStats = async (userId) => {
+ try {
+ const recentSubs = await db.select({
+ id: submission.id,
+ language: submission.language,
+ status: submission.status,
+ verdict: executionResult.verdict,
+ timeTaken: submission.timeTaken,
+ memoryTaken: submission.memoryTaken,
+ createdAt: submission.createdAt,
+ problemId: submission.problemId,
+ problemTitle: problem.title,
+ problemSlug: problem.slug,
+ problemDifficulty: problem.difficulty
+ }).from(submission).leftJoin(executionResult, eq(executionResult.submissionId, submission.id)).leftJoin(problem, eq(problem.id, submission.problemId)).where(and(eq(submission.userId, userId), eq(submission.mode, "SUBMIT"))).orderBy(desc(submission.createdAt)).limit(20);
+ const [totalRow] = await db.select({ count: count() }).from(submission).where(and(eq(submission.userId, userId), eq(submission.mode, "SUBMIT")));
+ const acceptedProblems = await db.selectDistinct({ problemId: submission.problemId }).from(submission).innerJoin(executionResult, eq(executionResult.submissionId, submission.id)).where(and(eq(submission.userId, userId), eq(submission.mode, "SUBMIT"), eq(executionResult.verdict, "ACCEPTED")));
+ const acceptedWithDiff = await db.selectDistinct({ problemId: submission.problemId, difficulty: problem.difficulty }).from(submission).innerJoin(executionResult, eq(executionResult.submissionId, submission.id)).innerJoin(problem, eq(problem.id, submission.problemId)).where(and(eq(submission.userId, userId), eq(submission.mode, "SUBMIT"), eq(executionResult.verdict, "ACCEPTED")));
+ const easyCount = acceptedWithDiff.filter((r2) => r2.difficulty === "EASY").length;
+ const mediumCount = acceptedWithDiff.filter((r2) => r2.difficulty === "MEDIUM").length;
+ const hardCount = acceptedWithDiff.filter((r2) => r2.difficulty === "HARD").length;
+ const formatted = recentSubs.map((r2) => ({
+ id: r2.id,
+ language: r2.language,
+ status: r2.verdict && r2.verdict !== "PENDING" ? r2.verdict : r2.status,
+ timeTaken: r2.timeTaken,
+ memoryTaken: r2.memoryTaken,
+ createdAt: r2.createdAt,
+ problem: {
+ id: r2.problemId,
+ title: r2.problemTitle,
+ slug: r2.problemSlug,
+ difficulty: r2.problemDifficulty
+ }
+ }));
+ return {
+ totalSubmissions: totalRow?.count ?? 0,
+ totalSolved: acceptedProblems.length,
+ solvedByDifficulty: { easy: easyCount, medium: mediumCount, hard: hardCount },
+ recentSubmissions: formatted
+ };
+ } catch (error) {
+ console.error("Dashboard stats error:", error);
+ return {
+ totalSubmissions: 0,
+ totalSolved: 0,
+ solvedByDifficulty: { easy: 0, medium: 0, hard: 0 },
+ recentSubmissions: []
+ };
+ }
+};
var handleGetAllSubmissions = async (userId, problemId) => {
try {
const results = await db.select({
@@ -174157,13 +171317,22 @@ var getAllSubmissions = asyncHandler_default(async (req, res) => {
message: response
});
});
+var getUserDashboardStats = asyncHandler_default(async (req, res) => {
+ const userId = req.user.id;
+ const response = await handleGetUserDashboardStats(userId);
+ return res.status(200).json({
+ success: true,
+ data: response
+ });
+});
// src/api/submission/submission-route.ts
var router3 = import_express3.Router();
-router3.post("/:problemId/:mode", validate("body", createsubmissionSchema), verifyJWT, createSubmission);
+router3.get("/user/dashboard", verifyJWT, getUserDashboardStats);
+router3.get("/problem/:problemId", verifyJWT, getAllSubmissions);
router3.get("/:submissionId", verifyJWT, getSubmissionStatus);
router3.get("/:submissionId/result", verifyJWT, getSubmissionResults);
-router3.get("/problem/:problemId", verifyJWT, getAllSubmissions);
+router3.post("/:problemId/:mode", validate("body", createSubmissionSchema), verifyJWT, createSubmission);
var submission_route_default = router3;
// src/api/interview/interview-route.ts
@@ -174188,936 +171357,6 @@ class ApiResponse {
}
}
-// node_modules/.pnpm/@google+generative-ai@0.24.1/node_modules/@google/generative-ai/dist/index.mjs
-var SchemaType;
-(function(SchemaType2) {
- SchemaType2["STRING"] = "string";
- SchemaType2["NUMBER"] = "number";
- SchemaType2["INTEGER"] = "integer";
- SchemaType2["BOOLEAN"] = "boolean";
- SchemaType2["ARRAY"] = "array";
- SchemaType2["OBJECT"] = "object";
-})(SchemaType || (SchemaType = {}));
-var ExecutableCodeLanguage;
-(function(ExecutableCodeLanguage2) {
- ExecutableCodeLanguage2["LANGUAGE_UNSPECIFIED"] = "language_unspecified";
- ExecutableCodeLanguage2["PYTHON"] = "python";
-})(ExecutableCodeLanguage || (ExecutableCodeLanguage = {}));
-var Outcome;
-(function(Outcome2) {
- Outcome2["OUTCOME_UNSPECIFIED"] = "outcome_unspecified";
- Outcome2["OUTCOME_OK"] = "outcome_ok";
- Outcome2["OUTCOME_FAILED"] = "outcome_failed";
- Outcome2["OUTCOME_DEADLINE_EXCEEDED"] = "outcome_deadline_exceeded";
-})(Outcome || (Outcome = {}));
-var POSSIBLE_ROLES = ["user", "model", "function", "system"];
-var HarmCategory;
-(function(HarmCategory2) {
- HarmCategory2["HARM_CATEGORY_UNSPECIFIED"] = "HARM_CATEGORY_UNSPECIFIED";
- HarmCategory2["HARM_CATEGORY_HATE_SPEECH"] = "HARM_CATEGORY_HATE_SPEECH";
- HarmCategory2["HARM_CATEGORY_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_SEXUALLY_EXPLICIT";
- HarmCategory2["HARM_CATEGORY_HARASSMENT"] = "HARM_CATEGORY_HARASSMENT";
- HarmCategory2["HARM_CATEGORY_DANGEROUS_CONTENT"] = "HARM_CATEGORY_DANGEROUS_CONTENT";
- HarmCategory2["HARM_CATEGORY_CIVIC_INTEGRITY"] = "HARM_CATEGORY_CIVIC_INTEGRITY";
-})(HarmCategory || (HarmCategory = {}));
-var HarmBlockThreshold;
-(function(HarmBlockThreshold2) {
- HarmBlockThreshold2["HARM_BLOCK_THRESHOLD_UNSPECIFIED"] = "HARM_BLOCK_THRESHOLD_UNSPECIFIED";
- HarmBlockThreshold2["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE";
- HarmBlockThreshold2["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE";
- HarmBlockThreshold2["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH";
- HarmBlockThreshold2["BLOCK_NONE"] = "BLOCK_NONE";
-})(HarmBlockThreshold || (HarmBlockThreshold = {}));
-var HarmProbability;
-(function(HarmProbability2) {
- HarmProbability2["HARM_PROBABILITY_UNSPECIFIED"] = "HARM_PROBABILITY_UNSPECIFIED";
- HarmProbability2["NEGLIGIBLE"] = "NEGLIGIBLE";
- HarmProbability2["LOW"] = "LOW";
- HarmProbability2["MEDIUM"] = "MEDIUM";
- HarmProbability2["HIGH"] = "HIGH";
-})(HarmProbability || (HarmProbability = {}));
-var BlockReason;
-(function(BlockReason2) {
- BlockReason2["BLOCKED_REASON_UNSPECIFIED"] = "BLOCKED_REASON_UNSPECIFIED";
- BlockReason2["SAFETY"] = "SAFETY";
- BlockReason2["OTHER"] = "OTHER";
-})(BlockReason || (BlockReason = {}));
-var FinishReason;
-(function(FinishReason2) {
- FinishReason2["FINISH_REASON_UNSPECIFIED"] = "FINISH_REASON_UNSPECIFIED";
- FinishReason2["STOP"] = "STOP";
- FinishReason2["MAX_TOKENS"] = "MAX_TOKENS";
- FinishReason2["SAFETY"] = "SAFETY";
- FinishReason2["RECITATION"] = "RECITATION";
- FinishReason2["LANGUAGE"] = "LANGUAGE";
- FinishReason2["BLOCKLIST"] = "BLOCKLIST";
- FinishReason2["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT";
- FinishReason2["SPII"] = "SPII";
- FinishReason2["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL";
- FinishReason2["OTHER"] = "OTHER";
-})(FinishReason || (FinishReason = {}));
-var TaskType;
-(function(TaskType2) {
- TaskType2["TASK_TYPE_UNSPECIFIED"] = "TASK_TYPE_UNSPECIFIED";
- TaskType2["RETRIEVAL_QUERY"] = "RETRIEVAL_QUERY";
- TaskType2["RETRIEVAL_DOCUMENT"] = "RETRIEVAL_DOCUMENT";
- TaskType2["SEMANTIC_SIMILARITY"] = "SEMANTIC_SIMILARITY";
- TaskType2["CLASSIFICATION"] = "CLASSIFICATION";
- TaskType2["CLUSTERING"] = "CLUSTERING";
-})(TaskType || (TaskType = {}));
-var FunctionCallingMode;
-(function(FunctionCallingMode2) {
- FunctionCallingMode2["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED";
- FunctionCallingMode2["AUTO"] = "AUTO";
- FunctionCallingMode2["ANY"] = "ANY";
- FunctionCallingMode2["NONE"] = "NONE";
-})(FunctionCallingMode || (FunctionCallingMode = {}));
-var DynamicRetrievalMode;
-(function(DynamicRetrievalMode2) {
- DynamicRetrievalMode2["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED";
- DynamicRetrievalMode2["MODE_DYNAMIC"] = "MODE_DYNAMIC";
-})(DynamicRetrievalMode || (DynamicRetrievalMode = {}));
-
-class GoogleGenerativeAIError extends Error {
- constructor(message) {
- super(`[GoogleGenerativeAI Error]: ${message}`);
- }
-}
-
-class GoogleGenerativeAIResponseError extends GoogleGenerativeAIError {
- constructor(message, response) {
- super(message);
- this.response = response;
- }
-}
-
-class GoogleGenerativeAIFetchError extends GoogleGenerativeAIError {
- constructor(message, status, statusText, errorDetails) {
- super(message);
- this.status = status;
- this.statusText = statusText;
- this.errorDetails = errorDetails;
- }
-}
-
-class GoogleGenerativeAIRequestInputError extends GoogleGenerativeAIError {
-}
-
-class GoogleGenerativeAIAbortError extends GoogleGenerativeAIError {
-}
-var DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com";
-var DEFAULT_API_VERSION = "v1beta";
-var PACKAGE_VERSION = "0.24.1";
-var PACKAGE_LOG_HEADER = "genai-js";
-var Task;
-(function(Task2) {
- Task2["GENERATE_CONTENT"] = "generateContent";
- Task2["STREAM_GENERATE_CONTENT"] = "streamGenerateContent";
- Task2["COUNT_TOKENS"] = "countTokens";
- Task2["EMBED_CONTENT"] = "embedContent";
- Task2["BATCH_EMBED_CONTENTS"] = "batchEmbedContents";
-})(Task || (Task = {}));
-
-class RequestUrl {
- constructor(model, task, apiKey, stream, requestOptions) {
- this.model = model;
- this.task = task;
- this.apiKey = apiKey;
- this.stream = stream;
- this.requestOptions = requestOptions;
- }
- toString() {
- var _a, _b;
- const apiVersion = ((_a = this.requestOptions) === null || _a === undefined ? undefined : _a.apiVersion) || DEFAULT_API_VERSION;
- const baseUrl2 = ((_b = this.requestOptions) === null || _b === undefined ? undefined : _b.baseUrl) || DEFAULT_BASE_URL;
- let url = `${baseUrl2}/${apiVersion}/${this.model}:${this.task}`;
- if (this.stream) {
- url += "?alt=sse";
- }
- return url;
- }
-}
-function getClientHeaders(requestOptions) {
- const clientHeaders = [];
- if (requestOptions === null || requestOptions === undefined ? undefined : requestOptions.apiClient) {
- clientHeaders.push(requestOptions.apiClient);
- }
- clientHeaders.push(`${PACKAGE_LOG_HEADER}/${PACKAGE_VERSION}`);
- return clientHeaders.join(" ");
-}
-async function getHeaders(url) {
- var _a;
- const headers = new Headers;
- headers.append("Content-Type", "application/json");
- headers.append("x-goog-api-client", getClientHeaders(url.requestOptions));
- headers.append("x-goog-api-key", url.apiKey);
- let customHeaders = (_a = url.requestOptions) === null || _a === undefined ? undefined : _a.customHeaders;
- if (customHeaders) {
- if (!(customHeaders instanceof Headers)) {
- try {
- customHeaders = new Headers(customHeaders);
- } catch (e3) {
- throw new GoogleGenerativeAIRequestInputError(`unable to convert customHeaders value ${JSON.stringify(customHeaders)} to Headers: ${e3.message}`);
- }
- }
- for (const [headerName, headerValue] of customHeaders.entries()) {
- if (headerName === "x-goog-api-key") {
- throw new GoogleGenerativeAIRequestInputError(`Cannot set reserved header name ${headerName}`);
- } else if (headerName === "x-goog-api-client") {
- throw new GoogleGenerativeAIRequestInputError(`Header name ${headerName} can only be set using the apiClient field`);
- }
- headers.append(headerName, headerValue);
- }
- }
- return headers;
-}
-async function constructModelRequest(model, task, apiKey, stream, body, requestOptions) {
- const url = new RequestUrl(model, task, apiKey, stream, requestOptions);
- return {
- url: url.toString(),
- fetchOptions: Object.assign(Object.assign({}, buildFetchOptions(requestOptions)), { method: "POST", headers: await getHeaders(url), body })
- };
-}
-async function makeModelRequest(model, task, apiKey, stream, body, requestOptions = {}, fetchFn = fetch) {
- const { url, fetchOptions } = await constructModelRequest(model, task, apiKey, stream, body, requestOptions);
- return makeRequest(url, fetchOptions, fetchFn);
-}
-async function makeRequest(url, fetchOptions, fetchFn = fetch) {
- let response;
- try {
- response = await fetchFn(url, fetchOptions);
- } catch (e3) {
- handleResponseError(e3, url);
- }
- if (!response.ok) {
- await handleResponseNotOk(response, url);
- }
- return response;
-}
-function handleResponseError(e3, url) {
- let err = e3;
- if (err.name === "AbortError") {
- err = new GoogleGenerativeAIAbortError(`Request aborted when fetching ${url.toString()}: ${e3.message}`);
- err.stack = e3.stack;
- } else if (!(e3 instanceof GoogleGenerativeAIFetchError || e3 instanceof GoogleGenerativeAIRequestInputError)) {
- err = new GoogleGenerativeAIError(`Error fetching from ${url.toString()}: ${e3.message}`);
- err.stack = e3.stack;
- }
- throw err;
-}
-async function handleResponseNotOk(response, url) {
- let message = "";
- let errorDetails;
- try {
- const json2 = await response.json();
- message = json2.error.message;
- if (json2.error.details) {
- message += ` ${JSON.stringify(json2.error.details)}`;
- errorDetails = json2.error.details;
- }
- } catch (e3) {}
- throw new GoogleGenerativeAIFetchError(`Error fetching from ${url.toString()}: [${response.status} ${response.statusText}] ${message}`, response.status, response.statusText, errorDetails);
-}
-function buildFetchOptions(requestOptions) {
- const fetchOptions = {};
- if ((requestOptions === null || requestOptions === undefined ? undefined : requestOptions.signal) !== undefined || (requestOptions === null || requestOptions === undefined ? undefined : requestOptions.timeout) >= 0) {
- const controller = new AbortController;
- if ((requestOptions === null || requestOptions === undefined ? undefined : requestOptions.timeout) >= 0) {
- setTimeout(() => controller.abort(), requestOptions.timeout);
- }
- if (requestOptions === null || requestOptions === undefined ? undefined : requestOptions.signal) {
- requestOptions.signal.addEventListener("abort", () => {
- controller.abort();
- });
- }
- fetchOptions.signal = controller.signal;
- }
- return fetchOptions;
-}
-function addHelpers(response) {
- response.text = () => {
- if (response.candidates && response.candidates.length > 0) {
- if (response.candidates.length > 1) {
- console.warn(`This response had ${response.candidates.length} ` + `candidates. Returning text from the first candidate only. ` + `Access response.candidates directly to use the other candidates.`);
- }
- if (hadBadFinishReason(response.candidates[0])) {
- throw new GoogleGenerativeAIResponseError(`${formatBlockErrorMessage(response)}`, response);
- }
- return getText(response);
- } else if (response.promptFeedback) {
- throw new GoogleGenerativeAIResponseError(`Text not available. ${formatBlockErrorMessage(response)}`, response);
- }
- return "";
- };
- response.functionCall = () => {
- if (response.candidates && response.candidates.length > 0) {
- if (response.candidates.length > 1) {
- console.warn(`This response had ${response.candidates.length} ` + `candidates. Returning function calls from the first candidate only. ` + `Access response.candidates directly to use the other candidates.`);
- }
- if (hadBadFinishReason(response.candidates[0])) {
- throw new GoogleGenerativeAIResponseError(`${formatBlockErrorMessage(response)}`, response);
- }
- console.warn(`response.functionCall() is deprecated. ` + `Use response.functionCalls() instead.`);
- return getFunctionCalls(response)[0];
- } else if (response.promptFeedback) {
- throw new GoogleGenerativeAIResponseError(`Function call not available. ${formatBlockErrorMessage(response)}`, response);
- }
- return;
- };
- response.functionCalls = () => {
- if (response.candidates && response.candidates.length > 0) {
- if (response.candidates.length > 1) {
- console.warn(`This response had ${response.candidates.length} ` + `candidates. Returning function calls from the first candidate only. ` + `Access response.candidates directly to use the other candidates.`);
- }
- if (hadBadFinishReason(response.candidates[0])) {
- throw new GoogleGenerativeAIResponseError(`${formatBlockErrorMessage(response)}`, response);
- }
- return getFunctionCalls(response);
- } else if (response.promptFeedback) {
- throw new GoogleGenerativeAIResponseError(`Function call not available. ${formatBlockErrorMessage(response)}`, response);
- }
- return;
- };
- return response;
-}
-function getText(response) {
- var _a, _b, _c2, _d2;
- const textStrings = [];
- if ((_b = (_a = response.candidates) === null || _a === undefined ? undefined : _a[0].content) === null || _b === undefined ? undefined : _b.parts) {
- for (const part of (_d2 = (_c2 = response.candidates) === null || _c2 === undefined ? undefined : _c2[0].content) === null || _d2 === undefined ? undefined : _d2.parts) {
- if (part.text) {
- textStrings.push(part.text);
- }
- if (part.executableCode) {
- textStrings.push("\n```" + part.executableCode.language + `
-` + part.executableCode.code + "\n```\n");
- }
- if (part.codeExecutionResult) {
- textStrings.push("\n```\n" + part.codeExecutionResult.output + "\n```\n");
- }
- }
- }
- if (textStrings.length > 0) {
- return textStrings.join("");
- } else {
- return "";
- }
-}
-function getFunctionCalls(response) {
- var _a, _b, _c2, _d2;
- const functionCalls = [];
- if ((_b = (_a = response.candidates) === null || _a === undefined ? undefined : _a[0].content) === null || _b === undefined ? undefined : _b.parts) {
- for (const part of (_d2 = (_c2 = response.candidates) === null || _c2 === undefined ? undefined : _c2[0].content) === null || _d2 === undefined ? undefined : _d2.parts) {
- if (part.functionCall) {
- functionCalls.push(part.functionCall);
- }
- }
- }
- if (functionCalls.length > 0) {
- return functionCalls;
- } else {
- return;
- }
-}
-var badFinishReasons = [
- FinishReason.RECITATION,
- FinishReason.SAFETY,
- FinishReason.LANGUAGE
-];
-function hadBadFinishReason(candidate) {
- return !!candidate.finishReason && badFinishReasons.includes(candidate.finishReason);
-}
-function formatBlockErrorMessage(response) {
- var _a, _b, _c2;
- let message = "";
- if ((!response.candidates || response.candidates.length === 0) && response.promptFeedback) {
- message += "Response was blocked";
- if ((_a = response.promptFeedback) === null || _a === undefined ? undefined : _a.blockReason) {
- message += ` due to ${response.promptFeedback.blockReason}`;
- }
- if ((_b = response.promptFeedback) === null || _b === undefined ? undefined : _b.blockReasonMessage) {
- message += `: ${response.promptFeedback.blockReasonMessage}`;
- }
- } else if ((_c2 = response.candidates) === null || _c2 === undefined ? undefined : _c2[0]) {
- const firstCandidate = response.candidates[0];
- if (hadBadFinishReason(firstCandidate)) {
- message += `Candidate was blocked due to ${firstCandidate.finishReason}`;
- if (firstCandidate.finishMessage) {
- message += `: ${firstCandidate.finishMessage}`;
- }
- }
- }
- return message;
-}
-function __await2(v2) {
- return this instanceof __await2 ? (this.v = v2, this) : new __await2(v2);
-}
-function __asyncGenerator2(thisArg, _arguments, generator) {
- if (!Symbol.asyncIterator)
- throw new TypeError("Symbol.asyncIterator is not defined.");
- var g2 = generator.apply(thisArg, _arguments || []), i2, q2 = [];
- return i2 = {}, verb("next"), verb("throw"), verb("return"), i2[Symbol.asyncIterator] = function() {
- return this;
- }, i2;
- function verb(n2) {
- if (g2[n2])
- i2[n2] = function(v2) {
- return new Promise(function(a2, b2) {
- q2.push([n2, v2, a2, b2]) > 1 || resume(n2, v2);
- });
- };
- }
- function resume(n2, v2) {
- try {
- step(g2[n2](v2));
- } catch (e3) {
- settle(q2[0][3], e3);
- }
- }
- function step(r2) {
- r2.value instanceof __await2 ? Promise.resolve(r2.value.v).then(fulfill, reject) : settle(q2[0][2], r2);
- }
- function fulfill(value) {
- resume("next", value);
- }
- function reject(value) {
- resume("throw", value);
- }
- function settle(f2, v2) {
- if (f2(v2), q2.shift(), q2.length)
- resume(q2[0][0], q2[0][1]);
- }
-}
-var responseLineRE = /^data\: (.*)(?:\n\n|\r\r|\r\n\r\n)/;
-function processStream(response) {
- const inputStream = response.body.pipeThrough(new TextDecoderStream("utf8", { fatal: true }));
- const responseStream = getResponseStream(inputStream);
- const [stream1, stream2] = responseStream.tee();
- return {
- stream: generateResponseSequence(stream1),
- response: getResponsePromise(stream2)
- };
-}
-async function getResponsePromise(stream) {
- const allResponses = [];
- const reader = stream.getReader();
- while (true) {
- const { done, value } = await reader.read();
- if (done) {
- return addHelpers(aggregateResponses(allResponses));
- }
- allResponses.push(value);
- }
-}
-function generateResponseSequence(stream) {
- return __asyncGenerator2(this, arguments, function* generateResponseSequence_1() {
- const reader = stream.getReader();
- while (true) {
- const { value, done } = yield __await2(reader.read());
- if (done) {
- break;
- }
- yield yield __await2(addHelpers(value));
- }
- });
-}
-function getResponseStream(inputStream) {
- const reader = inputStream.getReader();
- const stream = new ReadableStream({
- start(controller) {
- let currentText = "";
- return pump();
- function pump() {
- return reader.read().then(({ value, done }) => {
- if (done) {
- if (currentText.trim()) {
- controller.error(new GoogleGenerativeAIError("Failed to parse stream"));
- return;
- }
- controller.close();
- return;
- }
- currentText += value;
- let match = currentText.match(responseLineRE);
- let parsedResponse;
- while (match) {
- try {
- parsedResponse = JSON.parse(match[1]);
- } catch (e3) {
- controller.error(new GoogleGenerativeAIError(`Error parsing JSON response: "${match[1]}"`));
- return;
- }
- controller.enqueue(parsedResponse);
- currentText = currentText.substring(match[0].length);
- match = currentText.match(responseLineRE);
- }
- return pump();
- }).catch((e3) => {
- let err = e3;
- err.stack = e3.stack;
- if (err.name === "AbortError") {
- err = new GoogleGenerativeAIAbortError("Request aborted when reading from the stream");
- } else {
- err = new GoogleGenerativeAIError("Error reading from the stream");
- }
- throw err;
- });
- }
- }
- });
- return stream;
-}
-function aggregateResponses(responses) {
- const lastResponse = responses[responses.length - 1];
- const aggregatedResponse = {
- promptFeedback: lastResponse === null || lastResponse === undefined ? undefined : lastResponse.promptFeedback
- };
- for (const response of responses) {
- if (response.candidates) {
- let candidateIndex = 0;
- for (const candidate of response.candidates) {
- if (!aggregatedResponse.candidates) {
- aggregatedResponse.candidates = [];
- }
- if (!aggregatedResponse.candidates[candidateIndex]) {
- aggregatedResponse.candidates[candidateIndex] = {
- index: candidateIndex
- };
- }
- aggregatedResponse.candidates[candidateIndex].citationMetadata = candidate.citationMetadata;
- aggregatedResponse.candidates[candidateIndex].groundingMetadata = candidate.groundingMetadata;
- aggregatedResponse.candidates[candidateIndex].finishReason = candidate.finishReason;
- aggregatedResponse.candidates[candidateIndex].finishMessage = candidate.finishMessage;
- aggregatedResponse.candidates[candidateIndex].safetyRatings = candidate.safetyRatings;
- if (candidate.content && candidate.content.parts) {
- if (!aggregatedResponse.candidates[candidateIndex].content) {
- aggregatedResponse.candidates[candidateIndex].content = {
- role: candidate.content.role || "user",
- parts: []
- };
- }
- const newPart = {};
- for (const part of candidate.content.parts) {
- if (part.text) {
- newPart.text = part.text;
- }
- if (part.functionCall) {
- newPart.functionCall = part.functionCall;
- }
- if (part.executableCode) {
- newPart.executableCode = part.executableCode;
- }
- if (part.codeExecutionResult) {
- newPart.codeExecutionResult = part.codeExecutionResult;
- }
- if (Object.keys(newPart).length === 0) {
- newPart.text = "";
- }
- aggregatedResponse.candidates[candidateIndex].content.parts.push(newPart);
- }
- }
- }
- candidateIndex++;
- }
- if (response.usageMetadata) {
- aggregatedResponse.usageMetadata = response.usageMetadata;
- }
- }
- return aggregatedResponse;
-}
-async function generateContentStream(apiKey, model, params, requestOptions) {
- const response = await makeModelRequest(model, Task.STREAM_GENERATE_CONTENT, apiKey, true, JSON.stringify(params), requestOptions);
- return processStream(response);
-}
-async function generateContent(apiKey, model, params, requestOptions) {
- const response = await makeModelRequest(model, Task.GENERATE_CONTENT, apiKey, false, JSON.stringify(params), requestOptions);
- const responseJson = await response.json();
- const enhancedResponse = addHelpers(responseJson);
- return {
- response: enhancedResponse
- };
-}
-function formatSystemInstruction(input) {
- if (input == null) {
- return;
- } else if (typeof input === "string") {
- return { role: "system", parts: [{ text: input }] };
- } else if (input.text) {
- return { role: "system", parts: [input] };
- } else if (input.parts) {
- if (!input.role) {
- return { role: "system", parts: input.parts };
- } else {
- return input;
- }
- }
-}
-function formatNewContent(request2) {
- let newParts = [];
- if (typeof request2 === "string") {
- newParts = [{ text: request2 }];
- } else {
- for (const partOrString of request2) {
- if (typeof partOrString === "string") {
- newParts.push({ text: partOrString });
- } else {
- newParts.push(partOrString);
- }
- }
- }
- return assignRoleToPartsAndValidateSendMessageRequest(newParts);
-}
-function assignRoleToPartsAndValidateSendMessageRequest(parts) {
- const userContent = { role: "user", parts: [] };
- const functionContent = { role: "function", parts: [] };
- let hasUserContent = false;
- let hasFunctionContent = false;
- for (const part of parts) {
- if ("functionResponse" in part) {
- functionContent.parts.push(part);
- hasFunctionContent = true;
- } else {
- userContent.parts.push(part);
- hasUserContent = true;
- }
- }
- if (hasUserContent && hasFunctionContent) {
- throw new GoogleGenerativeAIError("Within a single message, FunctionResponse cannot be mixed with other type of part in the request for sending chat message.");
- }
- if (!hasUserContent && !hasFunctionContent) {
- throw new GoogleGenerativeAIError("No content is provided for sending chat message.");
- }
- if (hasUserContent) {
- return userContent;
- }
- return functionContent;
-}
-function formatCountTokensInput(params, modelParams) {
- var _a;
- let formattedGenerateContentRequest = {
- model: modelParams === null || modelParams === undefined ? undefined : modelParams.model,
- generationConfig: modelParams === null || modelParams === undefined ? undefined : modelParams.generationConfig,
- safetySettings: modelParams === null || modelParams === undefined ? undefined : modelParams.safetySettings,
- tools: modelParams === null || modelParams === undefined ? undefined : modelParams.tools,
- toolConfig: modelParams === null || modelParams === undefined ? undefined : modelParams.toolConfig,
- systemInstruction: modelParams === null || modelParams === undefined ? undefined : modelParams.systemInstruction,
- cachedContent: (_a = modelParams === null || modelParams === undefined ? undefined : modelParams.cachedContent) === null || _a === undefined ? undefined : _a.name,
- contents: []
- };
- const containsGenerateContentRequest = params.generateContentRequest != null;
- if (params.contents) {
- if (containsGenerateContentRequest) {
- throw new GoogleGenerativeAIRequestInputError("CountTokensRequest must have one of contents or generateContentRequest, not both.");
- }
- formattedGenerateContentRequest.contents = params.contents;
- } else if (containsGenerateContentRequest) {
- formattedGenerateContentRequest = Object.assign(Object.assign({}, formattedGenerateContentRequest), params.generateContentRequest);
- } else {
- const content = formatNewContent(params);
- formattedGenerateContentRequest.contents = [content];
- }
- return { generateContentRequest: formattedGenerateContentRequest };
-}
-function formatGenerateContentInput(params) {
- let formattedRequest;
- if (params.contents) {
- formattedRequest = params;
- } else {
- const content = formatNewContent(params);
- formattedRequest = { contents: [content] };
- }
- if (params.systemInstruction) {
- formattedRequest.systemInstruction = formatSystemInstruction(params.systemInstruction);
- }
- return formattedRequest;
-}
-function formatEmbedContentInput(params) {
- if (typeof params === "string" || Array.isArray(params)) {
- const content = formatNewContent(params);
- return { content };
- }
- return params;
-}
-var VALID_PART_FIELDS = [
- "text",
- "inlineData",
- "functionCall",
- "functionResponse",
- "executableCode",
- "codeExecutionResult"
-];
-var VALID_PARTS_PER_ROLE = {
- user: ["text", "inlineData"],
- function: ["functionResponse"],
- model: ["text", "functionCall", "executableCode", "codeExecutionResult"],
- system: ["text"]
-};
-function validateChatHistory(history) {
- let prevContent = false;
- for (const currContent of history) {
- const { role, parts } = currContent;
- if (!prevContent && role !== "user") {
- throw new GoogleGenerativeAIError(`First content should be with role 'user', got ${role}`);
- }
- if (!POSSIBLE_ROLES.includes(role)) {
- throw new GoogleGenerativeAIError(`Each item should include role field. Got ${role} but valid roles are: ${JSON.stringify(POSSIBLE_ROLES)}`);
- }
- if (!Array.isArray(parts)) {
- throw new GoogleGenerativeAIError("Content should have 'parts' property with an array of Parts");
- }
- if (parts.length === 0) {
- throw new GoogleGenerativeAIError("Each Content should have at least one part");
- }
- const countFields = {
- text: 0,
- inlineData: 0,
- functionCall: 0,
- functionResponse: 0,
- fileData: 0,
- executableCode: 0,
- codeExecutionResult: 0
- };
- for (const part of parts) {
- for (const key of VALID_PART_FIELDS) {
- if (key in part) {
- countFields[key] += 1;
- }
- }
- }
- const validParts = VALID_PARTS_PER_ROLE[role];
- for (const key of VALID_PART_FIELDS) {
- if (!validParts.includes(key) && countFields[key] > 0) {
- throw new GoogleGenerativeAIError(`Content with role '${role}' can't contain '${key}' part`);
- }
- }
- prevContent = true;
- }
-}
-function isValidResponse(response) {
- var _a;
- if (response.candidates === undefined || response.candidates.length === 0) {
- return false;
- }
- const content = (_a = response.candidates[0]) === null || _a === undefined ? undefined : _a.content;
- if (content === undefined) {
- return false;
- }
- if (content.parts === undefined || content.parts.length === 0) {
- return false;
- }
- for (const part of content.parts) {
- if (part === undefined || Object.keys(part).length === 0) {
- return false;
- }
- if (part.text !== undefined && part.text === "") {
- return false;
- }
- }
- return true;
-}
-var SILENT_ERROR = "SILENT_ERROR";
-
-class ChatSession {
- constructor(apiKey, model, params, _requestOptions = {}) {
- this.model = model;
- this.params = params;
- this._requestOptions = _requestOptions;
- this._history = [];
- this._sendPromise = Promise.resolve();
- this._apiKey = apiKey;
- if (params === null || params === undefined ? undefined : params.history) {
- validateChatHistory(params.history);
- this._history = params.history;
- }
- }
- async getHistory() {
- await this._sendPromise;
- return this._history;
- }
- async sendMessage(request2, requestOptions = {}) {
- var _a, _b, _c2, _d2, _e2, _f;
- await this._sendPromise;
- const newContent = formatNewContent(request2);
- const generateContentRequest = {
- safetySettings: (_a = this.params) === null || _a === undefined ? undefined : _a.safetySettings,
- generationConfig: (_b = this.params) === null || _b === undefined ? undefined : _b.generationConfig,
- tools: (_c2 = this.params) === null || _c2 === undefined ? undefined : _c2.tools,
- toolConfig: (_d2 = this.params) === null || _d2 === undefined ? undefined : _d2.toolConfig,
- systemInstruction: (_e2 = this.params) === null || _e2 === undefined ? undefined : _e2.systemInstruction,
- cachedContent: (_f = this.params) === null || _f === undefined ? undefined : _f.cachedContent,
- contents: [...this._history, newContent]
- };
- const chatSessionRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
- let finalResult;
- this._sendPromise = this._sendPromise.then(() => generateContent(this._apiKey, this.model, generateContentRequest, chatSessionRequestOptions)).then((result) => {
- var _a2;
- if (isValidResponse(result.response)) {
- this._history.push(newContent);
- const responseContent = Object.assign({
- parts: [],
- role: "model"
- }, (_a2 = result.response.candidates) === null || _a2 === undefined ? undefined : _a2[0].content);
- this._history.push(responseContent);
- } else {
- const blockErrorMessage = formatBlockErrorMessage(result.response);
- if (blockErrorMessage) {
- console.warn(`sendMessage() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.`);
- }
- }
- finalResult = result;
- }).catch((e3) => {
- this._sendPromise = Promise.resolve();
- throw e3;
- });
- await this._sendPromise;
- return finalResult;
- }
- async sendMessageStream(request2, requestOptions = {}) {
- var _a, _b, _c2, _d2, _e2, _f;
- await this._sendPromise;
- const newContent = formatNewContent(request2);
- const generateContentRequest = {
- safetySettings: (_a = this.params) === null || _a === undefined ? undefined : _a.safetySettings,
- generationConfig: (_b = this.params) === null || _b === undefined ? undefined : _b.generationConfig,
- tools: (_c2 = this.params) === null || _c2 === undefined ? undefined : _c2.tools,
- toolConfig: (_d2 = this.params) === null || _d2 === undefined ? undefined : _d2.toolConfig,
- systemInstruction: (_e2 = this.params) === null || _e2 === undefined ? undefined : _e2.systemInstruction,
- cachedContent: (_f = this.params) === null || _f === undefined ? undefined : _f.cachedContent,
- contents: [...this._history, newContent]
- };
- const chatSessionRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
- const streamPromise = generateContentStream(this._apiKey, this.model, generateContentRequest, chatSessionRequestOptions);
- this._sendPromise = this._sendPromise.then(() => streamPromise).catch((_ignored) => {
- throw new Error(SILENT_ERROR);
- }).then((streamResult) => streamResult.response).then((response) => {
- if (isValidResponse(response)) {
- this._history.push(newContent);
- const responseContent = Object.assign({}, response.candidates[0].content);
- if (!responseContent.role) {
- responseContent.role = "model";
- }
- this._history.push(responseContent);
- } else {
- const blockErrorMessage = formatBlockErrorMessage(response);
- if (blockErrorMessage) {
- console.warn(`sendMessageStream() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.`);
- }
- }
- }).catch((e3) => {
- if (e3.message !== SILENT_ERROR) {
- console.error(e3);
- }
- });
- return streamPromise;
- }
-}
-async function countTokens(apiKey, model, params, singleRequestOptions) {
- const response = await makeModelRequest(model, Task.COUNT_TOKENS, apiKey, false, JSON.stringify(params), singleRequestOptions);
- return response.json();
-}
-async function embedContent(apiKey, model, params, requestOptions) {
- const response = await makeModelRequest(model, Task.EMBED_CONTENT, apiKey, false, JSON.stringify(params), requestOptions);
- return response.json();
-}
-async function batchEmbedContents(apiKey, model, params, requestOptions) {
- const requestsWithModel = params.requests.map((request2) => {
- return Object.assign(Object.assign({}, request2), { model });
- });
- const response = await makeModelRequest(model, Task.BATCH_EMBED_CONTENTS, apiKey, false, JSON.stringify({ requests: requestsWithModel }), requestOptions);
- return response.json();
-}
-
-class GenerativeModel {
- constructor(apiKey, modelParams, _requestOptions = {}) {
- this.apiKey = apiKey;
- this._requestOptions = _requestOptions;
- if (modelParams.model.includes("/")) {
- this.model = modelParams.model;
- } else {
- this.model = `models/${modelParams.model}`;
- }
- this.generationConfig = modelParams.generationConfig || {};
- this.safetySettings = modelParams.safetySettings || [];
- this.tools = modelParams.tools;
- this.toolConfig = modelParams.toolConfig;
- this.systemInstruction = formatSystemInstruction(modelParams.systemInstruction);
- this.cachedContent = modelParams.cachedContent;
- }
- async generateContent(request2, requestOptions = {}) {
- var _a;
- const formattedParams = formatGenerateContentInput(request2);
- const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
- return generateContent(this.apiKey, this.model, Object.assign({ generationConfig: this.generationConfig, safetySettings: this.safetySettings, tools: this.tools, toolConfig: this.toolConfig, systemInstruction: this.systemInstruction, cachedContent: (_a = this.cachedContent) === null || _a === undefined ? undefined : _a.name }, formattedParams), generativeModelRequestOptions);
- }
- async generateContentStream(request2, requestOptions = {}) {
- var _a;
- const formattedParams = formatGenerateContentInput(request2);
- const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
- return generateContentStream(this.apiKey, this.model, Object.assign({ generationConfig: this.generationConfig, safetySettings: this.safetySettings, tools: this.tools, toolConfig: this.toolConfig, systemInstruction: this.systemInstruction, cachedContent: (_a = this.cachedContent) === null || _a === undefined ? undefined : _a.name }, formattedParams), generativeModelRequestOptions);
- }
- startChat(startChatParams) {
- var _a;
- return new ChatSession(this.apiKey, this.model, Object.assign({ generationConfig: this.generationConfig, safetySettings: this.safetySettings, tools: this.tools, toolConfig: this.toolConfig, systemInstruction: this.systemInstruction, cachedContent: (_a = this.cachedContent) === null || _a === undefined ? undefined : _a.name }, startChatParams), this._requestOptions);
- }
- async countTokens(request2, requestOptions = {}) {
- const formattedParams = formatCountTokensInput(request2, {
- model: this.model,
- generationConfig: this.generationConfig,
- safetySettings: this.safetySettings,
- tools: this.tools,
- toolConfig: this.toolConfig,
- systemInstruction: this.systemInstruction,
- cachedContent: this.cachedContent
- });
- const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
- return countTokens(this.apiKey, this.model, formattedParams, generativeModelRequestOptions);
- }
- async embedContent(request2, requestOptions = {}) {
- const formattedParams = formatEmbedContentInput(request2);
- const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
- return embedContent(this.apiKey, this.model, formattedParams, generativeModelRequestOptions);
- }
- async batchEmbedContents(batchEmbedContentRequest, requestOptions = {}) {
- const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
- return batchEmbedContents(this.apiKey, this.model, batchEmbedContentRequest, generativeModelRequestOptions);
- }
-}
-
-class GoogleGenerativeAI {
- constructor(apiKey) {
- this.apiKey = apiKey;
- }
- getGenerativeModel(modelParams, requestOptions) {
- if (!modelParams.model) {
- throw new GoogleGenerativeAIError(`Must provide a model name. ` + `Example: genai.getGenerativeModel({ model: 'my-model-name' })`);
- }
- return new GenerativeModel(this.apiKey, modelParams, requestOptions);
- }
- getGenerativeModelFromCachedContent(cachedContent, modelParams, requestOptions) {
- if (!cachedContent.name) {
- throw new GoogleGenerativeAIRequestInputError("Cached content must contain a `name` field.");
- }
- if (!cachedContent.model) {
- throw new GoogleGenerativeAIRequestInputError("Cached content must contain a `model` field.");
- }
- const disallowedDuplicates = ["model", "systemInstruction"];
- for (const key of disallowedDuplicates) {
- if ((modelParams === null || modelParams === undefined ? undefined : modelParams[key]) && cachedContent[key] && (modelParams === null || modelParams === undefined ? undefined : modelParams[key]) !== cachedContent[key]) {
- if (key === "model") {
- const modelParamsComp = modelParams.model.startsWith("models/") ? modelParams.model.replace("models/", "") : modelParams.model;
- const cachedContentComp = cachedContent.model.startsWith("models/") ? cachedContent.model.replace("models/", "") : cachedContent.model;
- if (modelParamsComp === cachedContentComp) {
- continue;
- }
- }
- throw new GoogleGenerativeAIRequestInputError(`Different value for "${key}" specified in modelParams` + ` (${modelParams[key]}) and cachedContent (${cachedContent[key]})`);
- }
- }
- const modelParamsFromCache = Object.assign(Object.assign({}, modelParams), { model: cachedContent.model, tools: cachedContent.tools, toolConfig: cachedContent.toolConfig, systemInstruction: cachedContent.systemInstruction, cachedContent });
- return new GenerativeModel(this.apiKey, modelParamsFromCache, requestOptions);
- }
-}
-
// node_modules/.pnpm/axios@1.15.0/node_modules/axios/lib/helpers/bind.js
function bind(fn, thisArg) {
return function wrap() {
@@ -175302,11 +171541,11 @@ var extend = (a2, b2, thisArg, { allOwnKeys } = {}) => {
}, { allOwnKeys });
return a2;
};
-var stripBOM = (content) => {
- if (content.charCodeAt(0) === 65279) {
- content = content.slice(1);
+var stripBOM = (content52) => {
+ if (content52.charCodeAt(0) === 65279) {
+ content52 = content52.slice(1);
}
- return content;
+ return content52;
};
var inherits = (constructor, superConstructor, props, descriptors) => {
constructor.prototype = Object.create(superConstructor.prototype, descriptors);
@@ -175343,14 +171582,14 @@ var toFlatObject = (sourceObj, destObj, filter, propFilter) => {
} while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype);
return destObj;
};
-var endsWith = (str, searchString, position) => {
+var endsWith = (str, searchString, position3) => {
str = String(str);
- if (position === undefined || position > str.length) {
- position = str.length;
+ if (position3 === undefined || position3 > str.length) {
+ position3 = str.length;
}
- position -= searchString.length;
- const lastIndex = str.indexOf(searchString, position);
- return lastIndex !== -1 && lastIndex === position;
+ position3 -= searchString.length;
+ const lastIndex = str.indexOf(searchString, position3);
+ return lastIndex !== -1 && lastIndex === position3;
};
var toArray2 = (thing) => {
if (!thing)
@@ -175456,13 +171695,13 @@ var toJSONObject = (obj) => {
}
if (!("toJSON" in source)) {
stack[i2] = source;
- const target = isArray(source) ? [] : {};
+ const target2 = isArray(source) ? [] : {};
forEach2(source, (value, key) => {
const reducedValue = visit(value, i2 + 1);
- !isUndefined(reducedValue) && (target[key] = reducedValue);
+ !isUndefined(reducedValue) && (target2[key] = reducedValue);
});
stack[i2] = undefined;
- return target;
+ return target2;
}
}
return source;
@@ -175686,8 +171925,8 @@ function toFormData(obj, formData, options) {
value = JSON.stringify(value);
} else if (utils_default.isArray(value) && isFlatArray(value) || (utils_default.isFileList(value) || utils_default.endsWith(key, "[]")) && (arr = utils_default.toArray(value))) {
key = removeBrackets(key);
- arr.forEach(function each(el, index2) {
- !(utils_default.isUndefined(el) || el === null) && formData.append(indexes === true ? renderKey([key], index2, dots) : indexes === null ? key : key + "[]", convertValue(el));
+ arr.forEach(function each(el, index3) {
+ !(utils_default.isUndefined(el) || el === null) && formData.append(indexes === true ? renderKey([key], index3, dots) : indexes === null ? key : key + "[]", convertValue(el));
});
return false;
}
@@ -175728,7 +171967,7 @@ function toFormData(obj, formData, options) {
var toFormData_default = toFormData;
// node_modules/.pnpm/axios@1.15.0/node_modules/axios/lib/helpers/AxiosURLSearchParams.js
-function encode(str) {
+function encode2(str) {
const charMap = {
"!": "%21",
"'": "%27",
@@ -175752,8 +171991,8 @@ prototype.append = function append(name, value) {
};
prototype.toString = function toString3(encoder) {
const _encode = encoder ? function(value) {
- return encoder.call(this, value, encode);
- } : encode;
+ return encoder.call(this, value, encode2);
+ } : encode2;
return this._pairs.map(function each(pair) {
return _encode(pair[0]) + "=" + _encode(pair[1]);
}, "").join("&");
@@ -175761,14 +172000,14 @@ prototype.toString = function toString3(encoder) {
var AxiosURLSearchParams_default = AxiosURLSearchParams;
// node_modules/.pnpm/axios@1.15.0/node_modules/axios/lib/helpers/buildURL.js
-function encode2(val) {
+function encode3(val) {
return encodeURIComponent(val).replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%20/g, "+");
}
function buildURL(url, params, options) {
if (!params) {
return url;
}
- const _encode = options && options.encode || encode2;
+ const _encode = options && options.encode || encode3;
const _options = utils_default.isFunction(options) ? {
serialize: options
} : options;
@@ -175924,27 +172163,27 @@ function arrayToObject(arr) {
return obj;
}
function formDataToJSON(formData) {
- function buildPath(path2, value, target, index2) {
- let name = path2[index2++];
+ function buildPath(path2, value, target2, index3) {
+ let name = path2[index3++];
if (name === "__proto__")
return true;
const isNumericKey = Number.isFinite(+name);
- const isLast = index2 >= path2.length;
- name = !name && utils_default.isArray(target) ? target.length : name;
+ const isLast = index3 >= path2.length;
+ name = !name && utils_default.isArray(target2) ? target2.length : name;
if (isLast) {
- if (utils_default.hasOwnProp(target, name)) {
- target[name] = [target[name], value];
+ if (utils_default.hasOwnProp(target2, name)) {
+ target2[name] = [target2[name], value];
} else {
- target[name] = value;
+ target2[name] = value;
}
return !isNumericKey;
}
- if (!target[name] || !utils_default.isObject(target[name])) {
- target[name] = [];
+ if (!target2[name] || !utils_default.isObject(target2[name])) {
+ target2[name] = [];
}
- const result = buildPath(path2, value, target[name], index2);
- if (result && utils_default.isArray(target[name])) {
- target[name] = arrayToObject(target[name]);
+ const result = buildPath(path2, value, target2[name], index3);
+ if (result && utils_default.isArray(target2[name])) {
+ target2[name] = arrayToObject(target2[name]);
}
return !isNumericKey;
}
@@ -176090,10 +172329,10 @@ var parseHeaders_default = (rawHeaders) => {
let val;
let i2;
rawHeaders && rawHeaders.split(`
-`).forEach(function parser(line2) {
- i2 = line2.indexOf(":");
- key = line2.substring(0, i2).trim().toLowerCase();
- val = line2.substring(i2 + 1).trim();
+`).forEach(function parser(line3) {
+ i2 = line3.indexOf(":");
+ key = line3.substring(0, i2).trim().toLowerCase();
+ val = line3.substring(i2 + 1).trim();
if (!key || parsed[key] && ignoreDuplicateOf[key]) {
return;
}
@@ -176172,8 +172411,8 @@ function matchHeaderValue(context, value, header, filter2, isHeaderNameFilter) {
}
}
function formatHeader(header) {
- return header.trim().toLowerCase().replace(/([a-z\d])(\w*)/g, (w2, char2, str) => {
- return char2.toUpperCase() + str;
+ return header.trim().toLowerCase().replace(/([a-z\d])(\w*)/g, (w2, char3, str) => {
+ return char3.toUpperCase() + str;
});
}
function buildAccessors(obj, header) {
@@ -176334,7 +172573,7 @@ class AxiosHeaders {
}
static concat(first, ...targets) {
const computed = new this(first);
- targets.forEach((target) => computed.set(target));
+ targets.forEach((target2) => computed.set(target2));
return computed;
}
static accessor(header) {
@@ -176667,7 +172906,7 @@ class AxiosTransformStream extends stream.Transform {
var AxiosTransformStream_default = AxiosTransformStream;
// node_modules/.pnpm/axios@1.15.0/node_modules/axios/lib/adapters/http.js
-import { EventEmitter } from "events";
+import { EventEmitter as EventEmitter3 } from "events";
// node_modules/.pnpm/axios@1.15.0/node_modules/axios/lib/helpers/formDataToStream.js
import util from "util";
@@ -176690,10 +172929,10 @@ var readBlob_default = readBlob;
// node_modules/.pnpm/axios@1.15.0/node_modules/axios/lib/helpers/formDataToStream.js
var BOUNDARY_ALPHABET = platform_default.ALPHABET.ALPHA_DIGIT + "-_";
-var textEncoder = typeof TextEncoder === "function" ? new TextEncoder : new util.TextEncoder;
+var textEncoder3 = typeof TextEncoder === "function" ? new TextEncoder : new util.TextEncoder;
var CRLF = `\r
`;
-var CRLF_BYTES = textEncoder.encode(CRLF);
+var CRLF_BYTES = textEncoder3.encode(CRLF);
var CRLF_BYTES_COUNT = 2;
class FormDataPart {
@@ -176702,11 +172941,11 @@ class FormDataPart {
const isStringValue = utils_default.isString(value);
let headers = `Content-Disposition: form-data; name="${escapeName(name)}"${!isStringValue && value.name ? `; filename="${escapeName(value.name)}"` : ""}${CRLF}`;
if (isStringValue) {
- value = textEncoder.encode(String(value).replace(/\r?\n|\r\n?/g, CRLF));
+ value = textEncoder3.encode(String(value).replace(/\r?\n|\r\n?/g, CRLF));
} else {
headers += `Content-Type: ${value.type || "application/octet-stream"}${CRLF}`;
}
- this.headers = textEncoder.encode(headers + CRLF);
+ this.headers = textEncoder3.encode(headers + CRLF);
this.contentLength = isStringValue ? value.byteLength : value.size;
this.size = this.headers.byteLength + this.contentLength + CRLF_BYTES_COUNT;
this.name = name;
@@ -176732,9 +172971,9 @@ class FormDataPart {
}
var formDataToStream = (form, headersHandler, options) => {
const {
- tag: tag2 = "form-data-boundary",
+ tag: tag3 = "form-data-boundary",
size = 25,
- boundary = tag2 + "-" + platform_default.generateString(size, BOUNDARY_ALPHABET)
+ boundary = tag3 + "-" + platform_default.generateString(size, BOUNDARY_ALPHABET)
} = options || {};
if (!utils_default.isFormData(form)) {
throw TypeError("FormData instance required");
@@ -176742,8 +172981,8 @@ var formDataToStream = (form, headersHandler, options) => {
if (boundary.length < 1 || boundary.length > 70) {
throw Error("boundary must be 10-70 characters long");
}
- const boundaryBytes = textEncoder.encode("--" + boundary + CRLF);
- const footerBytes = textEncoder.encode("--" + boundary + "--" + CRLF);
+ const boundaryBytes = textEncoder3.encode("--" + boundary + CRLF);
+ const footerBytes = textEncoder3.encode("--" + boundary + "--" + CRLF);
let contentLength = footerBytes.byteLength;
const parts = Array.from(form.entries()).map(([name, value]) => {
const part = new FormDataPart(name, value);
@@ -176922,12 +173161,12 @@ var speedometer_default = speedometer;
// node_modules/.pnpm/axios@1.15.0/node_modules/axios/lib/helpers/throttle.js
function throttle(fn, freq) {
- let timestamp2 = 0;
+ let timestamp3 = 0;
let threshold = 1000 / freq;
let lastArgs;
let timer;
const invoke = (args, now = Date.now()) => {
- timestamp2 = now;
+ timestamp3 = now;
lastArgs = null;
if (timer) {
clearTimeout(timer);
@@ -176937,7 +173176,7 @@ function throttle(fn, freq) {
};
const throttled = (...args) => {
const now = Date.now();
- const passed = now - timestamp2;
+ const passed = now - timestamp3;
if (passed >= threshold) {
invoke(args, now);
} else {
@@ -177083,7 +173322,7 @@ class Http2Sessions {
}
}
}
- const session2 = http2.connect(authority, options);
+ const session3 = http2.connect(authority, options);
let removed;
const removeSession = () => {
if (removed) {
@@ -177092,25 +173331,25 @@ class Http2Sessions {
removed = true;
let entries = authoritySessions, len = entries.length, i2 = len;
while (i2--) {
- if (entries[i2][0] === session2) {
+ if (entries[i2][0] === session3) {
if (len === 1) {
delete this.sessions[authority];
} else {
entries.splice(i2, 1);
}
- if (!session2.closed) {
- session2.close();
+ if (!session3.closed) {
+ session3.close();
}
return;
}
}
};
- const originalRequestFn = session2.request;
+ const originalRequestFn = session3.request;
const { sessionTimeout } = options;
if (sessionTimeout != null) {
let timer;
let streamsCount = 0;
- session2.request = function() {
+ session3.request = function() {
const stream4 = originalRequestFn.apply(this, arguments);
streamsCount++;
if (timer) {
@@ -177128,10 +173367,10 @@ class Http2Sessions {
return stream4;
};
}
- session2.once("close", removeSession);
- let entry = [session2, options];
+ session3.once("close", removeSession);
+ let entry = [session3, options];
authoritySessions ? authoritySessions.push(entry) : authoritySessions = this.sessions[authority] = [entry];
- return session2;
+ return session3;
}
}
var http2Sessions = new Http2Sessions;
@@ -177217,7 +173456,7 @@ var http2Transport = {
request(options, cb2) {
const authority = options.protocol + "//" + options.hostname + ":" + (options.port || (options.protocol === "https:" ? 443 : 80));
const { http2Options, headers } = options;
- const session2 = http2Sessions.getSession(authority, http2Options);
+ const session3 = http2Sessions.getSession(authority, http2Options);
const { HTTP2_HEADER_SCHEME, HTTP2_HEADER_METHOD, HTTP2_HEADER_PATH, HTTP2_HEADER_STATUS } = http2.constants;
const http2Headers = {
[HTTP2_HEADER_SCHEME]: options.protocol.replace(":", ""),
@@ -177227,7 +173466,7 @@ var http2Transport = {
utils_default.forEach(headers, (header, name) => {
name.charAt(0) !== ":" && (http2Headers[name] = header);
});
- const req = session2.request(http2Headers);
+ const req = session3.request(http2Headers);
req.once("response", (responseHeaders) => {
const response = req;
responseHeaders = Object.assign({}, responseHeaders);
@@ -177268,7 +173507,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) {
});
};
}
- const abortEmitter = new EventEmitter;
+ const abortEmitter = new EventEmitter3;
function abort(reason) {
try {
abortEmitter.emit("abort", !reason || reason.type ? new CanceledError_default(null, config, req) : reason);
@@ -177687,9 +173926,9 @@ var headersToObject = (thing) => thing instanceof AxiosHeaders_default ? { ...th
function mergeConfig(config1, config2) {
config2 = config2 || {};
const config = {};
- function getMergedValue(target, source, prop, caseless) {
- if (utils_default.isPlainObject(target) && utils_default.isPlainObject(source)) {
- return utils_default.merge.call({ caseless }, target, source);
+ function getMergedValue(target2, source, prop, caseless) {
+ if (utils_default.isPlainObject(target2) && utils_default.isPlainObject(source)) {
+ return utils_default.merge.call({ caseless }, target2, source);
} else if (utils_default.isPlainObject(source)) {
return utils_default.merge({}, source);
} else if (utils_default.isArray(source)) {
@@ -178215,14 +174454,14 @@ var getFetch = (config) => {
let env3 = config && config.env || {};
const { fetch: fetch2, Request: Request2, Response: Response2 } = env3;
const seeds = [Request2, Response2, fetch2];
- let len = seeds.length, i2 = len, seed, target, map = seedCache;
+ let len = seeds.length, i2 = len, seed, target2, map = seedCache;
while (i2--) {
seed = seeds[i2];
- target = map.get(seed);
- target === undefined && map.set(seed, target = i2 ? new Map : factory(env3));
- map = target;
+ target2 = map.get(seed);
+ target2 === undefined && map.set(seed, target2 = i2 ? new Map : factory(env3));
+ map = target2;
}
- return target;
+ return target2;
};
var adapter = getFetch();
@@ -178321,17 +174560,17 @@ var validators = {};
};
});
var deprecatedWarnings = {};
-validators.transitional = function transitional(validator, version2, message) {
+validators.transitional = function transitional(validator, version4, message) {
function formatMessage(opt, desc2) {
return "[Axios v" + VERSION + "] Transitional option '" + opt + "'" + desc2 + (message ? ". " + message : "");
}
return (value, opt, opts) => {
if (validator === false) {
- throw new AxiosError_default(formatMessage(opt, " has been removed" + (version2 ? " in " + version2 : "")), AxiosError_default.ERR_DEPRECATED);
+ throw new AxiosError_default(formatMessage(opt, " has been removed" + (version4 ? " in " + version4 : "")), AxiosError_default.ERR_DEPRECATED);
}
- if (version2 && !deprecatedWarnings[opt]) {
+ if (version4 && !deprecatedWarnings[opt]) {
deprecatedWarnings[opt] = true;
- console.warn(formatMessage(opt, " has been deprecated since v" + version2 + " and will be removed in the near future"));
+ console.warn(formatMessage(opt, " has been deprecated since v" + version4 + " and will be removed in the near future"));
}
return validator ? validator(value, opt, opts) : true;
};
@@ -178607,9 +174846,9 @@ class CancelToken {
if (!this._listeners) {
return;
}
- const index2 = this._listeners.indexOf(listener);
- if (index2 !== -1) {
- this._listeners.splice(index2, 1);
+ const index3 = this._listeners.indexOf(listener);
+ if (index3 !== -1) {
+ this._listeners.splice(index3, 1);
}
}
toAbortSignal() {
@@ -178757,8 +174996,8 @@ axios.default = axios;
var axios_default = axios;
// src/api/interview/interview-service.ts
-var genAI = new GoogleGenerativeAI(config_default.GEMINI_API_KEY);
-var model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
+var genAI2 = new GoogleGenerativeAI(config_default.GEMINI_API_KEY);
+var model2 = genAI2.getGenerativeModel({ model: "gemini-2.5-flash" });
var ROUND_FOCUS = {
technical: `TECHNICAL (DSA) ROUND: Ask classic data structures & algorithms problems only (e.g. arrays/strings, two pointers, sliding window, binary search, trees, graphs, heaps, hash maps, DP, greedy). Each question should be solvable by implementing a function or algorithm with clear constraints, edge cases, and time/space complexity discussion. Do NOT ask for large system or service design. Do NOT ask behavioral questions.`,
behavioral: `BEHAVIORAL ROUND: Use situational and past-experience questions only. Prefer STAR-style prompts (Situation, Task, Action, Result). Cover teamwork, conflict, leadership, deadlines, mistakes, and communication. Do not ask for code, pseudocode, or system architecture.`,
@@ -178771,9 +175010,9 @@ var LEVEL_FOCUS = {
hard: "Difficulty: HARD \u2014 demanding questions; expect strong depth and trade-off reasoning.",
mixed: "Difficulty: MIXED \u2014 vary difficulty within the set while staying appropriate to experience."
};
-async function textToAudio(text2) {
+async function textToAudio(text3) {
const data = {
- text: text2,
+ text: text3,
voiceId: "en-US-terrell"
};
try {
@@ -178795,16 +175034,23 @@ async function generateQuestions(data) {
role,
experience,
customRequirements,
+ resumeContext,
questionCount,
interviewLevel,
round,
codingLanguage
} = data;
- const count = Math.min(Math.max(Number(questionCount) || 1, 1), 5);
+ const count2 = Math.min(Math.max(Number(questionCount) || 1, 1), 5);
const levelLine = LEVEL_FOCUS[interviewLevel];
const roundLine = ROUND_FOCUS[round];
const langLine = (round === "technical" || round === "lld") && codingLanguage ? `
PROGRAMMING LANGUAGE: The candidate selected "${codingLanguage}" for their editor. Phrase each question so a solution is naturally written in that language (syntax may vary; keep the problem language-agnostic but mention they may implement in ${codingLanguage}).` : "";
+ const MAX_RESUME_CHARS = 3500;
+ const resumeLine = resumeContext?.trim() ? `
+CANDIDATE RESUME PROFILE:
+${resumeContext.slice(0, MAX_RESUME_CHARS)}
+
+IMPORTANT: Use the resume profile above to personalise the questions. Reference specific technologies, projects, or experiences mentioned. Prioritise gaps or depth opportunities visible in the resume.` : "";
const prompt = `
You are an expert interviewer for software development roles. Generate a set of high-quality interview questions tailored to the candidate's role, experience, round type, and difficulty.
@@ -178818,15 +175064,17 @@ ROUND AND LEVEL:
${roundLine}
${levelLine}
${langLine}
+${resumeLine}
CUSTOM REQUIREMENTS FROM CANDIDATE:
${customRequirements?.trim() ? customRequirements : "No extra requirements provided."}
INSTRUCTIONS:
-- Generate exactly ${count} questions (no more, no fewer).
+- Generate exactly ${count2} questions (no more, no fewer).
- Every question must fit the selected round type above; do not blend unrelated round types.
- Calibrate depth to the experience level and the interview level (${interviewLevel}).
- Prioritize custom requirements when provided.
+- When a resume profile is present, tailor at least half the questions to the candidate's actual experience, tech stack, or projects from their resume.
- Avoid generic filler; be specific and practical for the role.
- Do not repeat questions. Do not include answers.
@@ -178847,14 +175095,14 @@ Use null for audioUrl on every question (the server will fill audio).
}
};
try {
- const result = await model.generateContent(payload);
+ const result = await model2.generateContent(payload);
const data2 = JSON.parse(result.response.text());
if (!data2.interviewId) {
data2.interviewId = v4_default();
}
if (Array.isArray(data2.questions)) {
- if (data2.questions.length > count) {
- data2.questions = data2.questions.slice(0, count);
+ if (data2.questions.length > count2) {
+ data2.questions = data2.questions.slice(0, count2);
}
for (const question of data2.questions) {
const audioData = await textToAudio(question.text);
@@ -178905,7 +175153,7 @@ Answer: ${answer}`;
}
}
};
- const result = await model.generateContent(payload);
+ const result = await model2.generateContent(payload);
let responseText;
if (result && result.response && typeof result.response.text === "function") {
responseText = result.response.text();
@@ -178933,6 +175181,7 @@ var generateInterviewQuestionsSchema = create$3({
role: create$6().required("Role is required"),
experience: create$6().required("Experience is required"),
customRequirements: create$6().optional(),
+ resumeContext: create$6().optional().max(4000, "Resume context too long"),
questionCount: create$5().required("Question count is required"),
interviewLevel: create$6().required("Interview level is required"),
round: create$6().required("Round is required"),
@@ -178968,14 +175217,6 @@ var api_default = () => {
// src/loaders/express.ts
var import_cookie_parser = __toESM(require_cookie_parser(), 1);
-// src/utils/redis.js
-var import_ioredis2 = __toESM(require_built3(), 1);
-var redisUrl2 = config_default2.REDIS_URL;
-if (!redisUrl2) {
- throw new Error("REDIS_URL must be set in your environment");
-}
-var redisClient = new import_ioredis2.default(redisUrl2);
-
// src/shared/ratelimiter.ts
var CAPACITY = 10;
var WINDOW = 60;
@@ -178989,7 +175230,7 @@ var rateLimitMiddleware = asyncHandler_default(async (req, res, next) => {
}
const key = `${KEY_PREFIX}:${userId}`;
const now = Date.now() / 1000;
- const bucket = await redisClient.hgetall(key);
+ const bucket = await redis_default.hgetall(key);
let tokens = parseFloat(bucket.tokens) || CAPACITY;
let last = parseFloat(bucket.last) || now;
const delta = now - last;
@@ -179000,7 +175241,7 @@ var rateLimitMiddleware = asyncHandler_default(async (req, res, next) => {
return res.set("Retry-After", String(retrySecs)).status(429).json({ error: `Too many submissions. Try again in ${retrySecs}s.` });
}
tokens -= 1;
- const pipeline = redisClient.multi();
+ const pipeline = redis_default.multi();
pipeline.hset(key, "tokens", tokens, "last", last);
pipeline.expire(key, WINDOW);
await pipeline.exec();
@@ -179057,12 +175298,12 @@ var express_default = ({ app }) => {
var loaders_default = async ({
expressApp
}) => {
- express_default({ app: expressApp });
await getDrizzleClient();
logger_default.info("\uD83D\uDEE1\uFE0F Database loaded \uD83D\uDEE1\uFE0F");
+ express_default({ app: expressApp });
+ logger_default.info("\uD83D\uDEE1\uFE0F Express loaded \uD83D\uDEE1\uFE0F");
await loadGoogleOAuthClient();
logger_default.info("\uD83D\uDEE1\uFE0F Google OAuth loaded \uD83D\uDEE1\uFE0F");
- logger_default.info("\uD83D\uDEE1\uFE0F Express loaded \uD83D\uDEE1\uFE0F");
logger_default.info("\uD83D\uDEE1\uFE0F All modules loaded! \uD83D\uDEE1\uFE0F");
};
diff --git a/backend/src/api/contest/contest.route.ts b/backend/src/api/contest/contest.route.ts
index bdfbcc8..aa809c0 100644
--- a/backend/src/api/contest/contest.route.ts
+++ b/backend/src/api/contest/contest.route.ts
@@ -1,6 +1,6 @@
// import {createContest,getAllContests,getContestById,getClock,getLeaderboard,registerContest} from "./contest.controller.js"
// import { Router } from 'express';
-import { verifyJWT } from '../../middlewares/auth.middleware.js';
+// import { verifyJWT } from '../../middlewares/auth.middleware.js';
// const router = Router();
diff --git a/backend/src/api/problem/problem-schema.ts b/backend/src/api/problem/problem-schema.ts
index cc4961b..1d5a874 100644
--- a/backend/src/api/problem/problem-schema.ts
+++ b/backend/src/api/problem/problem-schema.ts
@@ -15,10 +15,10 @@ export const createProblemSchema = yup.object({
constraints: yup.string().required("Constraints is required"),
timeLimit: yup.number().required("Time Limit is required"),
memoryLimit: yup.number().required("Memory Limit is required"),
- editorialContent: yup.string().required("Editorial is required"),
- editorialLink: yup.string().required("Editorial Link is required"),
+ editorialContent: yup.string().optional().default(""),
+ editorialLink: yup.string().optional().default(""),
solution: yup.string().required("Solution is required"),
- tags: yup.array().of(yup.string()).required("Tags is required"),
+ tags: yup.array().of(yup.string()).optional().default([]),
testcases: yup.number().required(),
sampleTestcases: yup.number().required()
});
\ No newline at end of file
diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts
index 1e9c914..431382e 100644
--- a/backend/src/config/index.ts
+++ b/backend/src/config/index.ts
@@ -1,13 +1,17 @@
import dotenv from 'dotenv';
import path from 'path';
import * as yup from 'yup';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
dotenv.config({ path: path.join(__dirname, '../../.env') });
const envSchema = yup.object().shape({
- NODE_ENV : yup.string().oneOf(['dev','production']).default('dev'),
- DATABASE_URL : yup.string().required('Database URL is Required'),
- PORT : yup.string().default('8000'),
+ NODE_ENV: yup.string().oneOf(['dev', 'production']).default('dev'),
+ DATABASE_URL: yup.string().required('Database URL is Required'),
+ PORT: yup.string().default('8000'),
ALLOWED_ORIGINS: yup.string(),
// JWT_SECRET : yup.string().required(),
// JWT_REFRESH_SECRET: yup.string().required(),
@@ -17,13 +21,13 @@ const envSchema = yup.object().shape({
GEMINI_API_KEY: yup.string().optional(),
// GOOGLE_CALLBACK_URL : yup.string().required(),
LOG_LEVEL: yup
- .string()
- .oneOf(['error', 'warn', 'info', 'http', 'verbose', 'debug', 'silly'])
- .default('info'),
+ .string()
+ .oneOf(['error', 'warn', 'info', 'http', 'verbose', 'debug', 'silly'])
+ .default('info'),
API_VERSION: yup.string().default('v1'),
MAX_API_REQUEST_RETRIES: yup.number().integer().default(3),
- CLIENT_URL : yup.string().default('https://code-sm.vercel.app'),
- MURF_API_KEY : yup.string().optional(),
+ CLIENT_URL: yup.string().default('https://code-sm.vercel.app'),
+ MURF_API_KEY: yup.string().optional(),
REDIS_HOST: yup.string().required(),
REDIS_PASSWORD: yup.string().required(),
REDIS_PORT: yup.string().required(),
@@ -31,19 +35,19 @@ const envSchema = yup.object().shape({
REDIS_URL: yup.string().required(),
REFRESH_TOKEN_EXPIRY: yup.string().required(),
REFRESH_TOKEN_SECRET: yup.string().required(),
- MONGO_URI : yup.string().required(),
+ MONGO_URI: yup.string().required(),
ACCESS_TOKEN_EXPIRY: yup.string().required(),
ACCESS_TOKEN_SECRET: yup.string().required(),
AWS_ACCESS_KEY_ID: yup.string().required(),
AWS_BUCKET_NAME: yup.string().required(),
- AWS_REGION : yup.string().required(),
- VITE_API_URL : yup.string().required(),
+ AWS_REGION: yup.string().required(),
+ VITE_API_URL: yup.string().required(),
EMAIL_FROM: yup.string().required(),
EMAIL_HOST: yup.string().required(),
EMAIL_PASS: yup.string().required(),
EMAIL_PORT: yup.number().required(),
EMAIL_USER: yup.string().required(),
- SMTP_VERIFY_URL : yup.string().required(),
+ SMTP_VERIFY_URL: yup.string().required(),
GOOGLE_REDIRECT_URI: yup.string().required(),
JWT_SECRET: yup.string().required(),
})
diff --git a/backend/src/scripts/seed-admin.js b/backend/src/scripts/seed-admin.js
index aa106f7..63a03af 100644
--- a/backend/src/scripts/seed-admin.js
+++ b/backend/src/scripts/seed-admin.js
@@ -1,27 +1,27 @@
import bcrypt from "bcryptjs";
-import User from "../models/user.model.js";
-import env from '../config/index.js'
+import { user } from "../db/schema.ts";
+import env from '../config/index.ts'
export async function seedAdmin() {
- const adminExists = await User.findOne({ role: "admin" });
+ const adminExists = await user.findOne({ role: "ADMIN" });
if (adminExists) {
console.log("Admin already exists. Skipping.");
process.exit(0);
}
- const { ADMIN_USERNAME,ADMIN_FULLNAME, ADMIN_EMAIL, ADMIN_PASSWORD } = env;
+ const { ADMIN_USERNAME, ADMIN_FULLNAME, ADMIN_EMAIL, ADMIN_PASSWORD } = env;
if (!ADMIN_EMAIL || !ADMIN_PASSWORD) {
throw new Error("ADMIN_EMAIL / ADMIN_PASSWORD missing");
}
const passwordHash = await bcrypt.hash(ADMIN_PASSWORD, 12);
- await User.create({
+ await user.create({
username: ADMIN_USERNAME,
- fullName : ADMIN_FULLNAME,
+ fullName: ADMIN_FULLNAME,
email: ADMIN_EMAIL,
- password : passwordHash,
+ password: passwordHash,
role: "admin",
});
diff --git a/backend/tsconfig.json b/backend/tsconfig.json
index 2de74a7..cacc83c 100644
--- a/backend/tsconfig.json
+++ b/backend/tsconfig.json
@@ -10,8 +10,8 @@
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"forceConsistentCasingInFileNames": true,
- "moduleResolution": "node",
- "module": "commonjs",
+ "moduleResolution": "node16",
+ "module": "node16",
"pretty": true,
"sourceMap": false,
"outDir": "./dist",