plugin-cluster-manager 1.1.10 → 1.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client-v2.d.ts +2 -0
- package/client-v2.js +1 -0
- package/client.js +1 -0
- package/dist/client/index.js +1 -1
- package/dist/client-v2/914.5dc1105cf3ada6a6.js +10 -0
- package/dist/client-v2/index.js +10 -0
- package/dist/externalVersion.js +6 -5
- package/dist/locale/en-US.json +138 -28
- package/dist/locale/vi-VN.json +139 -28
- package/dist/locale/zh-CN.json +140 -28
- package/dist/server/actions/cache-monitor.js +301 -0
- package/dist/server/actions/cluster-nodes.js +391 -11
- package/dist/server/actions/doctor.js +1246 -0
- package/dist/server/actions/orchestrator.js +37 -0
- package/dist/server/actions/queue-mappings.js +107 -0
- package/dist/server/collections/cluster-manager-doctor-runs.js +52 -0
- package/dist/server/collections/cluster-manager-doctor.js +44 -0
- package/dist/server/collections/worker-queue-mappings.js +106 -0
- package/dist/server/hooks/cacheInvalidationHooks.js +81 -0
- package/dist/server/middlewares/listMetaCacheMiddleware.js +79 -0
- package/dist/server/orchestrator/PackageManager.js +21 -24
- package/dist/server/orchestrator/docker-adapter.js +49 -27
- package/dist/server/plugin.js +71 -16
- package/dist/server/queue-scanner.js +141 -0
- package/dist/server/utils/node.js +30 -2
- package/dist/server/utils/versionManager.js +91 -0
- package/package.json +9 -5
- package/server.js +1 -0
- package/src/client/AclCacheManager.tsx +292 -287
- package/src/client/CacheMonitor.tsx +166 -179
- package/src/client/ClusterManagerLayout.tsx +54 -42
- package/src/client/ClusterNodes.tsx +698 -418
- package/src/client/ContainerOrchestrator.tsx +184 -102
- package/src/client/Doctor.tsx +559 -0
- package/src/client/NginxCacheManager.tsx +415 -0
- package/src/client/PluginOperations.tsx +234 -234
- package/src/client/QueueAssignment.tsx +355 -0
- package/src/client/TaskManager.tsx +194 -187
- package/src/client/WorkflowExecutions.tsx +243 -238
- package/src/client/index.tsx +22 -14
- package/src/client/utils/clientSafeCache.ts +41 -0
- package/src/client/utils/requestDedupInterceptor.ts +213 -0
- package/src/client-v2/plugin.tsx +24 -0
- package/src/locale/en-US.json +138 -28
- package/src/locale/vi-VN.json +139 -28
- package/src/locale/zh-CN.json +140 -28
- package/src/server/__tests__/doctor.test.ts +53 -0
- package/src/server/actions/acl-cache.ts +272 -272
- package/src/server/actions/cache-monitor.ts +453 -116
- package/src/server/actions/cluster-nodes.ts +878 -378
- package/src/server/actions/doctor.ts +1536 -0
- package/src/server/actions/orchestrator.ts +54 -2
- package/src/server/actions/queue-mappings.ts +94 -0
- package/src/server/collections/cluster-manager-doctor-runs.ts +23 -0
- package/src/server/collections/cluster-manager-doctor.ts +19 -0
- package/src/server/collections/worker-queue-mappings.ts +85 -0
- package/src/server/hooks/cacheInvalidationHooks.ts +58 -0
- package/src/server/middlewares/listMetaCacheMiddleware.ts +55 -0
- package/src/server/orchestrator/PackageManager.ts +20 -24
- package/src/server/orchestrator/docker-adapter.ts +74 -37
- package/src/server/plugin.ts +347 -270
- package/src/server/queue-scanner.ts +154 -0
- package/src/server/utils/node.ts +48 -0
- package/src/server/utils/versionManager.ts +69 -0
- package/dist/client/AclCacheManager.d.ts +0 -2
- package/dist/client/CacheMonitor.d.ts +0 -2
- package/dist/client/ClusterManagerLayout.d.ts +0 -2
- package/dist/client/ClusterNodes.d.ts +0 -2
- package/dist/client/ContainerOrchestrator.d.ts +0 -2
- package/dist/client/EventQueueMonitor.d.ts +0 -2
- package/dist/client/LockMonitor.d.ts +0 -2
- package/dist/client/PackageInstaller.d.ts +0 -2
- package/dist/client/PluginOperations.d.ts +0 -2
- package/dist/client/RedisMonitor.d.ts +0 -2
- package/dist/client/TaskManager.d.ts +0 -2
- package/dist/client/WorkflowExecutions.d.ts +0 -2
- package/dist/client/index.d.ts +0 -5
- package/dist/client/utils.d.ts +0 -12
- package/dist/index.d.ts +0 -2
- package/dist/server/actions/acl-cache.d.ts +0 -53
- package/dist/server/actions/cache-monitor.d.ts +0 -23
- package/dist/server/actions/cluster-nodes.d.ts +0 -49
- package/dist/server/actions/event-queue-monitor.d.ts +0 -13
- package/dist/server/actions/lock-monitor.d.ts +0 -19
- package/dist/server/actions/orchestrator.d.ts +0 -58
- package/dist/server/actions/package-manager.d.ts +0 -6
- package/dist/server/actions/plugin-operations.d.ts +0 -6
- package/dist/server/actions/redis-monitor.d.ts +0 -12
- package/dist/server/actions/tasks.d.ts +0 -7
- package/dist/server/actions/workflow-executions.d.ts +0 -7
- package/dist/server/adapters/redis-lock-adapter.d.ts +0 -15
- package/dist/server/adapters/redis-node-registry.d.ts +0 -12
- package/dist/server/adapters/redis-pubsub-adapter.d.ts +0 -16
- package/dist/server/collections/app.d.ts +0 -8
- package/dist/server/collections/cluster-manager-acl-cache.d.ts +0 -22
- package/dist/server/collections/cluster-manager-cache-mgr.d.ts +0 -22
- package/dist/server/collections/cluster-manager-cluster.d.ts +0 -22
- package/dist/server/collections/cluster-manager-lock.d.ts +0 -22
- package/dist/server/collections/cluster-manager-plugins.d.ts +0 -18
- package/dist/server/collections/cluster-manager-queue.d.ts +0 -22
- package/dist/server/collections/cluster-manager-redis.d.ts +0 -22
- package/dist/server/collections/cluster-manager-workflow.d.ts +0 -22
- package/dist/server/collections/cluster-manager.d.ts +0 -22
- package/dist/server/collections/orchestrator-settings.d.ts +0 -59
- package/dist/server/collections/orchestrator-stacks.d.ts +0 -102
- package/dist/server/collections/worker-orchestrator.d.ts +0 -22
- package/dist/server/collections/worker-packages-configs.d.ts +0 -3
- package/dist/server/collections/worker-packages.d.ts +0 -22
- package/dist/server/orchestrator/PackageManager.d.ts +0 -39
- package/dist/server/orchestrator/docker-adapter.d.ts +0 -41
- package/dist/server/orchestrator/index.d.ts +0 -4
- package/dist/server/orchestrator/k8s-adapter.d.ts +0 -50
- package/dist/server/orchestrator/leader-election.d.ts +0 -48
- package/dist/server/orchestrator/types.d.ts +0 -84
- package/dist/server/plugin.d.ts +0 -26
- package/dist/server/utils/node.d.ts +0 -6
- package/dist/server/utils/redis.d.ts +0 -29
- package/dist/shared/packages.d.ts +0 -23
- /package/{dist/server/index.d.ts → src/client-v2/index.tsx} +0 -0
|
@@ -17,9 +17,7 @@ function getDockerode() {
|
|
|
17
17
|
try {
|
|
18
18
|
Dockerode = require('dockerode');
|
|
19
19
|
} catch {
|
|
20
|
-
throw new Error(
|
|
21
|
-
'[DockerAdapter] "dockerode" package not found. Install it: yarn add dockerode',
|
|
22
|
-
);
|
|
20
|
+
throw new Error('[DockerAdapter] "dockerode" package not found. Install it: yarn add dockerode');
|
|
23
21
|
}
|
|
24
22
|
}
|
|
25
23
|
return Dockerode;
|
|
@@ -58,11 +56,7 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
58
56
|
const containers = await this.docker.listContainers({
|
|
59
57
|
all: true,
|
|
60
58
|
filters: {
|
|
61
|
-
label: [
|
|
62
|
-
`${LABEL_STACK}=${stack.name}`,
|
|
63
|
-
`${LABEL_MANAGED}=true`,
|
|
64
|
-
...this.buildLabelFilters(this.workerLabels),
|
|
65
|
-
],
|
|
59
|
+
label: [`${LABEL_STACK}=${stack.name}`, `${LABEL_MANAGED}=true`, ...this.buildLabelFilters(this.workerLabels)],
|
|
66
60
|
},
|
|
67
61
|
});
|
|
68
62
|
|
|
@@ -105,9 +99,20 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
105
99
|
if (diff > 0) {
|
|
106
100
|
// Scale UP
|
|
107
101
|
let targetNetworks = stack.networks && stack.networks.length > 0 ? stack.networks : [];
|
|
108
|
-
|
|
102
|
+
const targetNetworkMode = stack.networkMode;
|
|
109
103
|
let targetEnvVars = this.buildEnvArray(stack.envVars);
|
|
110
104
|
let targetVolumes = stack.volumes || [];
|
|
105
|
+
// Default the worker image to whatever the app container is running, so
|
|
106
|
+
// workers stay version-locked with the app even when the stack record
|
|
107
|
+
// has a stale/empty image. An explicit stack.image still wins.
|
|
108
|
+
let targetImage = stack.image;
|
|
109
|
+
// Inherit the app container's startup command/entrypoint so workers boot
|
|
110
|
+
// identically (e.g. source-tarball extraction + `yarn start`). Without
|
|
111
|
+
// this, a worker created from the bare image runs the image default
|
|
112
|
+
// command, skips the app's bootstrap, never finishes booting, and never
|
|
113
|
+
// registers a heartbeat — so it never appears in Cluster Nodes.
|
|
114
|
+
let inheritedCmd: string[] | undefined;
|
|
115
|
+
let inheritedEntrypoint: string[] | undefined;
|
|
111
116
|
|
|
112
117
|
// Auto-detect current container's configuration to inherit networks and env vars
|
|
113
118
|
try {
|
|
@@ -115,50 +120,70 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
115
120
|
const myContainerId = os.hostname();
|
|
116
121
|
const myContainer = this.docker.getContainer(myContainerId);
|
|
117
122
|
const myInfo = await myContainer.inspect();
|
|
118
|
-
|
|
123
|
+
|
|
124
|
+
// Inherit the app container's image when the stack does not pin one
|
|
125
|
+
if (!targetImage && myInfo?.Config?.Image) {
|
|
126
|
+
targetImage = myInfo.Config.Image;
|
|
127
|
+
console.log('[DockerAdapter] Inherited image from app container:', targetImage);
|
|
128
|
+
}
|
|
129
|
+
|
|
119
130
|
// Always inherit Networks so worker can communicate with main app
|
|
120
131
|
if (myInfo?.NetworkSettings?.Networks) {
|
|
121
132
|
const inheritedNetworks = Object.keys(myInfo.NetworkSettings.Networks);
|
|
122
133
|
targetNetworks = Array.from(new Set([...inheritedNetworks, ...targetNetworks]));
|
|
123
134
|
console.log('[DockerAdapter] Inherited networks:', targetNetworks);
|
|
124
135
|
}
|
|
125
|
-
|
|
136
|
+
|
|
126
137
|
// Inherit Environment Variables and merge with stack.envVars
|
|
127
138
|
if (myInfo?.Config?.Env) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
+
const envDict: Record<string, string> = {};
|
|
140
|
+
myInfo.Config.Env.forEach((e: string) => {
|
|
141
|
+
const idx = e.indexOf('=');
|
|
142
|
+
if (idx !== -1) {
|
|
143
|
+
envDict[e.substring(0, idx)] = e.substring(idx + 1);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
// Overwrite with explicitly defined env vars
|
|
147
|
+
Object.assign(envDict, stack.envVars || {});
|
|
148
|
+
|
|
149
|
+
targetEnvVars = Object.entries(envDict).map(([k, v]) => `${k}=${v}`);
|
|
139
150
|
}
|
|
140
151
|
// Inherit Volumes (Binds)
|
|
141
152
|
if (myInfo?.HostConfig?.Binds) {
|
|
142
153
|
const inheritedBinds = myInfo.HostConfig.Binds as string[];
|
|
143
154
|
targetVolumes = Array.from(new Set([...inheritedBinds, ...targetVolumes]));
|
|
144
155
|
}
|
|
156
|
+
// Inherit the startup Cmd/Entrypoint so the worker runs the same bootstrap
|
|
157
|
+
// as the app container (used only when the stack pins no explicit command).
|
|
158
|
+
if (Array.isArray(myInfo?.Config?.Cmd) && myInfo.Config.Cmd.length > 0) {
|
|
159
|
+
inheritedCmd = myInfo.Config.Cmd as string[];
|
|
160
|
+
}
|
|
161
|
+
if (Array.isArray(myInfo?.Config?.Entrypoint) && myInfo.Config.Entrypoint.length > 0) {
|
|
162
|
+
inheritedEntrypoint = myInfo.Config.Entrypoint as string[];
|
|
163
|
+
}
|
|
145
164
|
} catch (e: any) {
|
|
146
165
|
// Ignore error if not running in a container or cannot inspect
|
|
147
166
|
console.error('[DockerAdapter] Failed to inherit container config:', e.message);
|
|
148
167
|
}
|
|
149
168
|
|
|
150
169
|
// Automatically separate logs for workers to prevent log interleaving with the main app
|
|
151
|
-
const hasLoggerBase = targetEnvVars.some(e => e.startsWith('LOGGER_BASE_PATH='));
|
|
170
|
+
const hasLoggerBase = targetEnvVars.some((e) => e.startsWith('LOGGER_BASE_PATH='));
|
|
152
171
|
if (!hasLoggerBase) {
|
|
153
172
|
targetEnvVars.push(`LOGGER_BASE_PATH=/app/nocobase/storage/logs/${stack.name}`);
|
|
154
173
|
}
|
|
155
174
|
|
|
175
|
+
if (!targetImage) {
|
|
176
|
+
throw new Error(
|
|
177
|
+
`[DockerAdapter] No image configured for stack "${stack.name}" and the app container image could not be determined.`,
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
156
181
|
for (let i = 0; i < diff; i++) {
|
|
157
182
|
const suffix = `${Date.now()}-${Math.random().toString(36).substring(2, 6)}`;
|
|
158
183
|
const containerName = `${stack.name}-${suffix}`;
|
|
159
184
|
|
|
160
185
|
const createOpts: any = {
|
|
161
|
-
Image:
|
|
186
|
+
Image: targetImage,
|
|
162
187
|
name: containerName,
|
|
163
188
|
Env: targetEnvVars,
|
|
164
189
|
Labels: {
|
|
@@ -174,6 +199,15 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
174
199
|
|
|
175
200
|
if (stack.command) {
|
|
176
201
|
createOpts.Cmd = ['/bin/sh', '-c', stack.command];
|
|
202
|
+
} else {
|
|
203
|
+
// No explicit command: replay the app container's bootstrap so the
|
|
204
|
+
// worker boots NocoBase the same way and registers a heartbeat.
|
|
205
|
+
if (inheritedEntrypoint) {
|
|
206
|
+
createOpts.Entrypoint = inheritedEntrypoint;
|
|
207
|
+
}
|
|
208
|
+
if (inheritedCmd) {
|
|
209
|
+
createOpts.Cmd = inheritedCmd;
|
|
210
|
+
}
|
|
177
211
|
}
|
|
178
212
|
|
|
179
213
|
if (stack.resourceLimits?.memory) {
|
|
@@ -190,7 +224,7 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
190
224
|
createOpts.HostConfig.SecurityOpt = ['no-new-privileges:true'];
|
|
191
225
|
|
|
192
226
|
const container = await this.docker.createContainer(createOpts);
|
|
193
|
-
|
|
227
|
+
|
|
194
228
|
// Connect to additional networks before starting
|
|
195
229
|
if (targetNetworks.length > 0) {
|
|
196
230
|
const startIndex = targetNetworkMode ? 0 : 1;
|
|
@@ -199,7 +233,9 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
199
233
|
const net = this.docker.getNetwork(targetNetworks[i]);
|
|
200
234
|
await net.connect({ Container: container.id });
|
|
201
235
|
} catch (err: any) {
|
|
202
|
-
console.warn(
|
|
236
|
+
console.warn(
|
|
237
|
+
`[DockerAdapter] Failed to connect container ${container.id} to network ${targetNetworks[i]}: ${err.message}`,
|
|
238
|
+
);
|
|
203
239
|
}
|
|
204
240
|
}
|
|
205
241
|
}
|
|
@@ -209,9 +245,7 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
209
245
|
}
|
|
210
246
|
} else if (diff < 0) {
|
|
211
247
|
// Scale DOWN — remove newest first (LIFO)
|
|
212
|
-
const sorted = running.sort(
|
|
213
|
-
(a, b) => b.createdAt.getTime() - a.createdAt.getTime(),
|
|
214
|
-
);
|
|
248
|
+
const sorted = running.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
215
249
|
const toRemove = sorted.slice(0, Math.abs(diff));
|
|
216
250
|
|
|
217
251
|
for (const c of toRemove) {
|
|
@@ -334,14 +368,17 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
334
368
|
.split(',')
|
|
335
369
|
.map((part) => part.trim())
|
|
336
370
|
.filter(Boolean)
|
|
337
|
-
.reduce(
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
371
|
+
.reduce(
|
|
372
|
+
(acc, part) => {
|
|
373
|
+
const [key, ...valueParts] = part.split('=');
|
|
374
|
+
const value = valueParts.join('=');
|
|
375
|
+
if (key?.trim() && value?.trim()) {
|
|
376
|
+
acc[key.trim()] = value.trim();
|
|
377
|
+
}
|
|
378
|
+
return acc;
|
|
379
|
+
},
|
|
380
|
+
{} as Record<string, string>,
|
|
381
|
+
);
|
|
345
382
|
}
|
|
346
383
|
|
|
347
384
|
private labelsMatch(labels: Record<string, string>, expected: Record<string, string>): boolean {
|