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.
Files changed (90) hide show
  1. package/README.md +17 -5
  2. package/dist/client/index.js +1 -1
  3. package/dist/externalVersion.js +5 -5
  4. package/dist/locale/en-US.json +28 -4
  5. package/dist/locale/vi-VN.json +28 -4
  6. package/dist/locale/zh-CN.json +28 -4
  7. package/dist/server/actions/event-queue-monitor.js +123 -1
  8. package/dist/server/actions/orchestrator.js +20 -1
  9. package/dist/server/actions/plugin-operations.js +171 -0
  10. package/dist/server/collections/app.js +38 -0
  11. package/dist/server/collections/cluster-manager-acl-cache.js +44 -0
  12. package/dist/server/collections/cluster-manager-cache-mgr.js +44 -0
  13. package/dist/server/collections/cluster-manager-cluster.js +44 -0
  14. package/dist/server/collections/cluster-manager-lock.js +44 -0
  15. package/dist/server/collections/cluster-manager-plugins.js +44 -0
  16. package/dist/server/collections/cluster-manager-queue.js +44 -0
  17. package/dist/server/collections/cluster-manager-redis.js +44 -0
  18. package/dist/server/collections/cluster-manager-workflow.js +44 -0
  19. package/dist/server/collections/cluster-manager.js +44 -0
  20. package/dist/server/collections/worker-orchestrator.js +44 -0
  21. package/dist/server/collections/worker-packages.js +44 -0
  22. package/dist/server/orchestrator/docker-adapter.js +19 -6
  23. package/dist/server/plugin.js +9 -3
  24. package/package.json +9 -4
  25. package/src/client/ClusterManagerLayout.tsx +16 -10
  26. package/src/client/ContainerOrchestrator.tsx +38 -3
  27. package/src/client/EventQueueMonitor.tsx +349 -202
  28. package/src/client/PluginOperations.tsx +226 -0
  29. package/src/locale/en-US.json +28 -4
  30. package/src/locale/vi-VN.json +28 -4
  31. package/src/locale/zh-CN.json +28 -4
  32. package/src/server/actions/event-queue-monitor.ts +234 -95
  33. package/src/server/actions/orchestrator.ts +21 -1
  34. package/src/server/actions/plugin-operations.ts +151 -0
  35. package/src/server/collections/app.ts +7 -0
  36. package/src/server/collections/cluster-manager-acl-cache.ts +23 -0
  37. package/src/server/collections/cluster-manager-cache-mgr.ts +23 -0
  38. package/src/server/collections/cluster-manager-cluster.ts +23 -0
  39. package/src/server/collections/cluster-manager-lock.ts +23 -0
  40. package/src/server/collections/cluster-manager-plugins.ts +19 -0
  41. package/src/server/collections/cluster-manager-queue.ts +23 -0
  42. package/src/server/collections/cluster-manager-redis.ts +23 -0
  43. package/src/server/collections/cluster-manager-workflow.ts +23 -0
  44. package/src/server/collections/cluster-manager.ts +23 -0
  45. package/src/server/collections/worker-orchestrator.ts +23 -0
  46. package/src/server/collections/worker-packages.ts +23 -0
  47. package/src/server/orchestrator/docker-adapter.ts +25 -9
  48. package/src/server/orchestrator/types.ts +3 -0
  49. package/src/server/plugin.ts +29 -21
  50. package/dist/client/AclCacheManager.d.ts +0 -2
  51. package/dist/client/CacheMonitor.d.ts +0 -2
  52. package/dist/client/ClusterManagerLayout.d.ts +0 -2
  53. package/dist/client/ClusterNodes.d.ts +0 -2
  54. package/dist/client/ContainerOrchestrator.d.ts +0 -2
  55. package/dist/client/EventQueueMonitor.d.ts +0 -2
  56. package/dist/client/LockMonitor.d.ts +0 -2
  57. package/dist/client/PackageInstaller.d.ts +0 -2
  58. package/dist/client/RedisMonitor.d.ts +0 -2
  59. package/dist/client/TaskManager.d.ts +0 -2
  60. package/dist/client/WorkflowExecutions.d.ts +0 -2
  61. package/dist/client/index.d.ts +0 -5
  62. package/dist/client/utils.d.ts +0 -12
  63. package/dist/index.d.ts +0 -2
  64. package/dist/server/actions/acl-cache.d.ts +0 -53
  65. package/dist/server/actions/cache-monitor.d.ts +0 -23
  66. package/dist/server/actions/cluster-nodes.d.ts +0 -49
  67. package/dist/server/actions/event-queue-monitor.d.ts +0 -13
  68. package/dist/server/actions/lock-monitor.d.ts +0 -19
  69. package/dist/server/actions/orchestrator.d.ts +0 -53
  70. package/dist/server/actions/package-manager.d.ts +0 -6
  71. package/dist/server/actions/redis-monitor.d.ts +0 -12
  72. package/dist/server/actions/tasks.d.ts +0 -7
  73. package/dist/server/actions/workflow-executions.d.ts +0 -7
  74. package/dist/server/adapters/redis-lock-adapter.d.ts +0 -15
  75. package/dist/server/adapters/redis-node-registry.d.ts +0 -12
  76. package/dist/server/adapters/redis-pubsub-adapter.d.ts +0 -16
  77. package/dist/server/collections/orchestrator-settings.d.ts +0 -59
  78. package/dist/server/collections/orchestrator-stacks.d.ts +0 -102
  79. package/dist/server/collections/worker-packages-configs.d.ts +0 -3
  80. package/dist/server/index.d.ts +0 -1
  81. package/dist/server/orchestrator/PackageManager.d.ts +0 -37
  82. package/dist/server/orchestrator/docker-adapter.d.ts +0 -37
  83. package/dist/server/orchestrator/index.d.ts +0 -4
  84. package/dist/server/orchestrator/k8s-adapter.d.ts +0 -50
  85. package/dist/server/orchestrator/leader-election.d.ts +0 -48
  86. package/dist/server/orchestrator/types.d.ts +0 -79
  87. package/dist/server/plugin.d.ts +0 -26
  88. package/dist/server/utils/node.d.ts +0 -6
  89. package/dist/server/utils/redis.d.ts +0 -29
  90. 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
- // Inherit Networks if none specified
120
- if (!targetNetworkMode && targetNetworks.length === 0) {
121
- if (myInfo?.NetworkSettings?.Networks) {
122
- targetNetworks = Object.keys(myInfo.NetworkSettings.Networks);
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 (!targetNetworkMode && targetNetworks.length > 1) {
189
- for (let i = 1; i < targetNetworks.length; i++) {
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
  }
@@ -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 Worker Monitor UI');
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
  }
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare function AclCacheManager(): React.JSX.Element;
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare function CacheMonitor(): React.JSX.Element;
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare function ClusterManagerLayout(): React.JSX.Element;
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare function ClusterNodes(): React.JSX.Element;
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare function ContainerOrchestrator(): React.JSX.Element;
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare function EventQueueMonitor(): React.JSX.Element;
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare function LockMonitor(): React.JSX.Element;
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare const PackageInstaller: React.FC;
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare function RedisMonitor(): React.JSX.Element;
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare function TaskManager(): React.JSX.Element;
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare function WorkflowExecutions(): React.JSX.Element;
@@ -1,5 +0,0 @@
1
- import { Plugin } from '@nocobase/client';
2
- export declare class PluginClusterManagerClient extends Plugin {
3
- load(): Promise<void>;
4
- }
5
- export default PluginClusterManagerClient;
@@ -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,2 +0,0 @@
1
- export * from './server';
2
- export { default } from './server';
@@ -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
- }