@donkeylabs/server 2.0.31 → 2.0.33
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/docs/workflows.md +4 -1
- package/package.json +1 -1
- package/src/core/workflows.ts +19 -4
package/docs/workflows.md
CHANGED
|
@@ -97,9 +97,12 @@ Limit concurrent instances per workflow name:
|
|
|
97
97
|
const server = new AppServer({
|
|
98
98
|
db,
|
|
99
99
|
workflows: {
|
|
100
|
-
concurrentWorkflows: 1, // 0 = unlimited
|
|
100
|
+
concurrentWorkflows: 1, // default for all workflows (0 = unlimited)
|
|
101
101
|
},
|
|
102
102
|
});
|
|
103
|
+
|
|
104
|
+
// Per-register override
|
|
105
|
+
ctx.core.workflows.register(orderWorkflow, { maxConcurrent: 1 });
|
|
103
106
|
```
|
|
104
107
|
|
|
105
108
|
### 3. Track Progress
|
package/package.json
CHANGED
package/src/core/workflows.ts
CHANGED
|
@@ -766,7 +766,7 @@ export interface WorkflowsConfig {
|
|
|
766
766
|
sqlitePragmas?: SqlitePragmaConfig;
|
|
767
767
|
/** Disable in-process watchdog timers (use external watchdog instead) */
|
|
768
768
|
useWatchdog?: boolean;
|
|
769
|
-
/**
|
|
769
|
+
/** Default max concurrent instances per workflow name (0 = unlimited, default: 0) */
|
|
770
770
|
concurrentWorkflows?: number;
|
|
771
771
|
/** Resume strategy for orphaned workflows (default: "blocking") */
|
|
772
772
|
resumeStrategy?: WorkflowResumeStrategy;
|
|
@@ -796,6 +796,8 @@ export interface WorkflowRegisterOptions {
|
|
|
796
796
|
* workflows.register(myWorkflow, { modulePath: import.meta.url });
|
|
797
797
|
*/
|
|
798
798
|
modulePath?: string;
|
|
799
|
+
/** Max concurrent instances for this workflow (overrides defaults) */
|
|
800
|
+
maxConcurrent?: number;
|
|
799
801
|
}
|
|
800
802
|
|
|
801
803
|
export interface Workflows {
|
|
@@ -874,6 +876,7 @@ class WorkflowsImpl implements Workflows {
|
|
|
874
876
|
private sqlitePragmas?: SqlitePragmaConfig;
|
|
875
877
|
private useWatchdog: boolean;
|
|
876
878
|
private concurrentWorkflows: number;
|
|
879
|
+
private workflowConcurrencyOverrides = new Map<string, number>();
|
|
877
880
|
private resumeStrategy!: WorkflowResumeStrategy;
|
|
878
881
|
private workflowModulePaths = new Map<string, string>();
|
|
879
882
|
private isolatedProcesses = new Map<string, IsolatedProcessInfo>();
|
|
@@ -1002,6 +1005,10 @@ class WorkflowsImpl implements Workflows {
|
|
|
1002
1005
|
}
|
|
1003
1006
|
|
|
1004
1007
|
this.definitions.set(definition.name, definition);
|
|
1008
|
+
|
|
1009
|
+
if (options?.maxConcurrent !== undefined) {
|
|
1010
|
+
this.workflowConcurrencyOverrides.set(definition.name, options.maxConcurrent);
|
|
1011
|
+
}
|
|
1005
1012
|
}
|
|
1006
1013
|
|
|
1007
1014
|
async start<T = any>(workflowName: string, input: T): Promise<string> {
|
|
@@ -1010,12 +1017,13 @@ class WorkflowsImpl implements Workflows {
|
|
|
1010
1017
|
throw new Error(`Workflow "${workflowName}" is not registered`);
|
|
1011
1018
|
}
|
|
1012
1019
|
|
|
1013
|
-
|
|
1020
|
+
const limit = this.getConcurrencyLimit(workflowName);
|
|
1021
|
+
if (limit > 0) {
|
|
1014
1022
|
const running = await this.adapter.getInstancesByWorkflow(workflowName, "running");
|
|
1015
1023
|
const pending = await this.adapter.getInstancesByWorkflow(workflowName, "pending");
|
|
1016
|
-
if (running.length + pending.length >=
|
|
1024
|
+
if (running.length + pending.length >= limit) {
|
|
1017
1025
|
throw new Error(
|
|
1018
|
-
`Workflow "${workflowName}" has reached its concurrency limit (${
|
|
1026
|
+
`Workflow "${workflowName}" has reached its concurrency limit (${limit})`
|
|
1019
1027
|
);
|
|
1020
1028
|
}
|
|
1021
1029
|
}
|
|
@@ -2005,6 +2013,13 @@ class WorkflowsImpl implements Workflows {
|
|
|
2005
2013
|
await this.adapter.updateInstance(instanceId, { metadata });
|
|
2006
2014
|
}
|
|
2007
2015
|
|
|
2016
|
+
private getConcurrencyLimit(workflowName: string): number {
|
|
2017
|
+
if (this.workflowConcurrencyOverrides.has(workflowName)) {
|
|
2018
|
+
return this.workflowConcurrencyOverrides.get(workflowName) ?? 0;
|
|
2019
|
+
}
|
|
2020
|
+
return this.concurrentWorkflows;
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2008
2023
|
private async markOrphanedAsFailed(
|
|
2009
2024
|
instances: WorkflowInstance[],
|
|
2010
2025
|
reason: string
|