Skip to content

Commit 744ebab

Browse files
committed
refactor(deployments): enhance deployment worker and queue handling for cloud environments
- Refactored the deployment worker to create a no-op worker when Redis is disabled (e.g., IS_CLOUD), preventing BullMQ connection errors. - Updated queue initialization to use a no-op queue in cloud environments, ensuring compatibility and stability. - Improved error handling and logging for job processing in the deployment worker.
1 parent 17da1d5 commit 744ebab

File tree

2 files changed

+102
-75
lines changed

2 files changed

+102
-75
lines changed

apps/dokploy/server/queues/deployments-queue.ts

Lines changed: 75 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
deployApplication,
33
deployCompose,
44
deployPreviewApplication,
5+
IS_CLOUD,
56
rebuildApplication,
67
rebuildCompose,
78
rebuildPreviewApplication,
@@ -13,70 +14,83 @@ import { type Job, Worker } from "bullmq";
1314
import type { DeploymentJob } from "./queue-types";
1415
import { redisConfig } from "./redis-connection";
1516

16-
export const deploymentWorker = new Worker(
17-
"deployments",
18-
async (job: Job<DeploymentJob>) => {
19-
try {
20-
if (job.data.applicationType === "application") {
21-
await updateApplicationStatus(job.data.applicationId, "running");
17+
const createDeploymentWorker = () =>
18+
new Worker(
19+
"deployments",
20+
async (job: Job<DeploymentJob>) => {
21+
try {
22+
if (job.data.applicationType === "application") {
23+
await updateApplicationStatus(job.data.applicationId, "running");
2224

23-
if (job.data.type === "redeploy") {
24-
await rebuildApplication({
25-
applicationId: job.data.applicationId,
26-
titleLog: job.data.titleLog,
27-
descriptionLog: job.data.descriptionLog,
25+
if (job.data.type === "redeploy") {
26+
await rebuildApplication({
27+
applicationId: job.data.applicationId,
28+
titleLog: job.data.titleLog,
29+
descriptionLog: job.data.descriptionLog,
30+
});
31+
} else if (job.data.type === "deploy") {
32+
await deployApplication({
33+
applicationId: job.data.applicationId,
34+
titleLog: job.data.titleLog,
35+
descriptionLog: job.data.descriptionLog,
36+
});
37+
}
38+
} else if (job.data.applicationType === "compose") {
39+
await updateCompose(job.data.composeId, {
40+
composeStatus: "running",
2841
});
29-
} else if (job.data.type === "deploy") {
30-
await deployApplication({
31-
applicationId: job.data.applicationId,
32-
titleLog: job.data.titleLog,
33-
descriptionLog: job.data.descriptionLog,
42+
if (job.data.type === "deploy") {
43+
await deployCompose({
44+
composeId: job.data.composeId,
45+
titleLog: job.data.titleLog,
46+
descriptionLog: job.data.descriptionLog,
47+
});
48+
} else if (job.data.type === "redeploy") {
49+
await rebuildCompose({
50+
composeId: job.data.composeId,
51+
titleLog: job.data.titleLog,
52+
descriptionLog: job.data.descriptionLog,
53+
});
54+
}
55+
} else if (job.data.applicationType === "application-preview") {
56+
await updatePreviewDeployment(job.data.previewDeploymentId, {
57+
previewStatus: "running",
3458
});
35-
}
36-
} else if (job.data.applicationType === "compose") {
37-
await updateCompose(job.data.composeId, {
38-
composeStatus: "running",
39-
});
40-
if (job.data.type === "deploy") {
41-
await deployCompose({
42-
composeId: job.data.composeId,
43-
titleLog: job.data.titleLog,
44-
descriptionLog: job.data.descriptionLog,
45-
});
46-
} else if (job.data.type === "redeploy") {
47-
await rebuildCompose({
48-
composeId: job.data.composeId,
49-
titleLog: job.data.titleLog,
50-
descriptionLog: job.data.descriptionLog,
51-
});
52-
}
53-
} else if (job.data.applicationType === "application-preview") {
54-
await updatePreviewDeployment(job.data.previewDeploymentId, {
55-
previewStatus: "running",
56-
});
5759

58-
if (job.data.type === "redeploy") {
59-
await rebuildPreviewApplication({
60-
applicationId: job.data.applicationId,
61-
titleLog: job.data.titleLog,
62-
descriptionLog: job.data.descriptionLog,
63-
previewDeploymentId: job.data.previewDeploymentId,
64-
});
65-
} else if (job.data.type === "deploy") {
66-
await deployPreviewApplication({
67-
applicationId: job.data.applicationId,
68-
titleLog: job.data.titleLog,
69-
descriptionLog: job.data.descriptionLog,
70-
previewDeploymentId: job.data.previewDeploymentId,
71-
});
60+
if (job.data.type === "redeploy") {
61+
await rebuildPreviewApplication({
62+
applicationId: job.data.applicationId,
63+
titleLog: job.data.titleLog,
64+
descriptionLog: job.data.descriptionLog,
65+
previewDeploymentId: job.data.previewDeploymentId,
66+
});
67+
} else if (job.data.type === "deploy") {
68+
await deployPreviewApplication({
69+
applicationId: job.data.applicationId,
70+
titleLog: job.data.titleLog,
71+
descriptionLog: job.data.descriptionLog,
72+
previewDeploymentId: job.data.previewDeploymentId,
73+
});
74+
}
7275
}
76+
} catch (error) {
77+
console.log("Error", error);
7378
}
74-
} catch (error) {
75-
console.log("Error", error);
76-
}
77-
},
78-
{
79-
autorun: false,
80-
connection: redisConfig,
81-
},
82-
);
79+
},
80+
{
81+
autorun: false,
82+
connection: redisConfig,
83+
},
84+
);
85+
86+
/** No-op worker when Redis is disabled (e.g. IS_CLOUD). Avoids BullMQ connection errors. */
87+
const noopWorker = {
88+
run: () => Promise.resolve(),
89+
close: () => Promise.resolve(),
90+
cancelJob: () => Promise.resolve(),
91+
cancelAllJobs: () => Promise.resolve(),
92+
};
93+
94+
export const deploymentWorker = !IS_CLOUD
95+
? createDeploymentWorker()
96+
: (noopWorker as unknown as Worker<DeploymentJob>);

apps/dokploy/server/queues/queueSetup.ts

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1+
import { IS_CLOUD } from "@dokploy/server";
12
import {
23
execAsync,
34
execAsyncRemote,
45
} from "@dokploy/server/utils/process/execAsync";
6+
import type { Job } from "bullmq";
57
import { Queue } from "bullmq";
68
import { deploymentWorker } from "./deployments-queue";
79
import { redisConfig } from "./redis-connection";
810

9-
const myQueue = new Queue("deployments", {
10-
connection: redisConfig,
11+
/** No-op queue when Redis is disabled (e.g. IS_CLOUD). Avoids BullMQ connection errors. */
12+
const createNoopQueue = () => ({
13+
getJobs: () => Promise.resolve([] as Job[]),
14+
add: () =>
15+
Promise.resolve({ id: "noop", remove: () => Promise.resolve() } as Job),
16+
close: () => Promise.resolve(),
17+
on: () => {},
1118
});
1219

20+
const myQueue = !IS_CLOUD
21+
? new Queue("deployments", { connection: redisConfig })
22+
: (createNoopQueue() as unknown as Queue);
23+
1324
export const getJobsByApplicationId = async (applicationId: string) => {
1425
const jobs = await myQueue.getJobs();
1526
return jobs.filter((job) => job?.data?.applicationId === applicationId);
@@ -20,19 +31,21 @@ export const getJobsByComposeId = async (composeId: string) => {
2031
return jobs.filter((job) => job?.data?.composeId === composeId);
2132
};
2233

23-
process.on("SIGTERM", () => {
24-
myQueue.close();
25-
process.exit(0);
26-
});
34+
if (!IS_CLOUD) {
35+
process.on("SIGTERM", () => {
36+
myQueue.close();
37+
process.exit(0);
38+
});
2739

28-
myQueue.on("error", (error) => {
29-
if ((error as any).code === "ECONNREFUSED") {
30-
console.error(
31-
"Make sure you have installed Redis and it is running.",
32-
error,
33-
);
34-
}
35-
});
40+
myQueue.on("error", (error) => {
41+
if ((error as any).code === "ECONNREFUSED") {
42+
console.error(
43+
"Make sure you have installed Redis and it is running.",
44+
error,
45+
);
46+
}
47+
});
48+
}
3649

3750
export const cleanQueuesByApplication = async (applicationId: string) => {
3851
const jobs = await myQueue.getJobs(["waiting", "delayed"]);

0 commit comments

Comments
 (0)