comfyui-node 1.6.0 → 1.6.2
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/dist/.tsbuildinfo +1 -1
- package/dist/call-wrapper.js +856 -856
- package/dist/index.d.ts +13 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/dist/multipool/client-registry.d.ts +33 -0
- package/dist/multipool/client-registry.d.ts.map +1 -0
- package/dist/multipool/client-registry.js +153 -0
- package/dist/multipool/client-registry.js.map +1 -0
- package/dist/multipool/helpers.d.ts +5 -0
- package/dist/multipool/helpers.d.ts.map +1 -0
- package/dist/multipool/helpers.js +53 -0
- package/dist/multipool/helpers.js.map +1 -0
- package/dist/multipool/index.d.ts +3 -0
- package/dist/multipool/index.d.ts.map +1 -0
- package/dist/multipool/index.js +3 -0
- package/dist/multipool/index.js.map +1 -0
- package/dist/multipool/interfaces.d.ts +13 -0
- package/dist/multipool/interfaces.d.ts.map +1 -0
- package/dist/multipool/interfaces.js +2 -0
- package/dist/multipool/interfaces.js.map +1 -0
- package/dist/multipool/job-profiler.d.ts +128 -0
- package/dist/multipool/job-profiler.d.ts.map +1 -0
- package/dist/multipool/job-profiler.js +222 -0
- package/dist/multipool/job-profiler.js.map +1 -0
- package/dist/multipool/job-queue-processor.d.ts +28 -0
- package/dist/multipool/job-queue-processor.d.ts.map +1 -0
- package/dist/multipool/job-queue-processor.js +197 -0
- package/dist/multipool/job-queue-processor.js.map +1 -0
- package/dist/multipool/job-state-registry.d.ts +67 -0
- package/dist/multipool/job-state-registry.d.ts.map +1 -0
- package/dist/multipool/job-state-registry.js +283 -0
- package/dist/multipool/job-state-registry.js.map +1 -0
- package/dist/multipool/logger.d.ts +30 -0
- package/dist/multipool/logger.d.ts.map +1 -0
- package/dist/multipool/logger.js +75 -0
- package/dist/multipool/logger.js.map +1 -0
- package/dist/multipool/multi-workflow-pool.d.ts +43 -0
- package/dist/multipool/multi-workflow-pool.d.ts.map +1 -0
- package/dist/multipool/multi-workflow-pool.js +314 -0
- package/dist/multipool/multi-workflow-pool.js.map +1 -0
- package/dist/multipool/pool-event-manager.d.ts +11 -0
- package/dist/multipool/pool-event-manager.d.ts.map +1 -0
- package/dist/multipool/pool-event-manager.js +28 -0
- package/dist/multipool/pool-event-manager.js.map +1 -0
- package/dist/multipool/tests/error-classification-tests.d.ts +2 -0
- package/dist/multipool/tests/error-classification-tests.d.ts.map +1 -0
- package/dist/multipool/tests/error-classification-tests.js +374 -0
- package/dist/multipool/tests/error-classification-tests.js.map +1 -0
- package/dist/multipool/tests/job-state-registry.d.ts +17 -0
- package/dist/multipool/tests/job-state-registry.d.ts.map +1 -0
- package/dist/multipool/tests/job-state-registry.js +24 -0
- package/dist/multipool/tests/job-state-registry.js.map +1 -0
- package/dist/multipool/tests/multipool-basic.d.ts +12 -0
- package/dist/multipool/tests/multipool-basic.d.ts.map +1 -0
- package/dist/multipool/tests/multipool-basic.js +142 -0
- package/dist/multipool/tests/multipool-basic.js.map +1 -0
- package/dist/multipool/tests/profiling-demo.d.ts +7 -0
- package/dist/multipool/tests/profiling-demo.d.ts.map +1 -0
- package/dist/multipool/tests/profiling-demo.js +88 -0
- package/dist/multipool/tests/profiling-demo.js.map +1 -0
- package/dist/multipool/tests/prompt-generator.d.ts +10 -0
- package/dist/multipool/tests/prompt-generator.d.ts.map +1 -0
- package/dist/multipool/tests/prompt-generator.js +26 -0
- package/dist/multipool/tests/prompt-generator.js.map +1 -0
- package/dist/multipool/tests/test-helpers.d.ts +4 -0
- package/dist/multipool/tests/test-helpers.d.ts.map +1 -0
- package/dist/multipool/tests/test-helpers.js +10 -0
- package/dist/multipool/tests/test-helpers.js.map +1 -0
- package/dist/multipool/tests/two-stage-edit-simulation.d.ts +32 -0
- package/dist/multipool/tests/two-stage-edit-simulation.d.ts.map +1 -0
- package/dist/multipool/tests/two-stage-edit-simulation.js +299 -0
- package/dist/multipool/tests/two-stage-edit-simulation.js.map +1 -0
- package/dist/multipool/workflow.d.ts +179 -0
- package/dist/multipool/workflow.d.ts.map +1 -0
- package/dist/multipool/workflow.js +334 -0
- package/dist/multipool/workflow.js.map +1 -0
- package/dist/pool/SmartPool.d.ts +143 -143
- package/dist/pool/SmartPool.d.ts.map +1 -1
- package/dist/pool/SmartPool.js +676 -676
- package/dist/pool/SmartPool.js.map +1 -1
- package/dist/pool/SmartPoolV2.d.ts +119 -119
- package/dist/pool/SmartPoolV2.js +586 -586
- package/dist/pool/WorkflowPool.d.ts +202 -202
- package/dist/pool/WorkflowPool.d.ts.map +1 -1
- package/dist/pool/WorkflowPool.js +845 -840
- package/dist/pool/WorkflowPool.js.map +1 -1
- package/dist/pool/client/ClientManager.d.ts +86 -86
- package/dist/pool/client/ClientManager.js +215 -215
- package/dist/pool/index.d.ts +9 -11
- package/dist/pool/index.d.ts.map +1 -1
- package/dist/pool/index.js +3 -5
- package/dist/pool/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
export { ComfyApi } from "./client.js";
|
|
2
|
-
export { CallWrapper } from "./call-wrapper.js";
|
|
3
|
-
export { ComfyPool, EQueueMode } from "./pool.js";
|
|
4
|
-
export { WorkflowPool,
|
|
5
|
-
export { PromptBuilder } from "./prompt-builder.js";
|
|
6
|
-
export { Workflow, WorkflowJob } from "./workflow.js";
|
|
7
|
-
export type { AugmentNodes, SamplerName, SchedulerName } from "./node-type-hints.js";
|
|
8
|
-
export type { WorkflowResult, WorkflowResultMeta } from "./workflow.js";
|
|
9
|
-
export type { WorkflowAffinity } from "./pool/types/affinity.js";
|
|
10
|
-
export type { TSamplerName, TSchedulerName } from "./types/sampler.js";
|
|
11
|
-
export type { TComfyAPIEventMap, TComfyPoolEventMap, ComfyApiEventKey, ComfyPoolEventKey } from "./types/event.js";
|
|
12
|
-
export type { WorkflowPoolEventMap, WorkflowPoolOpts, JobRecord, JobStatus, WorkflowJobOptions, QueueAdapter, QueueReservation, QueueStats, FailoverStrategy, JobProfileStats, NodeExecutionProfile } from "./pool/index.js";
|
|
13
|
-
export { seed } from "./tools.js";
|
|
1
|
+
export { ComfyApi } from "./client.js";
|
|
2
|
+
export { CallWrapper } from "./call-wrapper.js";
|
|
3
|
+
export { ComfyPool, EQueueMode } from "./pool.js";
|
|
4
|
+
export { WorkflowPool, MemoryQueueAdapter, SmartFailoverStrategy } from "./pool/index.js";
|
|
5
|
+
export { PromptBuilder } from "./prompt-builder.js";
|
|
6
|
+
export { Workflow, WorkflowJob } from "./workflow.js";
|
|
7
|
+
export type { AugmentNodes, SamplerName, SchedulerName } from "./node-type-hints.js";
|
|
8
|
+
export type { WorkflowResult, WorkflowResultMeta } from "./workflow.js";
|
|
9
|
+
export type { WorkflowAffinity } from "./pool/types/affinity.js";
|
|
10
|
+
export type { TSamplerName, TSchedulerName } from "./types/sampler.js";
|
|
11
|
+
export type { TComfyAPIEventMap, TComfyPoolEventMap, ComfyApiEventKey, ComfyPoolEventKey } from "./types/event.js";
|
|
12
|
+
export type { WorkflowPoolEventMap, WorkflowPoolOpts, JobRecord, JobStatus, WorkflowJobOptions, QueueAdapter, QueueReservation, QueueStats, FailoverStrategy, JobProfileStats, NodeExecutionProfile } from "./pool/index.js";
|
|
13
|
+
export { seed } from "./tools.js";
|
|
14
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrF,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxE,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACvE,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACnH,YAAY,EACV,oBAAoB,EACpB,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { ComfyApi } from "./client.js";
|
|
2
|
-
export { CallWrapper } from "./call-wrapper.js";
|
|
3
|
-
export { ComfyPool, EQueueMode } from "./pool.js";
|
|
4
|
-
export { WorkflowPool,
|
|
5
|
-
export { PromptBuilder } from "./prompt-builder.js";
|
|
6
|
-
export { Workflow, WorkflowJob } from "./workflow.js";
|
|
7
|
-
export { seed } from "./tools.js";
|
|
1
|
+
export { ComfyApi } from "./client.js";
|
|
2
|
+
export { CallWrapper } from "./call-wrapper.js";
|
|
3
|
+
export { ComfyPool, EQueueMode } from "./pool.js";
|
|
4
|
+
export { WorkflowPool, MemoryQueueAdapter, SmartFailoverStrategy } from "./pool/index.js";
|
|
5
|
+
export { PromptBuilder } from "./prompt-builder.js";
|
|
6
|
+
export { Workflow, WorkflowJob } from "./workflow.js";
|
|
7
|
+
export { seed } from "./tools.js";
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAoBtD,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { MultiWorkflowPool } from "src/multipool/multi-workflow-pool.js";
|
|
2
|
+
import { ComfyApi } from "src/client.js";
|
|
3
|
+
import { Workflow } from "./workflow.js";
|
|
4
|
+
import { Logger } from "./logger.js";
|
|
5
|
+
export type ClientState = "idle" | "busy" | "offline";
|
|
6
|
+
export interface EnhancedClient {
|
|
7
|
+
url: string;
|
|
8
|
+
state: ClientState;
|
|
9
|
+
nodeName: string;
|
|
10
|
+
priority?: number;
|
|
11
|
+
api: ComfyApi;
|
|
12
|
+
workflowAffinity?: Set<string>;
|
|
13
|
+
}
|
|
14
|
+
export declare class ClientRegistry {
|
|
15
|
+
pool: MultiWorkflowPool;
|
|
16
|
+
private logger;
|
|
17
|
+
clients: Map<string, EnhancedClient>;
|
|
18
|
+
workflowAffinityMap: Map<string, Set<string>>;
|
|
19
|
+
constructor(pool: MultiWorkflowPool, logger: Logger);
|
|
20
|
+
addClient(clientUrl: string, options?: {
|
|
21
|
+
workflowAffinity: Workflow[];
|
|
22
|
+
priority?: number;
|
|
23
|
+
}): void;
|
|
24
|
+
removeClient(clientUrl: string): void;
|
|
25
|
+
getQueueStatus(clientUrl: string): Promise<import("../types/api.js").QueueResponse>;
|
|
26
|
+
getOptimalClient(workflow: Workflow): EnhancedClient | null;
|
|
27
|
+
hasClientsForWorkflow(workflowHash: string): boolean;
|
|
28
|
+
getOptimalIdleClient(workflow: Workflow): Promise<EnhancedClient | null>;
|
|
29
|
+
private checkClientQueueState;
|
|
30
|
+
markClientIncompatibleWithWorkflow(url: string, structureHash: string | undefined): void;
|
|
31
|
+
getAllEligibleClientsForWorkflow(workflow: Workflow): EnhancedClient[];
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=client-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-registry.d.ts","sourceRoot":"","sources":["../../src/multipool/client-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAEtD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,QAAQ,CAAC;IACd,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,qBAAa,cAAc;IAEzB,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAa;IAGjD,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAa;gBAE9C,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM;IAKnD,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,gBAAgB,EAAE,QAAQ,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;IA8B1F,YAAY,CAAC,SAAS,EAAE,MAAM;IAIxB,cAAc,CAAC,SAAS,EAAE,MAAM;IAQtC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ;IAsCnC,qBAAqB,CAAC,YAAY,EAAE,MAAM;IAMpC,oBAAoB,CAAC,QAAQ,EAAE,QAAQ;YA6B/B,qBAAqB;IAcnC,kCAAkC,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,SAAS;IAcjF,gCAAgC,CAAC,QAAQ,EAAE,QAAQ;CAapD"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { ComfyApi } from "src/client.js";
|
|
2
|
+
export class ClientRegistry {
|
|
3
|
+
pool;
|
|
4
|
+
logger;
|
|
5
|
+
clients = new Map();
|
|
6
|
+
// Maps a workflow structure hash to a set of client URLs that have affinity for that workflow
|
|
7
|
+
workflowAffinityMap = new Map();
|
|
8
|
+
constructor(pool, logger) {
|
|
9
|
+
this.pool = pool;
|
|
10
|
+
this.logger = logger;
|
|
11
|
+
}
|
|
12
|
+
addClient(clientUrl, options) {
|
|
13
|
+
const comfyApi = new ComfyApi(clientUrl);
|
|
14
|
+
const enhancedClient = {
|
|
15
|
+
url: clientUrl,
|
|
16
|
+
state: "idle",
|
|
17
|
+
nodeName: new URL(clientUrl).hostname,
|
|
18
|
+
priority: options?.priority,
|
|
19
|
+
api: comfyApi
|
|
20
|
+
};
|
|
21
|
+
if (options?.workflowAffinity) {
|
|
22
|
+
enhancedClient.workflowAffinity = new Set();
|
|
23
|
+
for (const workflow of options.workflowAffinity) {
|
|
24
|
+
let hash = workflow.structureHash;
|
|
25
|
+
if (!hash) {
|
|
26
|
+
workflow.updateHash();
|
|
27
|
+
hash = workflow.structureHash;
|
|
28
|
+
}
|
|
29
|
+
if (!hash) {
|
|
30
|
+
throw new Error("Workflow must have a valid structure hash for affinity.");
|
|
31
|
+
}
|
|
32
|
+
if (!this.workflowAffinityMap.has(hash)) {
|
|
33
|
+
this.workflowAffinityMap.set(hash, new Set());
|
|
34
|
+
}
|
|
35
|
+
this.workflowAffinityMap.get(hash).add(clientUrl);
|
|
36
|
+
enhancedClient.workflowAffinity.add(hash);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
this.clients.set(clientUrl, enhancedClient);
|
|
40
|
+
}
|
|
41
|
+
removeClient(clientUrl) {
|
|
42
|
+
this.clients.delete(clientUrl);
|
|
43
|
+
}
|
|
44
|
+
async getQueueStatus(clientUrl) {
|
|
45
|
+
const comfyApi = this.clients.get(clientUrl)?.api;
|
|
46
|
+
if (!comfyApi) {
|
|
47
|
+
throw new Error(`Client ${clientUrl} not found`);
|
|
48
|
+
}
|
|
49
|
+
return comfyApi.getQueue();
|
|
50
|
+
}
|
|
51
|
+
getOptimalClient(workflow) {
|
|
52
|
+
let workflowHash = workflow.structureHash;
|
|
53
|
+
if (!workflowHash) {
|
|
54
|
+
workflow.updateHash();
|
|
55
|
+
workflowHash = workflow.structureHash;
|
|
56
|
+
}
|
|
57
|
+
if (!workflowHash) {
|
|
58
|
+
throw new Error("Workflow must have a valid structure hash.");
|
|
59
|
+
}
|
|
60
|
+
// Filter clients based on workflow affinity
|
|
61
|
+
const suitableClients = [];
|
|
62
|
+
for (const client of this.clients.values()) {
|
|
63
|
+
if (client.state !== "idle") {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (client.workflowAffinity && client.workflowAffinity.has(workflowHash)) {
|
|
67
|
+
suitableClients.push(client);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (suitableClients.length === 0) {
|
|
71
|
+
this.logger.debug(`No suitable clients found for workflow ${workflowHash}.`);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
this.logger.debug(`Suitable clients for workflow ${workflowHash}: ${suitableClients.map(value => value.nodeName).join(",")}`);
|
|
75
|
+
// sort suitable clients by priority
|
|
76
|
+
suitableClients.sort((a, b) => {
|
|
77
|
+
const priorityA = a.priority ?? 0;
|
|
78
|
+
const priorityB = b.priority ?? 0;
|
|
79
|
+
return priorityB - priorityA; // higher priority first
|
|
80
|
+
});
|
|
81
|
+
return suitableClients.length > 0 ? suitableClients[0] : null;
|
|
82
|
+
}
|
|
83
|
+
hasClientsForWorkflow(workflowHash) {
|
|
84
|
+
const clientSet = this.workflowAffinityMap.get(workflowHash);
|
|
85
|
+
return clientSet !== undefined && clientSet.size > 0;
|
|
86
|
+
}
|
|
87
|
+
// Get an optimal idle client for a given workflow (used for general queue)
|
|
88
|
+
async getOptimalIdleClient(workflow) {
|
|
89
|
+
this.logger.debug(`Searching for idle clients for workflow ${workflow.structureHash}...`);
|
|
90
|
+
// We can infer model capabilities from workflow and try to get the best idle client, based on other workflow affinities, for now lets pick any idle client
|
|
91
|
+
const idleClients = [];
|
|
92
|
+
for (const client of this.clients.values()) {
|
|
93
|
+
if (client.state === "idle") {
|
|
94
|
+
// For the general queue, we need to check the actual queue state
|
|
95
|
+
await this.checkClientQueueState(client);
|
|
96
|
+
if (client.state === "idle") {
|
|
97
|
+
this.logger.debug(`Client ${client.nodeName} is idle.`);
|
|
98
|
+
idleClients.push(client);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
this.logger.debug(`Idle clients available: ${idleClients.map(value => value.nodeName).join(",")}`);
|
|
103
|
+
// sort idle clients by priority
|
|
104
|
+
idleClients.sort((a, b) => {
|
|
105
|
+
const priorityA = a.priority ?? 0;
|
|
106
|
+
const priorityB = b.priority ?? 0;
|
|
107
|
+
return priorityB - priorityA; // higher priority first
|
|
108
|
+
});
|
|
109
|
+
return idleClients.length > 0 ? idleClients[0] : null;
|
|
110
|
+
}
|
|
111
|
+
async checkClientQueueState(client) {
|
|
112
|
+
try {
|
|
113
|
+
const queue = await this.getQueueStatus(client.url);
|
|
114
|
+
if (queue.queue_running.length > 0 || queue.queue_pending.length > 0) {
|
|
115
|
+
client.state = "busy";
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
client.state = "idle";
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
this.logger.error(`Error checking queue state for client ${client.nodeName}:`, error);
|
|
123
|
+
client.state = "offline";
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
markClientIncompatibleWithWorkflow(url, structureHash) {
|
|
127
|
+
const client = this.clients.get(url);
|
|
128
|
+
if (client && structureHash && client.workflowAffinity) {
|
|
129
|
+
client.workflowAffinity.delete(structureHash);
|
|
130
|
+
const affinitySet = this.workflowAffinityMap.get(structureHash);
|
|
131
|
+
if (affinitySet) {
|
|
132
|
+
affinitySet.delete(url);
|
|
133
|
+
if (affinitySet.size === 0) {
|
|
134
|
+
this.workflowAffinityMap.delete(structureHash);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
getAllEligibleClientsForWorkflow(workflow) {
|
|
140
|
+
const eligibleClients = [];
|
|
141
|
+
const workflowHash = workflow.structureHash;
|
|
142
|
+
if (!workflowHash) {
|
|
143
|
+
throw new Error("Workflow must have a valid structure hash.");
|
|
144
|
+
}
|
|
145
|
+
for (const client of this.clients.values()) {
|
|
146
|
+
if (client.workflowAffinity && client.workflowAffinity.has(workflowHash)) {
|
|
147
|
+
eligibleClients.push(client);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return eligibleClients;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=client-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-registry.js","sourceRoot":"","sources":["../../src/multipool/client-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/multipool/helpers.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,KAAK,EAAE,GAAG,GAAG;IAAE,IAAI,EAAE,YAAY,GAAG,0BAA0B,GAAG,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAyD9H"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export function classifyFailure(error) {
|
|
2
|
+
const responseData = error?.bodyJSON || error?.response?.data;
|
|
3
|
+
// Case 1: Connection Failure (no response from server)
|
|
4
|
+
if (!responseData) {
|
|
5
|
+
return { type: 'connection', message: error.message || 'Connection failed' };
|
|
6
|
+
}
|
|
7
|
+
// Case 2: Workflow Incompatibility (specific errors from ComfyUI)
|
|
8
|
+
if (responseData.node_errors && Object.keys(responseData.node_errors).length > 0) {
|
|
9
|
+
for (const nodeError of Object.values(responseData.node_errors)) {
|
|
10
|
+
for (const err of nodeError.errors) {
|
|
11
|
+
// Missing custom nodes
|
|
12
|
+
if (err.type.includes("FileNotFoundError") || err.details?.includes("cannot be found")) {
|
|
13
|
+
return { type: 'workflow_incompatibility', message: `Missing file or model: ${err.details}` };
|
|
14
|
+
}
|
|
15
|
+
// Missing model files (checkpoints, LoRAs, etc.) - also covers other value_not_in_list that reference files
|
|
16
|
+
if (err.type === "value_not_in_list") {
|
|
17
|
+
const details = err.details || "";
|
|
18
|
+
// Check for common model/file input names
|
|
19
|
+
if (details.includes("ckpt_name") || details.includes("lora_name") ||
|
|
20
|
+
details.includes("model_name") || details.includes("vae_name") ||
|
|
21
|
+
details.includes("embedding_name") || details.includes("controlnet") ||
|
|
22
|
+
details.includes(".safetensors") || details.includes(".ckpt") ||
|
|
23
|
+
details.includes(".pt") || details.includes(".pth")) {
|
|
24
|
+
return { type: 'workflow_incompatibility', message: `Missing model file: ${details}` };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// Errors during model loading
|
|
28
|
+
if (err.message && (err.message.includes("KeyError: '") || err.message.includes("safetensors_load"))) {
|
|
29
|
+
return { type: 'workflow_incompatibility', message: `Failed to load model: ${err.message}` };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Check for missing custom nodes (invalid_prompt type)
|
|
35
|
+
if (responseData.error?.type === "invalid_prompt" &&
|
|
36
|
+
responseData.error?.message?.includes("does not exist")) {
|
|
37
|
+
return { type: 'workflow_incompatibility', message: responseData.error.message };
|
|
38
|
+
}
|
|
39
|
+
// Check for python exception for missing nodes
|
|
40
|
+
if (responseData.exception_message && responseData.exception_message.includes("Node type not found")) {
|
|
41
|
+
return { type: 'workflow_incompatibility', message: responseData.exception_message };
|
|
42
|
+
}
|
|
43
|
+
// Case 3: Transient Failure (OOM, invalid inputs, etc.)
|
|
44
|
+
if (responseData.exception_message) {
|
|
45
|
+
if (responseData.exception_message.includes("out of memory")) {
|
|
46
|
+
return { type: 'transient', message: 'CUDA out of memory' };
|
|
47
|
+
}
|
|
48
|
+
return { type: 'transient', message: responseData.exception_message };
|
|
49
|
+
}
|
|
50
|
+
// Default to transient for other server-side errors
|
|
51
|
+
return { type: 'transient', message: JSON.stringify(responseData) };
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/multipool/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/multipool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/multipool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { LogLevel } from "./logger.js";
|
|
2
|
+
export interface PoolEvent {
|
|
3
|
+
type: string;
|
|
4
|
+
payload: any;
|
|
5
|
+
}
|
|
6
|
+
export interface MultiWorkflowPoolOptions {
|
|
7
|
+
connectionTimeoutMs?: number;
|
|
8
|
+
enableMonitoring?: boolean;
|
|
9
|
+
monitoringIntervalMs?: number;
|
|
10
|
+
logLevel?: LogLevel;
|
|
11
|
+
enableProfiling?: boolean;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=interfaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/multipool/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,GAAG,CAAC;CACd;AAED,MAAM,WAAW,wBAAwB;IACvC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/multipool/interfaces.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Job Profiler for MultiWorkflowPool - Automatic per-node execution profiling
|
|
3
|
+
* ===========================================================================
|
|
4
|
+
*
|
|
5
|
+
* Captures detailed execution metrics for workflow jobs automatically:
|
|
6
|
+
* - Per-node execution timing
|
|
7
|
+
* - Progress tracking for nodes that emit progress events
|
|
8
|
+
* - Execution order and dependencies
|
|
9
|
+
* - Node types and metadata
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* ```ts
|
|
13
|
+
* const pool = new MultiWorkflowPool({ enableProfiling: true });
|
|
14
|
+
* const jobId = await pool.submitJob(workflow);
|
|
15
|
+
*
|
|
16
|
+
* const results = await pool.waitForJobCompletion(jobId);
|
|
17
|
+
* console.log(results.profileStats);
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export interface NodeExecutionProfile {
|
|
21
|
+
/** Node ID */
|
|
22
|
+
nodeId: string;
|
|
23
|
+
/** Node class type (e.g., KSampler, VAELoader) */
|
|
24
|
+
type?: string;
|
|
25
|
+
/** Node title/label */
|
|
26
|
+
title?: string;
|
|
27
|
+
/** Timestamp when node started executing (ms since epoch) */
|
|
28
|
+
startedAt?: number;
|
|
29
|
+
/** Timestamp when node completed (ms since epoch) */
|
|
30
|
+
completedAt?: number;
|
|
31
|
+
/** Execution duration in milliseconds */
|
|
32
|
+
duration?: number;
|
|
33
|
+
/** Progress events captured for this node */
|
|
34
|
+
progressEvents?: Array<{
|
|
35
|
+
timestamp: number;
|
|
36
|
+
value: number;
|
|
37
|
+
max: number;
|
|
38
|
+
}>;
|
|
39
|
+
/** Whether this node was cached (instant execution) */
|
|
40
|
+
cached: boolean;
|
|
41
|
+
/** Execution status */
|
|
42
|
+
status: 'pending' | 'executing' | 'completed' | 'cached' | 'failed';
|
|
43
|
+
/** Error message if failed */
|
|
44
|
+
error?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface JobProfileStats {
|
|
47
|
+
/** Prompt ID from ComfyUI */
|
|
48
|
+
promptId?: string;
|
|
49
|
+
/** Total execution time from queue to completion (ms) */
|
|
50
|
+
totalDuration: number;
|
|
51
|
+
/** Time spent in queue before execution started (ms) */
|
|
52
|
+
queueTime: number;
|
|
53
|
+
/** Actual execution time (ms) */
|
|
54
|
+
executionTime: number;
|
|
55
|
+
/** Timestamp when job was queued */
|
|
56
|
+
queuedAt: number;
|
|
57
|
+
/** Timestamp when execution started */
|
|
58
|
+
startedAt?: number;
|
|
59
|
+
/** Timestamp when execution completed */
|
|
60
|
+
completedAt: number;
|
|
61
|
+
/** Per-node execution profiles */
|
|
62
|
+
nodes: NodeExecutionProfile[];
|
|
63
|
+
/** Execution timeline summary */
|
|
64
|
+
summary: {
|
|
65
|
+
/** Total number of nodes in workflow */
|
|
66
|
+
totalNodes: number;
|
|
67
|
+
/** Number of nodes actually executed */
|
|
68
|
+
executedNodes: number;
|
|
69
|
+
/** Number of cached nodes */
|
|
70
|
+
cachedNodes: number;
|
|
71
|
+
/** Number of failed nodes */
|
|
72
|
+
failedNodes: number;
|
|
73
|
+
/** Slowest nodes (top 5) */
|
|
74
|
+
slowestNodes: Array<{
|
|
75
|
+
nodeId: string;
|
|
76
|
+
type?: string;
|
|
77
|
+
title?: string;
|
|
78
|
+
duration: number;
|
|
79
|
+
}>;
|
|
80
|
+
/** Nodes that emitted progress events */
|
|
81
|
+
progressNodes: string[];
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* JobProfiler tracks execution metrics for a single workflow job.
|
|
86
|
+
*/
|
|
87
|
+
export declare class JobProfiler {
|
|
88
|
+
private queuedAt;
|
|
89
|
+
private startedAt?;
|
|
90
|
+
private completedAt?;
|
|
91
|
+
private promptId?;
|
|
92
|
+
private nodeProfiles;
|
|
93
|
+
private lastExecutingNode;
|
|
94
|
+
constructor(queuedAt: number, workflowJson?: Record<string, any>);
|
|
95
|
+
/**
|
|
96
|
+
* Record execution start event
|
|
97
|
+
*/
|
|
98
|
+
onExecutionStart(promptId: string): void;
|
|
99
|
+
/**
|
|
100
|
+
* Record cached nodes
|
|
101
|
+
*/
|
|
102
|
+
onCachedNodes(nodeIds: string[]): void;
|
|
103
|
+
/**
|
|
104
|
+
* Record node execution start
|
|
105
|
+
*/
|
|
106
|
+
onNodeExecuting(nodeId: string): void;
|
|
107
|
+
/**
|
|
108
|
+
* Record node completion (when next node starts or execution ends)
|
|
109
|
+
*/
|
|
110
|
+
private completeNode;
|
|
111
|
+
/**
|
|
112
|
+
* Record execution end (node: null event)
|
|
113
|
+
*/
|
|
114
|
+
onExecutionComplete(): void;
|
|
115
|
+
/**
|
|
116
|
+
* Record progress event for a node
|
|
117
|
+
*/
|
|
118
|
+
onProgress(nodeId: string | number, value: number, max: number): void;
|
|
119
|
+
/**
|
|
120
|
+
* Record node execution error
|
|
121
|
+
*/
|
|
122
|
+
onNodeError(nodeId: string, error: string): void;
|
|
123
|
+
/**
|
|
124
|
+
* Generate final profile statistics
|
|
125
|
+
*/
|
|
126
|
+
getStats(): JobProfileStats;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=job-profiler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job-profiler.d.ts","sourceRoot":"","sources":["../../src/multipool/job-profiler.ts"],"names":[],"mappings":"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"}
|