Skip to content

Commit 2cde0ad

Browse files
Parent Orchestration Access For SubOrchestration (#92)
* feat: add support for parent orchestration instance in sub-orchestrations - Introduced ParentOrchestrationInstance type to represent details of the parent orchestration. - Updated OrchestrationContext to include a parent property for accessing parent orchestration details. - Enhanced newExecutionStartedEvent function to accept parent instance information. - Modified OrchestrationExecutor to extract and set parent instance info during execution. - Added tests to verify parent orchestration info is correctly handled in sub-orchestrations. - Created FEATURE_PARITY.md to document feature comparison between durabletask-js and durabletask-dotnet. * Potential fix for pull request finding 'Unused variable, import, function or class' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> * fix: rename variable for clarity and improve test readability * cleanup * fix: remove redundant import of timer events in parent orchestration tests --------- Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
1 parent 0376f94 commit 2cde0ad

File tree

9 files changed

+406
-1
lines changed

9 files changed

+406
-1
lines changed

package-lock.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/durabletask-js/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export { TOrchestrator } from "./types/orchestrator.type";
7878
export { TActivity } from "./types/activity.type";
7979
export { TInput } from "./types/input.type";
8080
export { TOutput } from "./types/output.type";
81+
export { ParentOrchestrationInstance } from "./types/parent-orchestration-instance.type";
8182

8283
// Logger
8384
export { Logger, ConsoleLogger, NoOpLogger } from "./types/logger.type";

packages/durabletask-js/src/task/context/orchestration-context.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
import { ParentOrchestrationInstance } from "../../types/parent-orchestration-instance.type";
45
import { TActivity } from "../../types/activity.type";
56
import { TOrchestrator } from "../../types/orchestrator.type";
67
import { TaskOptions, SubOrchestrationOptions } from "../options";
@@ -17,6 +18,16 @@ export abstract class OrchestrationContext {
1718
*/
1819
abstract get instanceId(): string;
1920

21+
/**
22+
* Gets the parent orchestration instance, or `undefined` if this is not a sub-orchestration.
23+
*
24+
* This property is useful for determining if the current orchestration was started by another
25+
* orchestration (i.e., it's a sub-orchestration) and for accessing details about the parent.
26+
*
27+
* @returns {ParentOrchestrationInstance | undefined} The parent orchestration details, or `undefined` if this is a top-level orchestration.
28+
*/
29+
abstract get parent(): ParentOrchestrationInstance | undefined;
30+
2031
/**
2132
* Get the current date/time as UTC
2233
*
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
/**
5+
* Represents the parent orchestration instance details for a sub-orchestration.
6+
*
7+
* This information is available when an orchestration is started as a sub-orchestration
8+
* by another orchestration. It provides details about the parent that started this
9+
* orchestration, which can be useful for debugging and tracing.
10+
*/
11+
export interface ParentOrchestrationInstance {
12+
/**
13+
* The name of the parent orchestration.
14+
*/
15+
name: string;
16+
17+
/**
18+
* The unique instance ID of the parent orchestration.
19+
*/
20+
instanceId: string;
21+
22+
/**
23+
* The task scheduled ID that corresponds to this sub-orchestration in the parent's history.
24+
*/
25+
taskScheduledId: number;
26+
}

packages/durabletask-js/src/utils/pb-helper.util.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function newOrchestratorStartedEvent(timestamp?: Date | null): pb.History
2222
return event;
2323
}
2424

25-
export function newExecutionStartedEvent(name: string, instanceId: string, encodedInput?: string): pb.HistoryEvent {
25+
export function newExecutionStartedEvent(name: string, instanceId: string, encodedInput?: string, parentInstance?: { name: string; instanceId: string; taskScheduledId: number }): pb.HistoryEvent {
2626
const ts = new Timestamp();
2727

2828
const orchestrationInstance = new pb.OrchestrationInstance();
@@ -33,6 +33,19 @@ export function newExecutionStartedEvent(name: string, instanceId: string, encod
3333
executionStartedEvent.setInput(getStringValue(encodedInput));
3434
executionStartedEvent.setOrchestrationinstance(orchestrationInstance);
3535

36+
// Set parent instance info if provided (for sub-orchestrations)
37+
if (parentInstance) {
38+
const parentOrchestrationInstance = new pb.OrchestrationInstance();
39+
parentOrchestrationInstance.setInstanceid(parentInstance.instanceId);
40+
41+
const parentInstanceInfo = new pb.ParentInstanceInfo();
42+
parentInstanceInfo.setName(getStringValue(parentInstance.name));
43+
parentInstanceInfo.setOrchestrationinstance(parentOrchestrationInstance);
44+
parentInstanceInfo.setTaskscheduledid(parentInstance.taskScheduledId);
45+
46+
executionStartedEvent.setParentinstance(parentInstanceInfo);
47+
}
48+
3649
const event = new pb.HistoryEvent();
3750
event.setEventid(-1);
3851
event.setTimestamp(ts);

packages/durabletask-js/src/worker/orchestration-executor.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,17 @@ export class OrchestrationExecutor {
129129
throw new OrchestratorNotRegisteredError(executionStartedEvent?.getName());
130130
}
131131

132+
// Extract parent instance info if this is a sub-orchestration
133+
const parentInstance = executionStartedEvent?.getParentinstance();
134+
if (parentInstance) {
135+
const parentOrchestrationInstance = parentInstance.getOrchestrationinstance();
136+
ctx._parent = {
137+
name: parentInstance.getName()?.getValue() ?? "",
138+
instanceId: parentOrchestrationInstance?.getInstanceid() ?? "",
139+
taskScheduledId: parentInstance.getTaskscheduledid(),
140+
};
141+
}
142+
132143
// Deserialize the input, if any
133144
let input = undefined;
134145

packages/durabletask-js/src/worker/runtime-orchestration-context.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import { createHash } from "crypto";
55
import { getName } from "../task";
66
import { OrchestrationContext } from "../task/context/orchestration-context";
7+
import { ParentOrchestrationInstance } from "../types/parent-orchestration-instance.type";
78
import * as pb from "../proto/orchestrator_service_pb";
89
import * as ph from "../utils/pb-helper.util";
910
import { CompletableTask } from "../task/completable-task";
@@ -28,6 +29,7 @@ export class RuntimeOrchestrationContext extends OrchestrationContext {
2829
_newGuidCounter: number;
2930
_currentUtcDatetime: Date;
3031
_instanceId: string;
32+
_parent?: ParentOrchestrationInstance;
3133
_completionStatus?: pb.OrchestrationStatus;
3234
_receivedEvents: Record<string, any[]>;
3335
_pendingEvents: Record<string, CompletableTask<any>[]>;
@@ -48,6 +50,7 @@ export class RuntimeOrchestrationContext extends OrchestrationContext {
4850
this._newGuidCounter = 0;
4951
this._currentUtcDatetime = new Date(1000, 0, 1);
5052
this._instanceId = instanceId;
53+
this._parent = undefined;
5154
this._completionStatus = undefined;
5255
this._receivedEvents = {};
5356
this._pendingEvents = {};
@@ -60,6 +63,10 @@ export class RuntimeOrchestrationContext extends OrchestrationContext {
6063
return this._instanceId;
6164
}
6265

66+
get parent(): ParentOrchestrationInstance | undefined {
67+
return this._parent;
68+
}
69+
6370
get currentUtcDateTime(): Date {
6471
return this._currentUtcDatetime;
6572
}

0 commit comments

Comments
 (0)