plugin-cluster-manager 1.1.11 → 1.1.15

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 (116) hide show
  1. package/client-v2.d.ts +2 -0
  2. package/client-v2.js +1 -0
  3. package/dist/client/index.js +1 -1
  4. package/dist/client-v2/914.c0bce51908fd81d7.js +10 -0
  5. package/dist/client-v2/index.js +10 -0
  6. package/dist/externalVersion.js +6 -5
  7. package/dist/locale/en-US.json +138 -124
  8. package/dist/locale/vi-VN.json +139 -125
  9. package/dist/locale/zh-CN.json +140 -125
  10. package/dist/server/actions/cluster-nodes.js +2 -6
  11. package/dist/server/actions/doctor.js +1 -5
  12. package/dist/server/actions/orchestrator.js +37 -0
  13. package/dist/server/actions/queue-mappings.js +107 -0
  14. package/dist/server/collections/worker-queue-mappings.js +106 -0
  15. package/dist/server/orchestrator/PackageManager.js +1 -8
  16. package/dist/server/orchestrator/docker-adapter.js +49 -27
  17. package/dist/server/plugin.js +10 -8
  18. package/dist/server/queue-scanner.js +141 -0
  19. package/dist/server/utils/node.js +30 -2
  20. package/package.json +46 -42
  21. package/src/client/AclCacheManager.tsx +292 -287
  22. package/src/client/CacheMonitor.tsx +2 -2
  23. package/src/client/ClusterManagerLayout.tsx +6 -0
  24. package/src/client/ClusterNodes.tsx +11 -4
  25. package/src/client/ContainerOrchestrator.tsx +186 -104
  26. package/src/client/Doctor.tsx +2 -2
  27. package/src/client/EventQueueMonitor.tsx +2 -2
  28. package/src/client/LockMonitor.tsx +2 -2
  29. package/src/client/NginxCacheManager.tsx +2 -2
  30. package/src/client/PackageInstaller.tsx +2 -2
  31. package/src/client/PluginOperations.tsx +2 -2
  32. package/src/client/QueueAssignment.tsx +355 -0
  33. package/src/client/RedisMonitor.tsx +3 -3
  34. package/src/client/TaskManager.tsx +194 -187
  35. package/src/client/WorkflowExecutions.tsx +243 -238
  36. package/src/client/utils.ts +1 -1
  37. package/src/client-v2/plugin.tsx +24 -0
  38. package/src/locale/en-US.json +138 -124
  39. package/src/locale/vi-VN.json +139 -125
  40. package/src/locale/zh-CN.json +140 -125
  41. package/src/server/actions/cluster-nodes.ts +4 -7
  42. package/src/server/actions/doctor.ts +11 -9
  43. package/src/server/actions/orchestrator.ts +54 -2
  44. package/src/server/actions/queue-mappings.ts +94 -0
  45. package/src/server/adapters/redis-node-registry.ts +126 -131
  46. package/src/server/collections/worker-queue-mappings.ts +85 -0
  47. package/src/server/orchestrator/PackageManager.ts +2 -10
  48. package/src/server/orchestrator/docker-adapter.ts +74 -37
  49. package/src/server/plugin.ts +15 -12
  50. package/src/server/queue-scanner.ts +154 -0
  51. package/src/server/utils/node.ts +48 -0
  52. package/dist/client/AclCacheManager.d.ts +0 -2
  53. package/dist/client/CacheMonitor.d.ts +0 -2
  54. package/dist/client/ClusterManagerLayout.d.ts +0 -2
  55. package/dist/client/ClusterNodes.d.ts +0 -2
  56. package/dist/client/ContainerOrchestrator.d.ts +0 -2
  57. package/dist/client/Doctor.d.ts +0 -2
  58. package/dist/client/EventQueueMonitor.d.ts +0 -2
  59. package/dist/client/LockMonitor.d.ts +0 -2
  60. package/dist/client/NginxCacheManager.d.ts +0 -2
  61. package/dist/client/PackageInstaller.d.ts +0 -2
  62. package/dist/client/PluginOperations.d.ts +0 -2
  63. package/dist/client/RedisMonitor.d.ts +0 -2
  64. package/dist/client/TaskManager.d.ts +0 -2
  65. package/dist/client/WorkflowExecutions.d.ts +0 -2
  66. package/dist/client/index.d.ts +0 -5
  67. package/dist/client/utils/clientSafeCache.d.ts +0 -3
  68. package/dist/client/utils/requestDedupInterceptor.d.ts +0 -2
  69. package/dist/client/utils.d.ts +0 -12
  70. package/dist/index.d.ts +0 -2
  71. package/dist/server/actions/acl-cache.d.ts +0 -53
  72. package/dist/server/actions/cache-monitor.d.ts +0 -33
  73. package/dist/server/actions/cluster-nodes.d.ts +0 -64
  74. package/dist/server/actions/doctor.d.ts +0 -82
  75. package/dist/server/actions/event-queue-monitor.d.ts +0 -13
  76. package/dist/server/actions/lock-monitor.d.ts +0 -19
  77. package/dist/server/actions/orchestrator.d.ts +0 -58
  78. package/dist/server/actions/package-manager.d.ts +0 -6
  79. package/dist/server/actions/plugin-operations.d.ts +0 -6
  80. package/dist/server/actions/redis-monitor.d.ts +0 -12
  81. package/dist/server/actions/tasks.d.ts +0 -7
  82. package/dist/server/actions/workflow-executions.d.ts +0 -7
  83. package/dist/server/adapters/redis-lock-adapter.d.ts +0 -15
  84. package/dist/server/adapters/redis-node-registry.d.ts +0 -12
  85. package/dist/server/adapters/redis-pubsub-adapter.d.ts +0 -16
  86. package/dist/server/collections/app.d.ts +0 -8
  87. package/dist/server/collections/cluster-manager-acl-cache.d.ts +0 -22
  88. package/dist/server/collections/cluster-manager-cache-mgr.d.ts +0 -22
  89. package/dist/server/collections/cluster-manager-cluster.d.ts +0 -22
  90. package/dist/server/collections/cluster-manager-doctor-runs.d.ts +0 -3
  91. package/dist/server/collections/cluster-manager-doctor.d.ts +0 -18
  92. package/dist/server/collections/cluster-manager-lock.d.ts +0 -22
  93. package/dist/server/collections/cluster-manager-plugins.d.ts +0 -18
  94. package/dist/server/collections/cluster-manager-queue.d.ts +0 -22
  95. package/dist/server/collections/cluster-manager-redis.d.ts +0 -22
  96. package/dist/server/collections/cluster-manager-workflow.d.ts +0 -22
  97. package/dist/server/collections/cluster-manager.d.ts +0 -22
  98. package/dist/server/collections/orchestrator-settings.d.ts +0 -59
  99. package/dist/server/collections/orchestrator-stacks.d.ts +0 -102
  100. package/dist/server/collections/worker-orchestrator.d.ts +0 -22
  101. package/dist/server/collections/worker-packages-configs.d.ts +0 -3
  102. package/dist/server/collections/worker-packages.d.ts +0 -22
  103. package/dist/server/hooks/cacheInvalidationHooks.d.ts +0 -1
  104. package/dist/server/middlewares/listMetaCacheMiddleware.d.ts +0 -2
  105. package/dist/server/orchestrator/PackageManager.d.ts +0 -39
  106. package/dist/server/orchestrator/docker-adapter.d.ts +0 -41
  107. package/dist/server/orchestrator/index.d.ts +0 -4
  108. package/dist/server/orchestrator/k8s-adapter.d.ts +0 -50
  109. package/dist/server/orchestrator/leader-election.d.ts +0 -48
  110. package/dist/server/orchestrator/types.d.ts +0 -84
  111. package/dist/server/plugin.d.ts +0 -26
  112. package/dist/server/utils/node.d.ts +0 -6
  113. package/dist/server/utils/redis.d.ts +0 -29
  114. package/dist/server/utils/versionManager.d.ts +0 -10
  115. package/dist/shared/packages.d.ts +0 -23
  116. /package/{dist/server/index.d.ts → src/client-v2/index.tsx} +0 -0
