plugin-cluster-manager 1.1.0 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -5
- package/dist/client/index.js +1 -1
- package/dist/externalVersion.js +5 -5
- package/dist/locale/en-US.json +28 -4
- package/dist/locale/vi-VN.json +28 -4
- package/dist/locale/zh-CN.json +28 -4
- package/dist/server/actions/event-queue-monitor.js +123 -1
- package/dist/server/actions/orchestrator.js +20 -1
- package/dist/server/actions/plugin-operations.js +171 -0
- package/dist/server/collections/app.js +38 -0
- package/dist/server/collections/cluster-manager-acl-cache.js +44 -0
- package/dist/server/collections/cluster-manager-cache-mgr.js +44 -0
- package/dist/server/collections/cluster-manager-cluster.js +44 -0
- package/dist/server/collections/cluster-manager-lock.js +44 -0
- package/dist/server/collections/cluster-manager-plugins.js +44 -0
- package/dist/server/collections/cluster-manager-queue.js +44 -0
- package/dist/server/collections/cluster-manager-redis.js +44 -0
- package/dist/server/collections/cluster-manager-workflow.js +44 -0
- package/dist/server/collections/cluster-manager.js +44 -0
- package/dist/server/collections/worker-orchestrator.js +44 -0
- package/dist/server/collections/worker-packages.js +44 -0
- package/dist/server/orchestrator/docker-adapter.js +19 -6
- package/dist/server/plugin.js +9 -3
- package/package.json +9 -4
- package/src/client/ClusterManagerLayout.tsx +16 -10
- package/src/client/ContainerOrchestrator.tsx +38 -3
- package/src/client/EventQueueMonitor.tsx +349 -202
- package/src/client/PluginOperations.tsx +226 -0
- package/src/locale/en-US.json +28 -4
- package/src/locale/vi-VN.json +28 -4
- package/src/locale/zh-CN.json +28 -4
- package/src/server/actions/event-queue-monitor.ts +234 -95
- package/src/server/actions/orchestrator.ts +21 -1
- package/src/server/actions/plugin-operations.ts +151 -0
- package/src/server/collections/app.ts +7 -0
- package/src/server/collections/cluster-manager-acl-cache.ts +23 -0
- package/src/server/collections/cluster-manager-cache-mgr.ts +23 -0
- package/src/server/collections/cluster-manager-cluster.ts +23 -0
- package/src/server/collections/cluster-manager-lock.ts +23 -0
- package/src/server/collections/cluster-manager-plugins.ts +19 -0
- package/src/server/collections/cluster-manager-queue.ts +23 -0
- package/src/server/collections/cluster-manager-redis.ts +23 -0
- package/src/server/collections/cluster-manager-workflow.ts +23 -0
- package/src/server/collections/cluster-manager.ts +23 -0
- package/src/server/collections/worker-orchestrator.ts +23 -0
- package/src/server/collections/worker-packages.ts +23 -0
- package/src/server/orchestrator/docker-adapter.ts +25 -9
- package/src/server/orchestrator/types.ts +3 -0
- package/src/server/plugin.ts +29 -21
- 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/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 -53
- package/dist/server/actions/package-manager.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/orchestrator-settings.d.ts +0 -59
- package/dist/server/collections/orchestrator-stacks.d.ts +0 -102
- package/dist/server/collections/worker-packages-configs.d.ts +0 -3
- package/dist/server/index.d.ts +0 -1
- package/dist/server/orchestrator/PackageManager.d.ts +0 -37
- package/dist/server/orchestrator/docker-adapter.d.ts +0 -37
- 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 -79
- 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
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "clusterManagerRedis" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'clusterManagerRedis' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'clusterManagerRedis',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "clusterManagerWorkflow" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'clusterManagerWorkflow' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'clusterManagerWorkflow',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "clusterManager" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'clusterManager' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'clusterManager',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "workerOrchestrator" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'workerOrchestrator' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'workerOrchestrator',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "workerPackages" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'workerPackages' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'workerPackages',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -116,11 +116,11 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
116
116
|
const myContainer = this.docker.getContainer(myContainerId);
|
|
117
117
|
const myInfo = await myContainer.inspect();
|
|
118
118
|
|
|
119
|
-
//
|
|
120
|
-
if (
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
// Always inherit Networks so worker can communicate with main app
|
|
120
|
+
if (myInfo?.NetworkSettings?.Networks) {
|
|
121
|
+
const inheritedNetworks = Object.keys(myInfo.NetworkSettings.Networks);
|
|
122
|
+
targetNetworks = Array.from(new Set([...inheritedNetworks, ...targetNetworks]));
|
|
123
|
+
console.log('[DockerAdapter] Inherited networks:', targetNetworks);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
// Inherit Environment Variables and merge with stack.envVars
|
|
@@ -134,16 +134,23 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
134
134
|
});
|
|
135
135
|
// Overwrite with explicitly defined env vars
|
|
136
136
|
Object.assign(envDict, stack.envVars || {});
|
|
137
|
+
|
|
137
138
|
targetEnvVars = Object.entries(envDict).map(([k, v]) => `${k}=${v}`);
|
|
138
139
|
}
|
|
139
|
-
|
|
140
140
|
// Inherit Volumes (Binds)
|
|
141
141
|
if (myInfo?.HostConfig?.Binds) {
|
|
142
142
|
const inheritedBinds = myInfo.HostConfig.Binds as string[];
|
|
143
143
|
targetVolumes = Array.from(new Set([...inheritedBinds, ...targetVolumes]));
|
|
144
144
|
}
|
|
145
|
-
} catch (e) {
|
|
145
|
+
} catch (e: any) {
|
|
146
146
|
// Ignore error if not running in a container or cannot inspect
|
|
147
|
+
console.error('[DockerAdapter] Failed to inherit container config:', e.message);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Automatically separate logs for workers to prevent log interleaving with the main app
|
|
151
|
+
const hasLoggerBase = targetEnvVars.some(e => e.startsWith('LOGGER_BASE_PATH='));
|
|
152
|
+
if (!hasLoggerBase) {
|
|
153
|
+
targetEnvVars.push(`LOGGER_BASE_PATH=/app/nocobase/storage/logs/${stack.name}`);
|
|
147
154
|
}
|
|
148
155
|
|
|
149
156
|
for (let i = 0; i < diff; i++) {
|
|
@@ -185,8 +192,9 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
185
192
|
const container = await this.docker.createContainer(createOpts);
|
|
186
193
|
|
|
187
194
|
// Connect to additional networks before starting
|
|
188
|
-
if (
|
|
189
|
-
|
|
195
|
+
if (targetNetworks.length > 0) {
|
|
196
|
+
const startIndex = targetNetworkMode ? 0 : 1;
|
|
197
|
+
for (let i = startIndex; i < targetNetworks.length; i++) {
|
|
190
198
|
try {
|
|
191
199
|
const net = this.docker.getNetwork(targetNetworks[i]);
|
|
192
200
|
await net.connect({ Container: container.id });
|
|
@@ -284,6 +292,14 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
284
292
|
return this.demuxDockerLogs(logBuffer);
|
|
285
293
|
}
|
|
286
294
|
|
|
295
|
+
async listNetworks(): Promise<{ id: string; name: string }[]> {
|
|
296
|
+
const networks = await this.docker.listNetworks();
|
|
297
|
+
return networks.map((n: any) => ({
|
|
298
|
+
id: n.Id,
|
|
299
|
+
name: n.Name,
|
|
300
|
+
}));
|
|
301
|
+
}
|
|
302
|
+
|
|
287
303
|
// ─── Private helpers ───
|
|
288
304
|
|
|
289
305
|
private mapState(state: string): ContainerInfo['status'] {
|
|
@@ -92,4 +92,7 @@ export interface IOrchestratorAdapter {
|
|
|
92
92
|
|
|
93
93
|
/** Get tail logs from a container */
|
|
94
94
|
getLogs(containerId: string, tail?: number): Promise<string>;
|
|
95
|
+
|
|
96
|
+
/** List available networks (if supported by adapter) */
|
|
97
|
+
listNetworks?(): Promise<{ id: string; name: string }[]>;
|
|
95
98
|
}
|
package/src/server/plugin.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { RedisPubSubAdapter } from './adapters/redis-pubsub-adapter';
|
|
|
15
15
|
import { RedisNodeRegistry } from './adapters/redis-node-registry';
|
|
16
16
|
import { RedisLockAdapter } from './adapters/redis-lock-adapter';
|
|
17
17
|
import { orchestratorActions } from './actions/orchestrator';
|
|
18
|
+
import { pluginOperationsActions } from './actions/plugin-operations';
|
|
18
19
|
import type { IOrchestratorAdapter } from './orchestrator/types';
|
|
19
20
|
import { DockerAdapter } from './orchestrator/docker-adapter';
|
|
20
21
|
import { K8sAdapter } from './orchestrator/k8s-adapter';
|
|
@@ -28,7 +29,7 @@ export class PluginClusterManagerServer extends Plugin {
|
|
|
28
29
|
public leaderElection: LeaderElection | null = null;
|
|
29
30
|
|
|
30
31
|
async beforeLoad() {
|
|
31
|
-
this.db.import({ directory: path.resolve(__dirname, 'collections') });
|
|
32
|
+
await this.db.import({ directory: path.resolve(__dirname, 'collections') });
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
async load() {
|
|
@@ -240,11 +241,17 @@ export class PluginClusterManagerServer extends Plugin {
|
|
|
240
241
|
actions: cacheMonitorActions,
|
|
241
242
|
});
|
|
242
243
|
|
|
243
|
-
// Package manager (installs apt/npm/python packages across nodes)
|
|
244
|
-
this.app.resourcer.define({
|
|
245
|
-
name: 'workerPackages',
|
|
246
|
-
actions: packageManagerActions,
|
|
247
|
-
});
|
|
244
|
+
// Package manager (installs apt/npm/python packages across nodes)
|
|
245
|
+
this.app.resourcer.define({
|
|
246
|
+
name: 'workerPackages',
|
|
247
|
+
actions: packageManagerActions,
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Plugin operations (force disable/remove application plugin records)
|
|
251
|
+
this.app.resourcer.define({
|
|
252
|
+
name: 'clusterManagerPlugins',
|
|
253
|
+
actions: pluginOperationsActions,
|
|
254
|
+
});
|
|
248
255
|
|
|
249
256
|
// Install ACL cache middleware inside the ACL chain so cached permissions are not overwritten.
|
|
250
257
|
const aclCacheMiddleware = createAclCacheMiddleware(this.app);
|
|
@@ -279,11 +286,12 @@ export class PluginClusterManagerServer extends Plugin {
|
|
|
279
286
|
'clusterManagerQueue:*',
|
|
280
287
|
'clusterManagerLock:*',
|
|
281
288
|
'clusterManagerCacheMgr:*',
|
|
282
|
-
'workerOrchestrator:*',
|
|
283
|
-
'orchestratorStacks:*',
|
|
284
|
-
'workerPackages:*',
|
|
285
|
-
|
|
286
|
-
|
|
289
|
+
'workerOrchestrator:*',
|
|
290
|
+
'orchestratorStacks:*',
|
|
291
|
+
'workerPackages:*',
|
|
292
|
+
'clusterManagerPlugins:*',
|
|
293
|
+
],
|
|
294
|
+
});
|
|
287
295
|
|
|
288
296
|
// ── Container Orchestrator ──
|
|
289
297
|
await this.initOrchestrator();
|
|
@@ -365,16 +373,16 @@ export class PluginClusterManagerServer extends Plugin {
|
|
|
365
373
|
} else {
|
|
366
374
|
// Fall back to env var for initial setup
|
|
367
375
|
const envAdapter = process.env.ORCHESTRATOR_ADAPTER;
|
|
368
|
-
if (envAdapter && envAdapter !== 'none') {
|
|
369
|
-
await this.connectAdapter({
|
|
370
|
-
adapterType: envAdapter,
|
|
371
|
-
dockerSocketPath: process.env.DOCKER_SOCKET || '/var/run/docker.sock',
|
|
372
|
-
k8sNamespace: 'nocobase',
|
|
373
|
-
});
|
|
374
|
-
} else {
|
|
375
|
-
this.app.logger.info('[Orchestrator] No adapter configured — configurable via
|
|
376
|
-
}
|
|
377
|
-
}
|
|
376
|
+
if (envAdapter && envAdapter !== 'none') {
|
|
377
|
+
await this.connectAdapter({
|
|
378
|
+
adapterType: envAdapter,
|
|
379
|
+
dockerSocketPath: process.env.DOCKER_SOCKET || '/var/run/docker.sock',
|
|
380
|
+
k8sNamespace: 'nocobase',
|
|
381
|
+
});
|
|
382
|
+
} else {
|
|
383
|
+
this.app.logger.info('[Orchestrator] No adapter configured — configurable via Cluster Manager UI');
|
|
384
|
+
}
|
|
385
|
+
}
|
|
378
386
|
} catch (err: any) {
|
|
379
387
|
this.app.logger.warn(`[Orchestrator] Could not load settings: ${err.message}`);
|
|
380
388
|
}
|
package/dist/client/index.d.ts
DELETED
package/dist/client/utils.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared i18n hook for the cluster-manager plugin.
|
|
3
|
-
*/
|
|
4
|
-
export declare function useT(): (key: string) => string;
|
|
5
|
-
/**
|
|
6
|
-
* Format bytes into human-readable string (B, KB, MB, GB).
|
|
7
|
-
*/
|
|
8
|
-
export declare function formatBytes(bytes: number): string;
|
|
9
|
-
/**
|
|
10
|
-
* Format seconds into human-readable uptime string (e.g., "2d 5h 30m").
|
|
11
|
-
*/
|
|
12
|
-
export declare function formatUptime(seconds: number): string;
|
package/dist/index.d.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { Context } from '@nocobase/actions';
|
|
2
|
-
/**
|
|
3
|
-
* In-memory ACL stats counter.
|
|
4
|
-
* Tracks total checks, cache hits/misses per role:resource:action.
|
|
5
|
-
*/
|
|
6
|
-
export interface AclCacheStats {
|
|
7
|
-
totalChecks: number;
|
|
8
|
-
cacheHits: number;
|
|
9
|
-
cacheMisses: number;
|
|
10
|
-
startedAt: string;
|
|
11
|
-
detailByRole: Record<string, {
|
|
12
|
-
checks: number;
|
|
13
|
-
hits: number;
|
|
14
|
-
misses: number;
|
|
15
|
-
}>;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Middleware that caches the permission object computed by the ACL middleware.
|
|
19
|
-
* Install via: app.acl.use(aclCacheMiddleware, { tag: 'aclCache', before: 'core', after: 'allow-manager' })
|
|
20
|
-
*
|
|
21
|
-
* FIX: Previously monkey-patched ctx.app.acl.can per-request, which is a race condition
|
|
22
|
-
* because acl is a shared singleton across concurrent requests. Now we use a post-check
|
|
23
|
-
* approach that reads from cache first and writes after the ACL middleware runs, without
|
|
24
|
-
* ever replacing the shared acl.can method.
|
|
25
|
-
*/
|
|
26
|
-
export declare function createAclCacheMiddleware(app: any): (ctx: Context, next: () => Promise<void>) => Promise<void>;
|
|
27
|
-
export declare const aclCacheActions: {
|
|
28
|
-
/**
|
|
29
|
-
* GET /clusterManagerAclCache:stats
|
|
30
|
-
* Returns ACL cache hit/miss statistics
|
|
31
|
-
*/
|
|
32
|
-
stats(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
33
|
-
/**
|
|
34
|
-
* GET /clusterManagerAclCache:listKeys
|
|
35
|
-
* Lists all cached ACL permission keys
|
|
36
|
-
*/
|
|
37
|
-
listKeys(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
38
|
-
/**
|
|
39
|
-
* POST /clusterManagerAclCache:clear
|
|
40
|
-
* Clear all ACL cache entries and reset stats
|
|
41
|
-
*/
|
|
42
|
-
clear(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
43
|
-
/**
|
|
44
|
-
* POST /clusterManagerAclCache:resetStats
|
|
45
|
-
* Reset the in-memory ACL stats counters
|
|
46
|
-
*/
|
|
47
|
-
resetStats(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
48
|
-
/**
|
|
49
|
-
* POST /clusterManagerAclCache:clearRole
|
|
50
|
-
* Clear ACL cache entries for a specific role
|
|
51
|
-
*/
|
|
52
|
-
clearRole(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
53
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Context } from '@nocobase/actions';
|
|
2
|
-
export declare const cacheMonitorActions: {
|
|
3
|
-
/**
|
|
4
|
-
* GET /clusterManagerCacheMgr:stores
|
|
5
|
-
* List all registered cache stores and their config
|
|
6
|
-
*/
|
|
7
|
-
stores(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
8
|
-
/**
|
|
9
|
-
* GET /clusterManagerCacheMgr:caches
|
|
10
|
-
* List all created named caches
|
|
11
|
-
*/
|
|
12
|
-
caches(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
13
|
-
/**
|
|
14
|
-
* GET /clusterManagerCacheMgr:redisMemory
|
|
15
|
-
* Get Redis memory usage for cache keys
|
|
16
|
-
*/
|
|
17
|
-
redisMemory(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
18
|
-
/**
|
|
19
|
-
* POST /clusterManagerCacheMgr:flushAll
|
|
20
|
-
* Flush all caches via CacheManager
|
|
21
|
-
*/
|
|
22
|
-
flushAll(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
23
|
-
};
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { Context } from '@nocobase/actions';
|
|
2
|
-
/**
|
|
3
|
-
* Read the last N lines from the local system log file.
|
|
4
|
-
* Extracted so it can be called from both the HTTP action and the PubSub subscriber.
|
|
5
|
-
*/
|
|
6
|
-
export declare function readLocalLogs(app: any, maxLines: number): Promise<{
|
|
7
|
-
node: {
|
|
8
|
-
hostname: string;
|
|
9
|
-
pid: number;
|
|
10
|
-
workerMode: string;
|
|
11
|
-
};
|
|
12
|
-
lines: string[];
|
|
13
|
-
file: string;
|
|
14
|
-
}>;
|
|
15
|
-
export declare const clusterActions: {
|
|
16
|
-
/**
|
|
17
|
-
* GET /clusterManagerCluster:current
|
|
18
|
-
* Always returns info about the APP node (not workers).
|
|
19
|
-
* If this request is handled by a worker, we look up the APP node from Redis.
|
|
20
|
-
*/
|
|
21
|
-
current(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
22
|
-
/**
|
|
23
|
-
* GET /clusterManagerCluster:list
|
|
24
|
-
* Returns all known cluster environments/nodes (if discovery adapter supports it)
|
|
25
|
-
*/
|
|
26
|
-
list(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
27
|
-
/**
|
|
28
|
-
* GET /clusterManagerCluster:health
|
|
29
|
-
* Health check for all subsystems
|
|
30
|
-
*/
|
|
31
|
-
health(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
32
|
-
/**
|
|
33
|
-
* POST /clusterManagerCluster:restart
|
|
34
|
-
* Publishes a restart signal to target nodes orchestrating a soft NocoBase restart or a hard docker daemon rebirth
|
|
35
|
-
*/
|
|
36
|
-
restart(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
37
|
-
/**
|
|
38
|
-
* GET /clusterManagerCluster:logs?targetNodeId=xxx&lines=200
|
|
39
|
-
*
|
|
40
|
-
* HA-aware log viewer. Reads logs from a specific node in the cluster.
|
|
41
|
-
*
|
|
42
|
-
* Flow:
|
|
43
|
-
* 1. If targetNodeId matches current node (or is empty) → read local FS directly
|
|
44
|
-
* 2. Otherwise → publish a log request via PubSub → target node reads its local FS
|
|
45
|
-
* and writes the result to a Redis key → this handler polls Redis until the
|
|
46
|
-
* response arrives (max 10s) → returns it to the client
|
|
47
|
-
*/
|
|
48
|
-
logs(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
49
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Context } from '@nocobase/actions';
|
|
2
|
-
export declare const eventQueueActions: {
|
|
3
|
-
/**
|
|
4
|
-
* GET /clusterManagerQueue:stats
|
|
5
|
-
* Returns event queue statistics
|
|
6
|
-
*/
|
|
7
|
-
stats(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
8
|
-
/**
|
|
9
|
-
* GET /clusterManagerQueue:messages
|
|
10
|
-
* List pending messages in a specific channel (memory adapter only)
|
|
11
|
-
*/
|
|
12
|
-
messages(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
13
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Context } from '@nocobase/actions';
|
|
2
|
-
export declare const lockActions: {
|
|
3
|
-
/**
|
|
4
|
-
* GET /clusterManagerLock:info
|
|
5
|
-
* Returns lock manager info
|
|
6
|
-
*/
|
|
7
|
-
info(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
8
|
-
/**
|
|
9
|
-
* GET /clusterManagerLock:list
|
|
10
|
-
* List active locks
|
|
11
|
-
*/
|
|
12
|
-
list(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
13
|
-
/**
|
|
14
|
-
* POST /clusterManagerLock:release
|
|
15
|
-
* Force release a stuck lock (admin emergency action)
|
|
16
|
-
* Uses compare-and-swap via DEL for Redis locks with the correct key prefix.
|
|
17
|
-
*/
|
|
18
|
-
release(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
19
|
-
};
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Orchestrator Actions
|
|
3
|
-
*
|
|
4
|
-
* API endpoints for container management. Write operations (scale, start, stop, remove)
|
|
5
|
-
* are guarded by leader election — only the leader node can execute them.
|
|
6
|
-
*/
|
|
7
|
-
import { Context } from '@nocobase/actions';
|
|
8
|
-
export declare const orchestratorActions: {
|
|
9
|
-
/**
|
|
10
|
-
* GET /workerOrchestrator:ping
|
|
11
|
-
* Test connectivity to the container runtime
|
|
12
|
-
*/
|
|
13
|
-
ping(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
14
|
-
/**
|
|
15
|
-
* GET /workerOrchestrator:containers?stackId=1
|
|
16
|
-
* List live containers for a stack
|
|
17
|
-
*/
|
|
18
|
-
containers(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
19
|
-
/**
|
|
20
|
-
* POST /workerOrchestrator:scale
|
|
21
|
-
* Body: { stackId: 1, replicas: 3 }
|
|
22
|
-
* Leader-only
|
|
23
|
-
*/
|
|
24
|
-
scale(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
25
|
-
/**
|
|
26
|
-
* POST /workerOrchestrator:start
|
|
27
|
-
* Body: { stackId: 1, containerId: "abc123" }
|
|
28
|
-
* Leader-only
|
|
29
|
-
*/
|
|
30
|
-
start(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
31
|
-
/**
|
|
32
|
-
* POST /workerOrchestrator:stop
|
|
33
|
-
* Body: { stackId: 1, containerId: "abc123" }
|
|
34
|
-
* Leader-only
|
|
35
|
-
*/
|
|
36
|
-
stop(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
37
|
-
/**
|
|
38
|
-
* POST /workerOrchestrator:remove
|
|
39
|
-
* Body: { stackId: 1, containerId: "abc123" }
|
|
40
|
-
* Leader-only
|
|
41
|
-
*/
|
|
42
|
-
remove(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
43
|
-
/**
|
|
44
|
-
* GET /workerOrchestrator:stats?containerId=abc123
|
|
45
|
-
* Get real-time stats for a container
|
|
46
|
-
*/
|
|
47
|
-
stats(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
48
|
-
/**
|
|
49
|
-
* GET /workerOrchestrator:logs?containerId=abc123&tail=100
|
|
50
|
-
* Get tail logs from a container
|
|
51
|
-
*/
|
|
52
|
-
logs(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
53
|
-
};
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export declare const packageManagerActions: {
|
|
2
|
-
installPackages(ctx: any, next: () => Promise<void>): Promise<void>;
|
|
3
|
-
getPackageConfig(ctx: any, next: () => Promise<void>): Promise<void>;
|
|
4
|
-
savePackageConfig(ctx: any, next: () => Promise<void>): Promise<void>;
|
|
5
|
-
resetInitStatus(ctx: any, next: () => Promise<void>): Promise<void>;
|
|
6
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Context } from '@nocobase/actions';
|
|
2
|
-
export declare const redisActions: {
|
|
3
|
-
info(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
4
|
-
clients(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
5
|
-
pubsub(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
6
|
-
slowlog(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
7
|
-
/**
|
|
8
|
-
* GET /clusterManagerRedis:syncMessages
|
|
9
|
-
* Returns info about NocoBase sync message channels (pub/sub layer)
|
|
10
|
-
*/
|
|
11
|
-
syncMessages(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
12
|
-
};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Context } from '@nocobase/actions';
|
|
2
|
-
export declare const tasksActions: {
|
|
3
|
-
list(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
4
|
-
cancel(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
5
|
-
retry(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
6
|
-
purge(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
7
|
-
};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Context } from '@nocobase/actions';
|
|
2
|
-
export declare const workflowActions: {
|
|
3
|
-
list(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
4
|
-
getJobs(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
5
|
-
cancel(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
6
|
-
purge(ctx: Context, next: () => Promise<void>): Promise<void>;
|
|
7
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { ILockAdapter, ILock, Releaser } from '@nocobase/lock-manager';
|
|
2
|
-
import { Application } from '@nocobase/server';
|
|
3
|
-
export declare class RedisLockAdapter implements ILockAdapter {
|
|
4
|
-
private options;
|
|
5
|
-
private client;
|
|
6
|
-
constructor(options: {
|
|
7
|
-
url?: string;
|
|
8
|
-
app: Application;
|
|
9
|
-
});
|
|
10
|
-
connect(): Promise<void>;
|
|
11
|
-
close(): Promise<void>;
|
|
12
|
-
acquire(key: string, ttl: number): Promise<Releaser>;
|
|
13
|
-
runExclusive<T>(key: string, fn: () => Promise<T>, ttl: number): Promise<T>;
|
|
14
|
-
tryAcquire(key: string, timeout?: number): Promise<ILock>;
|
|
15
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export declare class RedisNodeRegistry {
|
|
2
|
-
private app;
|
|
3
|
-
private timer;
|
|
4
|
-
private readonly ttlSecs;
|
|
5
|
-
private readonly intervalMs;
|
|
6
|
-
private readonly keyPrefix;
|
|
7
|
-
constructor(app: any);
|
|
8
|
-
start(): void;
|
|
9
|
-
stop(): void;
|
|
10
|
-
private heartbeat;
|
|
11
|
-
getNodes(): Promise<any[]>;
|
|
12
|
-
}
|