Skip to content

Commit

Permalink
add early js code examples
Browse files Browse the repository at this point in the history
Signed-off-by: Hannah Hunter <[email protected]>
  • Loading branch information
hhunter-ms committed Jan 3, 2024
1 parent 5d3f868 commit 3c9c255
Show file tree
Hide file tree
Showing 2 changed files with 460 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,29 @@ def hello_act(ctx: WorkflowActivityContext, input):

<!--javascript-->

Define the workflow activities you'd like your workflow to perform. Activities are a function definition and can take inputs and outputs. The following example creates a counter (activity) called `hello_act` that notifies users of the current counter value. `hello_act` is a function derived from a class called `WorkflowActivityContext`.
Define the workflow activities you'd like your workflow to perform. Activities are wrapped in the `WorkflowActivityContext` class, which implements the workflow activities.

```javascript
export default class WorkflowActivityContext {
private readonly _innerContext: ActivityContext;
constructor(innerContext: ActivityContext) {
if (!innerContext) {
throw new Error("ActivityContext cannot be undefined");
}
this._innerContext = innerContext;
}

public getWorkflowInstanceId(): string {
return this._innerContext.orchestrationId;
}

public getWorkflowActivityId(): number {
return this._innerContext.taskId;
}
}
```

[See the workflow activity in context.](https://github.com/dapr/python-sdk/blob/master/examples/demo_workflow/app.py#LL40C1-L43C59)
[See the workflow activity in context.](todo)


{{% /codetab %}}
Expand Down Expand Up @@ -214,13 +230,43 @@ def hello_world_wf(ctx: DaprWorkflowContext, input):

<!--javascript-->

The `hello_world_wf` function is derived from a class called `DaprWorkflowContext` with input and output parameter types. It also includes a `yield` statement that does the heavy lifting of the workflow and calls the workflow activities.
Next, register the workflow with the `WorkflowRuntime` class and start the workflow runtime.

```javascript
export default class WorkflowRuntime {

//..
// Register workflow
public registerWorkflow(workflow: TWorkflow): WorkflowRuntime {
const name = getFunctionName(workflow);
const workflowWrapper = (ctx: OrchestrationContext, input: any): any => {
const workflowContext = new WorkflowContext(ctx);
return workflow(workflowContext, input);
};
this.worker.addNamedOrchestrator(name, workflowWrapper);
return this;
}

// Register workflow activities
public registerActivity(fn: TWorkflowActivity<TInput, TOutput>): WorkflowRuntime {
const name = getFunctionName(fn);
const activityWrapper = (ctx: ActivityContext, intput: TInput): TOutput => {
const wfActivityContext = new WorkflowActivityContext(ctx);
return fn(wfActivityContext, intput);
};
this.worker.addNamedActivity(name, activityWrapper);
return this;
}

// Start the workflow runtime processing items and block.
public async start() {
await this.worker.start();
}

}
```

[See the `hello_world_wf` workflow in context.](https://github.com/dapr/python-sdk/blob/master/examples/demo_workflow/app.py#LL32C1-L38C51)
[See the `hello_world_wf` workflow in context.](todo)


{{% /codetab %}}
Expand Down Expand Up @@ -400,7 +446,7 @@ if __name__ == '__main__':

<!--javascript-->

[In the following example](https://github.com/dapr/python-sdk/blob/master/examples/demo_workflow/app.py), for a basic JavaScript hello world application using the Go SDK, your project code would include:
[In the following example](todo), for a basic JavaScript hello world application using the Go SDK, your project code would include:

- A JavaScript package called `todo` to receive the Go SDK capabilities.
- A builder with extensions called:
Expand All @@ -409,8 +455,174 @@ if __name__ == '__main__':
- `WorkflowActivityContext`: Allows you to [create workflow activities]({{< ref "#write-the-workflow-activities" >}})
- API calls. In the example below, these calls start, pause, resume, purge, and terminate the workflow.

```go
```javascript
import { TaskHubGrpcClient } from "kaibocai-durabletask-js";
import * as grpc from "@grpc/grpc-js";
import { WorkflowState } from "./WorkflowState";
import { generateInterceptors } from "../internal/ApiTokenClientInterceptor";
import { TWorkflow } from "../types/Workflow.type";
import { getFunctionName } from "../internal";

export default class WorkflowClient {
private readonly _innerClient: TaskHubGrpcClient;

/**
* Initializes a new instance of the DaprWorkflowClient.
* @param {string | undefined} hostAddress - The address of the Dapr runtime hosting the workflow services.
* @param {grpc.ChannelOptions | undefined} options - Additional options for configuring the gRPC channel.
*/
constructor(hostAddress?: string, options?: grpc.ChannelOptions) {
this._innerClient = this._buildInnerClient(hostAddress, options);
}

_buildInnerClient(hostAddress = "127.0.0.1:50001", options: grpc.ChannelOptions = {}): TaskHubGrpcClient {
const innerOptions = {
...options,
interceptors: [generateInterceptors(), ...(options?.interceptors ?? [])],
};
return new TaskHubGrpcClient(hostAddress, innerOptions);
}

/**
* Schedules a new workflow using the DurableTask client.
*
* @param {TWorkflow | string} workflow - The Workflow or the name of the workflow to be scheduled.
* @return {Promise<string>} A Promise resolving to the unique ID of the scheduled workflow instance.
*/
public async scheduleNewWorkflow(
workflow: TWorkflow | string,
input?: any,
instanceId?: string,
startAt?: Date,
): Promise<string> {
if (typeof workflow === "string") {
return await this._innerClient.scheduleNewOrchestration(workflow, input, instanceId, startAt);
}
return await this._innerClient.scheduleNewOrchestration(getFunctionName(workflow), input, instanceId, startAt);
}

/**
* Terminates the workflow associated with the provided instance id.
*
* @param {string} workflowInstanceId - Workflow instance id to terminate.
* @param {any} output - The optional output to set for the terminated workflow instance.
*/
public async terminateWorkflow(workflowInstanceId: string, output: any) {
await this._innerClient.terminateOrchestration(workflowInstanceId, output);
}

/**
* Fetches workflow instance metadata from the configured durable store.
*
* @param {string} workflowInstanceId - The unique identifier of the workflow instance to fetch.
* @param {boolean} getInputsAndOutputs - Indicates whether to fetch the workflow instance's
* inputs, outputs, and custom status (true) or omit them (false).
* @returns {Promise<WorkflowState | undefined>} A Promise that resolves to a metadata record describing
* the workflow instance and its execution status, or undefined
* if the instance is not found.
*/
public async getWorkflowState(
workflowInstanceId: string,
getInputsAndOutputs: boolean,
): Promise<WorkflowState | undefined> {
const state = await this._innerClient.getOrchestrationState(workflowInstanceId, getInputsAndOutputs);
if (state !== undefined) {
return new WorkflowState(state);
}
}

/**
* Waits for a workflow to start running and returns a {@link WorkflowState} object
* containing metadata about the started instance, and optionally, its input, output,
* and custom status payloads.
*
* A "started" workflow instance refers to any instance not in the Pending state.
*
* If a workflow instance is already running when this method is called, it returns immediately.
*
* @param {string} workflowInstanceId - The unique identifier of the workflow instance to wait for.
* @param {boolean} fetchPayloads - Indicates whether to fetch the workflow instance's
* inputs, outputs (true) or omit them (false).
* @param {number} timeout - The amount of time, in seconds, to wait for the workflow instance to start.
* @returns {Promise<WorkflowState | undefined>} A Promise that resolves to the workflow instance metadata
* or undefined if no such instance is found.
*/
public async waitForWorkflowStart(
workflowInstanceId: string,
fetchPayloads?: boolean,
timeout?: number,
): Promise<WorkflowState | undefined> {
const state = await this._innerClient.waitForOrchestrationStart(workflowInstanceId, fetchPayloads, timeout);
if (state !== undefined) {
return new WorkflowState(state);
}
}

/**
* Waits for a workflow to complete running and returns a {@link WorkflowState} object
* containing metadata about the completed instance, and optionally, its input, output,
* and custom status payloads.
*
* A "completed" workflow instance refers to any instance in one of the terminal states.
* For example, the Completed, Failed, or Terminated states.
*
* If a workflow instance is already running when this method is called, it returns immediately.
*
* @param {string} workflowInstanceId - The unique identifier of the workflow instance to wait for.
* @param {boolean} fetchPayloads - Indicates whether to fetch the workflow instance's
* inputs, outputs (true) or omit them (false).
* @param {number} timeout - The amount of time, in seconds, to wait for the workflow instance to start.
* @returns {Promise<WorkflowState | undefined>} A Promise that resolves to the workflow instance metadata
* or undefined if no such instance is found.
*/
public async waitForWorkflowCompletion(
workflowInstanceId: string,
fetchPayloads = true,
timeout: number,
): Promise<WorkflowState | undefined> {
const state = await this._innerClient.waitForOrchestrationCompletion(workflowInstanceId, fetchPayloads, timeout);
if (state != undefined) {
return new WorkflowState(state);
}
}

/**
* Sends an event notification message to an awaiting workflow instance.
*
* This method triggers the specified event in a running workflow instance,
* allowing the workflow to respond to the event if it has defined event handlers.
*
* @param {string} workflowInstanceId - The unique identifier of the workflow instance that will handle the event.
* @param {string} eventName - The name of the event. Event names are case-insensitive.
* @param {any} [eventPayload] - An optional serializable data payload to include with the event.
*/
public async raiseEvent(workflowInstanceId: string, eventName: string, eventPayload?: any) {
this._innerClient.raiseOrchestrationEvent(workflowInstanceId, eventName, eventPayload);
}

/**
* Purges the workflow instance state from the workflow state store.
*
* This method removes the persisted state associated with a workflow instance from the state store.
*
* @param {string} workflowInstanceId - The unique identifier of the workflow instance to purge.
* @return {Promise<boolean>} A Promise that resolves to true if the workflow state was found and purged successfully, otherwise false.
*/
public async purgeWorkflow(workflowInstanceId: string): Promise<boolean> {
const purgeResult = await this._innerClient.purgeOrchestration(workflowInstanceId);
if (purgeResult !== undefined) {
return purgeResult.deletedInstanceCount > 0;
}
return false;
}

/**
* Closes the inner DurableTask client and shutdown the GRPC channel.
*/
public async stop() {
await this._innerClient.stop();
}
}
```
{{% /codetab %}}
Expand Down
Loading

0 comments on commit 3c9c255

Please sign in to comment.