@@ -0,0 +1,154 @@
1
+ /**
2
+ * QueueScanner — discovers all registered queues in the system.
3
+ *
4
+ * Two sources:
5
+ * 1. EventQueue events (registered via app.eventQueue.subscribe)
6
+ * 2. Redis List-based queues (convention *:plugin-*:queue)
7
+ *
8
+ * Used by the Queue Assignment UI to let admins map queues to worker stacks.
9
+ */
10
+
11
+ import type { Application } from '@nocobase/server';
12
+ import { getRedisClient } from './utils/redis';
13
+
14
+ export type QueueItem = {
15
+ name: string;
16
+ label: string;
17
+ description: string;
18
+ type: 'event-queue' | 'redis-list';
19
+ pending: number | null;
20
+ };
21
+
22
+ const KNOWN_QUEUE_LABELS: Record<string, { label: string; description: string }> = {
23
+ 'workflow:process': {
24
+ label: 'Workflow',
25
+ description: 'Process workflow executions (plugin-workflow)',
26
+ },
27
+ 'async-task:process': {
28
+ label: 'Async Tasks',
29
+ description: 'Execute async tasks (plugin-async-task-manager)',
30
+ },
31
+ 'knowledge-base:document-vectorize': {
32
+ label: 'Document Vectorization',
33
+ description: 'Vectorize knowledge base documents (plugin-knowledge-base)',
34
+ },
35
+ 'git-review:process': {
36
+ label: 'Git Review',
37
+ description: 'AI code review jobs (plugin-git-manager)',
38
+ },
39
+ 'build-guide:process': {
40
+ label: 'Build Guide',
41
+ description: 'Build user guide pages (plugin-build-guide-block)',
42
+ },
43
+ 'build-ui-template:process': {
44
+ label: 'Build UI Template',
45
+ description: 'Build UI template pages (plugin-build-ui-template)',
46
+ },
47
+ };
48
+
49
+ /** Redis key patterns for List-based queues (same as event-queue-monitor.ts) */
50
+ const REDIS_QUEUE_PATTERNS = ['*:plugin-git-manager:review:queue', '*:plugin-build-guide-block:build:queue'];
51
+
52
+ function describeRedisQueueKey(key: string): { label: string; description: string } {
53
+ const parts = String(key).split(':');
54
+ const plugin = parts[parts.length - 3] || 'unknown';
55
+ const queue = parts[parts.length - 2] || key;
56
+ return {
57
+ label: `${queue} (${plugin})`,
58
+ description: `Redis List queue from ${plugin}`,
59
+ };
60
+ }
61
+
62
+ /**
63
+ * Discover all queues from EventQueue subscribers.
64
+ */
65
+ function scanEventQueue(app: Application): QueueItem[] {
66
+ const eq = (app as any).eventQueue;
67
+ if (!eq || !eq.events) return [];
68
+
69
+ const events: Map<string, { concurrency?: number; interval?: number; shared?: boolean }> = eq.events;
70
+ const items: QueueItem[] = [];
71
+
72
+ for (const [channel] of events.entries()) {
73
+ const known = KNOWN_QUEUE_LABELS[channel];
74
+ items.push({
75
+ name: channel,
76
+ label: known?.label ?? channel,
77
+ description: known?.description ?? `EventQueue channel: ${channel}`,
78
+ type: 'event-queue',
79
+ pending: null,
80
+ });
81
+ }
82
+
83
+ return items;
84
+ }
85
+
86
+ /**
87
+ * Discover Redis List-based queues via SCAN.
88
+ */
89
+ async function scanRedisQueues(app: Application): Promise<QueueItem[]> {
90
+ const redis = getRedisClient(app);
91
+ if (!redis) {
92
+ return [];
93
+ }
94
+
95
+ const seen = new Set<string>();
96
+ const items: QueueItem[] = [];
97
+
98
+ for (const pattern of REDIS_QUEUE_PATTERNS) {
99
+ try {
100
+ const keys: string[] = await redis.sendCommand(['SCAN', '0', 'MATCH', pattern, 'COUNT', '200']);
101
+ const keyList: string[] = typeof keys[1]?.length === 'number' ? keys[1] : [];
102
+
103
+ for (const key of keyList) {
104
+ if (seen.has(key)) continue;
105
+ seen.add(key);
106
+
107
+ const desc = describeRedisQueueKey(key);
108
+ let pending = 0;
109
+ try {
110
+ pending = Number(await redis.sendCommand(['LLEN', key])) || 0;
111
+ } catch {
112
+ pending = 0;
113
+ }
114
+
115
+ items.push({
116
+ name: key,
117
+ label: desc.label,
118
+ description: desc.description,
119
+ type: 'redis-list',
120
+ pending,
121
+ });
122
+ }
123
+ } catch {
124
+ // SCAN not supported or permission denied
125
+ }
126
+ }
127
+
128
+ return items;
129
+ }
130
+
131
+ /**
132
+ * Full queue scan — merges EventQueue + Redis results.
133
+ */
134
+ export async function scanQueues(app: Application): Promise<{ queues: QueueItem[]; total: number }> {
135
+ const eventQueues = scanEventQueue(app);
136
+ const redisQueues = await scanRedisQueues(app);
137
+
138
+ // Deduplicate: if a queue name appears in both sources, prefer EventQueue
139
+ const seenNames = new Set<string>();
140
+ const merged: QueueItem[] = [];
141
+
142
+ for (const q of eventQueues) {
143
+ merged.push(q);
144
+ seenNames.add(q.name);
145
+ }
146
+ for (const q of redisQueues) {
147
+ if (!seenNames.has(q.name)) {
148
+ merged.push(q);
149
+ seenNames.add(q.name);
150
+ }
151
+ }
152
+
153
+ return { queues: merged, total: merged.length };
154
+ }
@@ -1,5 +1,53 @@
1
1
  import os from 'os';
2
2
 
3
+ export type NodeRole = 'app' | 'worker' | 'sandbox';
4
+
5
+ /**
6
+ * Determine whether a WORKER_MODE value denotes a queue-processing worker
7
+ * (i.e. a node that does NOT serve HTTP), following NocoBase v2.1.x semantics:
8
+ * '' → app node (serves HTTP + every queue)
9
+ * '!' → app node (serves HTTP only)
10
+ * '*' → worker (serves all queues, no HTTP)
11
+ * 'a:b,c:d' → worker (serves the listed queue topics, no HTTP)
12
+ * '-' → transient subprocess (not a long-lived worker)
13
+ * Legacy literals 'worker' / 'task' are still tolerated for older deployments.
14
+ * A combined value containing '!' (e.g. '!,workflow:process') still serves
15
+ * HTTP, so it is treated as an app node.
16
+ */
17
+ export function isWorkerMode(workerMode?: string): boolean {
18
+ const mode = (workerMode ?? process.env.WORKER_MODE ?? '').trim();
19
+ if (!mode || mode === 'main' || mode === 'app') return false;
20
+ if (mode === '-') return false;
21
+ const topics = mode
22
+ .split(',')
23
+ .map((t) => t.trim())
24
+ .filter(Boolean);
25
+ if (topics.includes('!')) return false;
26
+ return true;
27
+ }
28
+
29
+ /**
30
+ * Resolve a node role from its descriptor. APP_ROLE (explicit) wins, then an
31
+ * explicit sandbox flag, then WORKER_MODE parsing. Works for both the local
32
+ * process (pass process.env values) and remote node records read from Redis.
33
+ */
34
+ export function getNodeRoleFrom(opts: { workerMode?: string; appRole?: string; isSandbox?: boolean }): NodeRole {
35
+ if (opts.appRole === 'app' || opts.appRole === 'worker' || opts.appRole === 'sandbox') {
36
+ return opts.appRole;
37
+ }
38
+ if (opts.isSandbox) return 'sandbox';
39
+ return isWorkerMode(opts.workerMode) ? 'worker' : 'app';
40
+ }
41
+
42
+ /** Resolve the role of the current Node.js process from its environment. */
43
+ export function getLocalRole(): NodeRole {
44
+ return getNodeRoleFrom({
45
+ workerMode: process.env.WORKER_MODE,
46
+ appRole: process.env.APP_ROLE,
47
+ isSandbox: process.env.SKILL_HUB_SANDBOX === 'true',
48
+ });
49
+ }
50
+
3
51
  /**
4
52
  * Generate a universally unique identifier for this specific Node.js process.
5
53
  * Combines app name, worker mode, hostname, port, and PID to ensure uniqueness
@@ -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 Doctor(): 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 function NginxCacheManager(): 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 PluginOperations(): React.JSX.Element;
@@ -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,3 +0,0 @@
1
- import { APIClient } from '@nocobase/client';
2
- export declare function clearClientCache(): void;
3
- export declare function setupClientSafeCache(apiClient: APIClient): void;
@@ -1,2 +0,0 @@
1
- import { APIClient } from '@nocobase/client';
2
- export declare function setupRequestDedupAndCache(apiClient: APIClient): void;
@@ -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,33 +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
- /**
24
- * GET /clusterManagerCacheMgr:nginxCacheStatus
25
- * Detect if Nginx is installed, locate conf, and auto-load cache paths
26
- */
27
- nginxCacheStatus(ctx: Context, next: () => Promise<void>): Promise<void>;
28
- /**
29
- * POST /clusterManagerCacheMgr:clearNginxCache
30
- * Clear physical cache files or send an HTTP Purge request
31
- */
32
- clearNginxCache(ctx: Context, next: () => Promise<void>): Promise<void>;
33
- };
@@ -1,64 +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:drift
29
- * Reports version/runtime/package drift across active cluster nodes.
30
- */
31
- drift(ctx: Context, next: () => Promise<void>): Promise<void>;
32
- /**
33
- * GET /clusterManagerCluster:legacyDiagnostics
34
- * Detects deprecated legacy multi-app plugins and leftover application records.
35
- */
36
- legacyDiagnostics(ctx: Context, next: () => Promise<void>): Promise<void>;
37
- /**
38
- * GET /clusterManagerCluster:health
39
- * Health check for all subsystems
40
- */
41
- health(ctx: Context, next: () => Promise<void>): Promise<void>;
42
- /**
43
- * POST /clusterManagerCluster:restart
44
- * Publishes a restart signal to target nodes orchestrating a soft NocoBase restart or a hard docker daemon rebirth
45
- */
46
- restart(ctx: Context, next: () => Promise<void>): Promise<void>;
47
- /**
48
- * POST /clusterManagerCluster:rollingRestart
49
- * Restarts online nodes one-by-one, optionally filtered by role.
50
- */
51
- rollingRestart(ctx: Context, next: () => Promise<void>): Promise<void>;
52
- /**
53
- * GET /clusterManagerCluster:logs?targetNodeId=xxx&lines=200
54
- *
55
- * HA-aware log viewer. Reads logs from a specific node in the cluster.
56
- *
57
- * Flow:
58
- * 1. If targetNodeId matches current node (or is empty) → read local FS directly
59
- * 2. Otherwise → publish a log request via PubSub → target node reads its local FS
60
- * and writes the result to a Redis key → this handler polls Redis until the
61
- * response arrives (max 10s) → returns it to the client
62
- */
63
- logs(ctx: Context, next: () => Promise<void>): Promise<void>;
64
- };
@@ -1,82 +0,0 @@
1
- /// <reference types="node" />
2
- import { Context } from '@nocobase/actions';
3
- import Application from '@nocobase/server';
4
- interface DiagnosticLogLine {
5
- source: string;
6
- line: string;
7
- timestamp?: string;
8
- level?: string;
9
- message?: string;
10
- stack?: string;
11
- }
12
- interface LogSignature {
13
- signature: string;
14
- level: string;
15
- count: number;
16
- firstSeen?: string;
17
- lastSeen?: string;
18
- sources: string[];
19
- samples: string[];
20
- }
21
- interface LogAnalysis {
22
- totalLines: number;
23
- levels: Record<string, number>;
24
- signatures: LogSignature[];
25
- }
26
- interface PluginSnapshot {
27
- name?: string;
28
- packageName?: string;
29
- enabled?: boolean;
30
- dbVersion?: string;
31
- loaded: boolean;
32
- runtimeVersion?: string;
33
- }
34
- interface DoctorNodeSnapshot {
35
- nodeId: string;
36
- node: {
37
- hostname: string;
38
- pid: number;
39
- workerMode: string;
40
- role: string;
41
- appVersion: string;
42
- nodeVersion: string;
43
- platform: string;
44
- arch: string;
45
- uptime: number;
46
- isSandbox: boolean;
47
- };
48
- memory: NodeJS.MemoryUsage;
49
- os: {
50
- totalMemory: number;
51
- freeMemory: number;
52
- cpuCount: number;
53
- loadAvg: number[];
54
- };
55
- env: Record<string, string | undefined>;
56
- plugins: PluginSnapshot[];
57
- logs: {
58
- files: Array<{
59
- file: string;
60
- lineCount: number;
61
- }>;
62
- lines: DiagnosticLogLine[];
63
- analysis: LogAnalysis;
64
- };
65
- collectedAt: string;
66
- error?: string;
67
- }
68
- interface DoctorSnapshotOptions {
69
- runId?: string;
70
- sinceMs?: number;
71
- untilMs?: number;
72
- maxLines?: number;
73
- }
74
- export declare function collectLocalDoctorSnapshot(app: Application, options?: DoctorSnapshotOptions): Promise<DoctorNodeSnapshot>;
75
- export declare const doctorActions: {
76
- start(ctx: Context, next: () => Promise<void>): Promise<void>;
77
- stop(ctx: Context, next: () => Promise<void>): Promise<void>;
78
- status(ctx: Context, next: () => Promise<void>): Promise<void>;
79
- report(ctx: Context, next: () => Promise<void>): Promise<void>;
80
- download(ctx: Context, next: () => Promise<void>): Promise<void>;
81
- };
82
- export {};
@@ -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,58 +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
- /**
54
- * GET /workerOrchestrator:networks
55
- * List available networks (if supported by adapter)
56
- */
57
- networks(ctx: Context, next: () => Promise<void>): Promise<void>;
58
- };
@@ -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,6 +0,0 @@
1
- import { Context } from '@nocobase/actions';
2
- export declare const pluginOperationsActions: {
3
- list(ctx: Context, next: () => Promise<void>): Promise<void>;
4
- forceDisable(ctx: Context, next: () => Promise<void>): Promise<void>;
5
- forceRemove(ctx: Context, 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
- };