diff --git a/README.md b/README.md
index cafd944f..760b95db 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,10 @@ TypeScript code gets transpiled to JavaScript code during the build process. Any
As a result, all code you include needs to be complete, or the site will fail to build.
+## dprint
+
+Consider running `yarn format` after the Snipsync toolchain or after making other edits. This runs `dprint` using the same configuration as the documentation repo, and should take care of dedenting and other formatting issues.
+
## Run the development server
To preview the site, run the local server with the following command:
diff --git a/docs/tutorials/go/background-check/durable-execution.mdx b/docs/tutorials/go/background-check/durable-execution.mdx
index 64ee4a88..26b2c2ec 100644
--- a/docs/tutorials/go/background-check/durable-execution.mdx
+++ b/docs/tutorials/go/background-check/durable-execution.mdx
@@ -37,7 +37,6 @@ tags:
- timer
---
-
When it comes to the Temporal Platform's ability to durably execute code, the SDK's ability to [Replay](https://docs.temporal.io/dev-guide/sdks#replays) a Workflow Execution is a major aspect of that.
This chapter introduces the development patterns which enable that.
@@ -140,7 +139,6 @@ From the Workflow details page you can copy the Event History from the JSON tab
## Add a Replay test {#add-replay-test}
-
Add the Replay test to the set of application tests.
The Replayer is available from the `go.temporal.io/sdk/worker` package in the SDK.
Register the Workflow Definition and then specify an existing Event History to compare to.
@@ -149,9 +147,10 @@ Run the tests in the test directory (`go test`).
If the Workflow Definition and the Event History are incompatible then the test fails.
+
[docs/tutorials/go/background-check/code/durability/tests/backgroundcheck_test.go](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/go/background-check/code/durability/tests/backgroundcheck_test.go)
-```go
+```go
// TestReplayWorkflowHistoryFromFile tests for Event History compatibility.
func (s *UnitTestSuite) TestReplayWorkflowHistoryFromFile() {
// Create a new Replayer
@@ -163,8 +162,8 @@ func (s *UnitTestSuite) TestReplayWorkflowHistoryFromFile() {
err := replayer.ReplayWorkflowHistoryFromJSONFile(nil, "backgroundcheck_workflow_event_history.json")
s.NoError(err)
}
-
```
+
### Why add a Replay test? {#why-replay-test}
@@ -184,7 +183,6 @@ Workflow code becomes non-deterministic primarily through two main avenues:
## Intrinsic non-deterministic logic {#intrinsic-non-deterministic-logic}
-
Referred to as "intrinsic non-determinism" this kind of "bad" Workflow code can prevent the Workflow code from completing because the Workflow can take a different code path than the one expected from the Event History.
The following are some common operations that **can't** be done inside of a Workflow Definition:
@@ -196,10 +194,10 @@ The following are some common operations that **can't** be done inside of a Work
- Use `workflow.Now()` as a replacement for `time.Now()`.
- Use `workflow.Sleep()` as a replacement for `time.Sleep()`.
- Working directly with threads or goroutines.
- - Use `workflow.Go()` as a replacement for the `go` statement.
- - Use `workflow.Channel()` as a replacement for the native `chan` type.
- Temporal provides support for both buffered and unbuffered channels.
- - Use `workflow.Selector()` as a replacement for the `select` statement.
+ - Use `workflow.Go()` as a replacement for the `go` statement.
+ - Use `workflow.Channel()` as a replacement for the native `chan` type.
+ Temporal provides support for both buffered and unbuffered channels.
+ - Use `workflow.Selector()` as a replacement for the `select` statement.
- Iterating over data structures with unknown ordering.
This includes iterating over maps using `range`, because with `range` the order of the map's iteration is randomized.
Instead you can collect the keys of the map, sort them, and then iterate over the sorted keys to access the map.
@@ -210,7 +208,9 @@ The following are some common operations that **can't** be done inside of a Work
One way to produce a non-deterministic error is to use a random number to determine whether to sleep inside the Workflow.
+
[docs/tutorials/go/background-check/code/durability/workflows/backgroundcheck_non_deterministic_code.go](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/go/background-check/code/durability/workflows/backgroundcheck_non_deterministic_code.go)
+
```go
// CAUTION! Do not use this code!
package workflows
@@ -247,8 +247,8 @@ func BackgroundCheckNonDeterministic(ctx workflow.Context, param string) (string
}
return ssnTraceResult, nil
}
-
```
+
If you run the BackgroundCheckNonDeterministic Workflow enough times, eventually you will see a Workflow Task failure.
@@ -391,7 +391,6 @@ The [Event reference](https://docs.temporal.io/references/events) serves as a so
### Add a call to sleep {#add-sleep-call}
-
In the following sample, we add a couple of logging statements and a Timer to the Workflow code to see how this affects the Event History.
Use the `workflow.Sleep()` API to cause the Workflow to sleep for a minute before the call to execute the Activity.
@@ -400,7 +399,9 @@ The Temporal SDK offers both a `workflow.StartTimer()` API, and a `workflow.Slee
Use the `workflow.GetLogger` API to log from Workflows to avoid seeing repeated logs from the Replay of the Workflow code.
+
[docs/tutorials/go/background-check/code/durability/workflows/backgroundcheck.go](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/go/background-check/code/durability/workflows/backgroundcheck.go)
+
```go
package workflows
@@ -438,13 +439,12 @@ func BackgroundCheck(ctx workflow.Context, param string) (string, error) {
// Make the results of the Workflow available
return ssnTraceResult, nil
}
-
```
+
### Inspect the new Event History {#inspect-new-event-history}
-
After updating your Workflow code to include the logging and Timer, run your tests again.
You should expect to see the `TestReplayWorkflowHistoryFromFile` test fail.
This is because the code we added creates new Events and alters the Event History sequence.
@@ -484,4 +484,3 @@ The following are a few examples of changes that do not lead to non-deterministi
- Modifying non-Command generating statements in a Workflow Definition, such as logging statements
- Changing attributes in the `ActivityOptions`
- Modifying code inside of an Activity Definition
-
diff --git a/docs/tutorials/go/background-check/index.mdx b/docs/tutorials/go/background-check/index.mdx
index 287434f3..c8207412 100644
--- a/docs/tutorials/go/background-check/index.mdx
+++ b/docs/tutorials/go/background-check/index.mdx
@@ -21,5 +21,3 @@ The tutorial is laid out in the following chapters:
- [Introduction](/tutorials/go/background-check/introduction)
- [Project setup](/tutorials/go/background-check/project-setup)
- [Develop for durability](/tutorials/go/background-check/durable-execution)
-
-
diff --git a/docs/tutorials/go/background-check/introduction.mdx b/docs/tutorials/go/background-check/introduction.mdx
index 236aaf37..ac353974 100644
--- a/docs/tutorials/go/background-check/introduction.mdx
+++ b/docs/tutorials/go/background-check/introduction.mdx
@@ -25,15 +25,15 @@ If you are reading this, chances are you already have some notion of why you wan
However, if you are still unsure, there are three major reasons why Temporal might be right for you.
1. **Reliabile execution.**
- With Temporal, you can rely on your application to work.
- The design of the system ensures that, once started, an application's main function executes to completion, whether that takes minutes, hours, days, weeks, or even years.
- Temporal calls this "Durable Execution".
+ With Temporal, you can rely on your application to work.
+ The design of the system ensures that, once started, an application's main function executes to completion, whether that takes minutes, hours, days, weeks, or even years.
+ Temporal calls this "Durable Execution".
2. **Code structure.**
- Temporal's programming model offers developers a way to express their business logic into coherent "Workflows" that are much easier to develop than distributed code bases.
+ Temporal's programming model offers developers a way to express their business logic into coherent "Workflows" that are much easier to develop than distributed code bases.
3. **State visibility.**
- The Temporal system provides out-of-the-box tooling that enables developers to see the state of their applications whenever they need to.
+ The Temporal system provides out-of-the-box tooling that enables developers to see the state of their applications whenever they need to.
## Audience
diff --git a/docs/tutorials/go/background-check/project-setup.mdx b/docs/tutorials/go/background-check/project-setup.mdx
index 6d74152d..c624b4c9 100644
--- a/docs/tutorials/go/background-check/project-setup.mdx
+++ b/docs/tutorials/go/background-check/project-setup.mdx
@@ -358,12 +358,13 @@ go get go.temporal.io/sdk
### Boilerplate Workflow code {#workflow-code}
-
In the Temporal Go SDK programming model, a [Workflow Definition](https://docs.temporal.io/workflows#workflow-definition) is an exportable function.
The `BackgroundCheck` function below is an example of a basic Workflow Definition.
+
[docs/tutorials/go/background-check/code/setup/workflows/backgroundcheck.go](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/go/background-check/code/setup/workflows/backgroundcheck.go)
+
```go
package workflows
@@ -392,8 +393,8 @@ func BackgroundCheck(ctx workflow.Context, param string) (string, error) {
// Make the results of the Workflow available
return ssnTraceResult, nil
}
-
```
+
The first parameter of a Go-based Workflow Definition must be of the [`workflow.Context`](https://pkg.go.dev/go.temporal.io/sdk/workflow#Context) type.
@@ -419,12 +420,13 @@ For example, in a small project like this, it is still a best practice to have a
### Boilerplate Activity code {#activity-code}
-
In the Temporal Go SDK programming model, an Activity is an exportable function or a `struct` method.
Below is an example of an Activity defined as a function.
+
[docs/tutorials/go/background-check/code/setup/activities/ssntraceactivity.go](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/go/background-check/code/setup/activities/ssntraceactivity.go)
+
```go
package activities
@@ -439,8 +441,8 @@ func SSNTraceActivity(ctx context.Context, param string) (*string, error) {
result := "pass"
return &result, nil
}
-
```
+
The first parameter of an Activity Definition is `context.Context`.
@@ -462,7 +464,9 @@ To run a Worker Process with a local development server, define the following st
In regards to organization, we recommend keeping Worker code separate from Workflow and Activity code.
+
[docs/tutorials/go/background-check/code/setup/dev_server_worker/main.go](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/go/background-check/code/setup/dev_server_worker/main.go)
+
```go
package main
@@ -499,8 +503,8 @@ func main() {
log.Fatalln("Unable to start the Worker Process", err)
}
}
-
```
+
:::info Auto restart worker when code changes
@@ -523,7 +527,9 @@ A Temporal Cloud Worker requires that you specify the following in the Client co
- Certificate and private key associated with the Namespace
+
[docs/tutorials/go/background-check/code/setup/cloud_worker/main.go](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/go/background-check/code/setup/cloud_worker/main.go)
+
```go
package main
@@ -584,19 +590,19 @@ func main() {
log.Fatalln("Unable to start the Worker Process", err)
}
}
-
```
+
- To run a Temporal Cloud Worker, you'll change some parameters in your Client connection code, such as updating the namespace and gRPC endpoint.
- You'll use:
-
- - The [Temporal Cloud Namespace Id](https://docs.temporal.io/cloud/namespaces#temporal-cloud-namespace-id).
- - The [Namespace's gRPC endpoint](https://docs.temporal.io/cloud/namespaces#temporal-cloud-grpc-endpoint).
- The endpoint uses this format `(namespace.unique_id.tmprl.cloud:port)`.
- - [Paths to the SSL certificate (.pem) and private key (.key)](https://docs.temporal.io/cloud/saml#integrate-saml-with-your-temporal-cloud-account) registered to your Namespace and stored on your Worker's file system.
-
- Copy the Namespace Id and the gRPC endpoint from the Namespace detail Web page on [Temporal Cloud Namespaces](https://cloud.temporal.io/namespaces). Click on a Namespace name to open the Namespace details.
+To run a Temporal Cloud Worker, you'll change some parameters in your Client connection code, such as updating the namespace and gRPC endpoint.
+You'll use:
+
+- The [Temporal Cloud Namespace Id](https://docs.temporal.io/cloud/namespaces#temporal-cloud-namespace-id).
+- The [Namespace's gRPC endpoint](https://docs.temporal.io/cloud/namespaces#temporal-cloud-grpc-endpoint).
+ The endpoint uses this format `(namespace.unique_id.tmprl.cloud:port)`.
+- [Paths to the SSL certificate (.pem) and private key (.key)](https://docs.temporal.io/cloud/saml#integrate-saml-with-your-temporal-cloud-account) registered to your Namespace and stored on your Worker's file system.
+
+Copy the Namespace Id and the gRPC endpoint from the Namespace detail Web page on [Temporal Cloud Namespaces](https://cloud.temporal.io/namespaces). Click on a Namespace name to open the Namespace details.
### Run a Self-hosted Worker {#dockerfile}
@@ -667,7 +673,9 @@ Copy the IP address part.
Set IP address, port, and Namespace in the Temporal Client options.
+
[docs/tutorials/go/background-check/code/setup/self_hosted_worker/main.go](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/go/background-check/code/setup/self_hosted_worker/main.go)
+
```go
package main
@@ -709,8 +717,8 @@ func main() {
log.Fatalln("Unable to start the Worker Process", err)
}
}
-
```
+
#### Build and deploy Docker image {#dockerfile}
@@ -932,14 +940,15 @@ You should now be at [http://localhost:8080/namespaces/backgroundcheck_namespace
## Add a testing framework {#test-framework}
-
**How to add a Testing Framework and Tests for the Workflow and Activity.**
Each Temporal SDK has a testing suite that can be used in conjunction with a typical language specific testing framework.
-In the Temporal Go SDK, the `testsuite` package (https://pkg.go.dev/go.temporal.io/sdk/testsuite) provides a test environment in which the Workflow and Activity code may be run for test purposes.
+In the Temporal Go SDK, the `testsuite` package (https://pkg.go.dev/go.temporal.io/sdk/testsuite) provides a test environment in which the Workflow and Activity code may be run for test purposes.
+
[docs/tutorials/go/background-check/code/setup/tests/backgroundcheckboilerplate_test.go](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/go/background-check/code/setup/tests/backgroundcheckboilerplate_test.go)
+
```go
package setup
@@ -967,8 +976,8 @@ func Test_BackgroundCheckApplication(t *testing.T) {
s := &UnitTestSuite{}
suite.Run(t, s)
}
-
```
+
In this example, we use a custom struct that absorbs both the testing functionality from testify (https://pkg.go.dev/github.com/stretchr/testify/suite) via `suite.Suite` and the testing functionality from the Temporal test framework via `testsuite.WorkflowTestSuite`.
@@ -976,7 +985,6 @@ Next we create a regular test function recognized by the `go test` command, an
### Add Workflow function tests {#test-workflow-code}
-
We can test Workflow code for the following conditions:
- Workflow status. For example, did the Workflow reach a completed status?
@@ -987,9 +995,10 @@ We can test Workflow code for the following conditions:
We can also perform a Workflow Replay test, and we'll provide detailed coverage of this topic in another section.
+
[docs/tutorials/go/background-check/code/setup/tests/backgroundcheckboilerplate_test.go](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/go/background-check/code/setup/tests/backgroundcheckboilerplate_test.go)
-```go
+```go
const ssn string = "555-55-5555"
// Test_BackgroundCheckWorkflow tests the BackgroundCheck Workflow function
@@ -1013,8 +1022,8 @@ func (s *UnitTestSuite) Test_BackgroundCheckWorkflow() {
s.NoError(env.GetWorkflowResult(&result))
s.Equal(result, ssnTraceResult)
}
-
```
+
Calling `env.ExecuteWorkflow(...)` executes the Workflow logic and any invoked Activities inside the test process.
@@ -1036,9 +1045,10 @@ We can test Activity code for the following conditions:
- Activity return values. Check to ensure the return value is expected.
+
[docs/tutorials/go/background-check/code/setup/tests/backgroundcheckboilerplate_test.go](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/go/background-check/code/setup/tests/backgroundcheckboilerplate_test.go)
-```go
+```go
// Test_SSNTraceActivity tests the SSNTraceActivity function
func (s *UnitTestSuite) Test_SSNTraceActivity() {
// Create a test environment
@@ -1055,6 +1065,6 @@ func (s *UnitTestSuite) Test_SSNTraceActivity() {
// Check for the expected return value.
s.Equal("pass", result)
}
-
```
+
diff --git a/docs/tutorials/java/background-check/durable-execution.mdx b/docs/tutorials/java/background-check/durable-execution.mdx
index 85a6814e..954c8928 100644
--- a/docs/tutorials/java/background-check/durable-execution.mdx
+++ b/docs/tutorials/java/background-check/durable-execution.mdx
@@ -141,7 +141,9 @@ From the Workflow details page you can copy the Event History from the JSON tab
Add the Replay test to the set of application tests.
+
[docs/tutorials/java/background-check/code/backgroundcheck-replay/src/test/java/backgroundcheckreplay/BackgroundCheckReplayWorkflowTest.java](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/java/background-check/code/backgroundcheck-replay/src/test/java/backgroundcheckreplay/BackgroundCheckReplayWorkflowTest.java)
+
```java
// ...
@Test
@@ -155,6 +157,7 @@ Add the Replay test to the set of application tests.
}
}
```
+
### Why add a Replay test? {#why-replay-test}
@@ -194,7 +197,9 @@ The following are some common operations that **can't** be done inside of a Work
One way to produce a non-deterministic error is to use a random number to determine whether to sleep inside the Workflow.
+
[docs/tutorials/java/background-check/code/backgroundcheck-replay/src/main/java/backgroundcheckreplay/BackgroundCheckReplayNonDeterministicWorkflowImpl.java](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/java/background-check/code/backgroundcheck-replay/src/main/java/backgroundcheckreplay/BackgroundCheckReplayNonDeterministicWorkflowImpl.java)
+
```java
package backgroundcheckreplay;
@@ -237,6 +242,7 @@ public class BackgroundCheckReplayNonDeterministicWorkflowImpl implements Backgr
}
```
+
## Non-deterministic code changes {#durability-through-replays}
@@ -319,7 +325,9 @@ The Temporal SDK offers both a `Workflow.newTimer()` API, and a `Workflow.sleep(
Use the `Workflow.getLogger` API to log from Workflows to suppress repeated logs from the Replay of the Workflow code.
+
[docs/tutorials/java/background-check/code/backgroundcheck-replay/src/main/java/backgroundcheckreplay/BackgroundCheckReplayWorkflowImpl.java](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/java/background-check/code/backgroundcheck-replay/src/main/java/backgroundcheckreplay/BackgroundCheckReplayWorkflowImpl.java)
+
```java
package backgroundcheckreplay;
@@ -361,8 +369,8 @@ public class BackgroundCheckReplayWorkflowImpl implements BackgroundCheckReplayW
}
}
-
```
+
### Inspect the new Event History {#inspect-new-event-history}
diff --git a/docs/tutorials/java/background-check/introduction.mdx b/docs/tutorials/java/background-check/introduction.mdx
index 32c83196..79106599 100644
--- a/docs/tutorials/java/background-check/introduction.mdx
+++ b/docs/tutorials/java/background-check/introduction.mdx
@@ -15,7 +15,6 @@ tags:
- temporal-sdk
---
-
Welcome to Temporal Java SDK Background Check tutorial.
:::info Temporal Java SDK API reference
@@ -177,4 +176,3 @@ For complex and large-scale use cases, having at least some experience with a va
The Temporal Java SDK is an Apache 2.0 licensed, and contributions are welcome.
Please review our [contribution guidelines](https://github.com/temporalio/sdk-java/blob/master/CONTRIBUTING.md).
-
diff --git a/docs/tutorials/java/background-check/project-setup.mdx b/docs/tutorials/java/background-check/project-setup.mdx
index fa03d6e2..6ae126f6 100644
--- a/docs/tutorials/java/background-check/project-setup.mdx
+++ b/docs/tutorials/java/background-check/project-setup.mdx
@@ -39,7 +39,6 @@ tags:
- workflow
---
-
This section covers how to use a terminal, a code editor, and a development Cluster to create a Namespace, write a single Activity Workflow, run a Worker that talks to your development Cluster, run a Workflow using the Temporal CLI, add a testing framework, and view Workflows in the Web UI.
:::note Construct a new Temporal Application project
@@ -70,11 +69,11 @@ Reference [the documentation](https://docs.temporal.io/cli) for detailed install
### Install via download
1. Download the version for your OS and architecture:
- - [Linux amd64](https://temporal.download/cli/archive/latest?platform=linux&arch=amd64)
- - [Linux arm64](https://temporal.download/cli/archive/latest?platform=linux&arch=arm64)
- - [macOS amd64](https://temporal.download/cli/archive/latest?platform=darwin&arch=amd64)
- - [macOS arm64](https://temporal.download/cli/archive/latest?platform=darwin&arch=arm64) (Apple silicon)
- - [Windows amd64](https://temporal.download/cli/archive/latest?platform=windows&arch=amd64)
+ - [Linux amd64](https://temporal.download/cli/archive/latest?platform=linux&arch=amd64)
+ - [Linux arm64](https://temporal.download/cli/archive/latest?platform=linux&arch=arm64)
+ - [macOS amd64](https://temporal.download/cli/archive/latest?platform=darwin&arch=amd64)
+ - [macOS arm64](https://temporal.download/cli/archive/latest?platform=darwin&arch=arm64) (Apple silicon)
+ - [Windows amd64](https://temporal.download/cli/archive/latest?platform=windows&arch=amd64)
2. Extract the downloaded archive.
3. Add the `temporal` binary to your `PATH` (`temporal.exe` for Windows).
@@ -89,6 +88,7 @@ Reference [the documentation](https://docs.temporal.io/cli) for detailed install
3. Switch to cloned directory, and run `go build ./cmd/temporal`
:::note
+
- The executable will be at `temporal` (`temporal.exe` for Windows).
Reference [the documentation](https://docs.temporal.io/cli) for detailed usage information.
@@ -379,8 +379,8 @@ public interface BackgroundCheckBoilerplateWorkflow {
public String backgroundCheck(String socialSecurityNumber);
}
-
```
+
To designate an interface as a Workflow, annotate the interface declaration
@@ -391,7 +391,6 @@ There can only be one Workflow Method per Workflow Definition.
#### Boilerplate Workflow Implementation {#workflow-code}
-
Now that you've defined your Workflow Interface you can define its implementation.
@@ -424,6 +423,7 @@ public class BackgroundCheckBoilerplateWorkflowImpl implements BackgroundCheckBo
}
```
+
You define your Workflow Implementation by defining a class that `implements` the
@@ -435,21 +435,21 @@ time, but Temporal requires that you set _either_ `StartToCloseTimeout` or `Sche
when creating your Activities stub. You can read more about these options [in our documentation](https://docs.temporal.io/activities#start-to-close-timeout)
As with regular Java methods, Workflow Methods support the passing of parameters.
-However, all Workflow Definition parameters must be serializable (using the Jackson JSON
+However, all Workflow Definition parameters must be serializable (using the Jackson JSON
Payload Converter).
-To request the execution of an Activity, also referred to as an [Activity Execution](https://docs.temporal.io/activities#activity-execution),
+To request the execution of an Activity, also referred to as an [Activity Execution](https://docs.temporal.io/activities#activity-execution),
call the Activity Method from within the Workflow Method. Use the `activities`
-object that was created in the Workflow Definition to call the Activity Method
-along with the any parameters that need to be passed.
+object that was created in the Workflow Definition to call the Activity Method
+along with the any parameters that need to be passed.
-A Java-based Workflow Definition can return any serializable output, or raise an
+A Java-based Workflow Definition can return any serializable output, or raise an
exception if one was encountered.
-We get into the best practices around Workflow parameters, return values, and
+We get into the best practices around Workflow parameters, return values, and
exceptions in the one of the next sections.
In regards to code organization, we recommend organizing Workflow code the same
-way you'd organize your standard Java code.
+way you'd organize your standard Java code.
### Boilerplate Activity Code {#boilerplate-activity-code}
@@ -457,7 +457,6 @@ In the Temporal Java SDK programming model, an Activity is defined as an interfa
#### Boilerplate Activity Interface {#activity-code}
-
The `BackgroundCheckActivity` interface below is an example of a the first part defining an Activity
@@ -477,6 +476,7 @@ public interface BackgroundCheckBoilerplateActivities {
}
```
+
To designate an interface as a Activity, annotate the interface declaration
@@ -487,7 +487,6 @@ Activity. There can multiple Activity Methods per Activity Definition.
#### Boilerplate Activity Implementation {#activity-code}
-
Now that you've defined your Activity Interface you can define its implementation.
@@ -510,22 +509,23 @@ public class BackgroundCheckBoilerplateActivitiesImpl implements BackgroundCheck
}
```
+
You define your Activity Implementation by defining a class that `implements` the
Activity Interface.
As with regular Java methods, Activity Methods support the passing of parameters.
-However, all Activity parameters must be serializable (using the Jackson JSON
+However, all Activity parameters must be serializable (using the Jackson JSON
Payload Converter).
-A Java-based Activity Definition can return any serializable output, or raise an
+A Java-based Activity Definition can return any serializable output, or raise an
exception if one was encountered.
-We get into the best practices around Activity parameters, return values, and
+We get into the best practices around Activity parameters, return values, and
exceptions in the one of the next sections.
In regards to code organization, we recommend organizing Activity code the same
-way you'd organize your standard Java code.
+way you'd organize your standard Java code.
### Run your Workflow and Activities using a Worker {#run-workers}
@@ -541,6 +541,7 @@ no progress unless at least one Worker is running.
#### Run a dev server Worker {#dev-server-worker}
To run a Worker Process with a local development server, define the following steps in code:
+
- Generate the gRPC stubs necessary to configure a connection to a Temporal Cluster running on localhost using the 'default' namespace
- Initialize a Temporal Client (`WorkflowClient`), passing in the gRPC stubs.
- Initialize a WorkerFactory, passing in the Temporal Client (`WorkflowClient`)
@@ -587,11 +588,11 @@ public class DevServerWorker {
}
}
```
+
#### Run a Temporal Cloud Worker {#cloud-worker}
-
A Temporal Cloud Worker requires that you specify the following in the Client connection options:
- Temporal Cloud Namespace
@@ -672,22 +673,22 @@ public class CloudWorker {
}
}
```
+
To run a Temporal Cloud Worker, you'll change some parameters in your Client connection code, such as updating the namespace and gRPC endpoint.
- You'll use:
-
- - The [Temporal Cloud Namespace Id](https://docs.temporal.io/cloud/namespaces#temporal-cloud-namespace-id).
- - The [Namespace's gRPC endpoint](https://docs.temporal.io/cloud/namespaces#temporal-cloud-grpc-endpoint).
- The endpoint uses this format `(namespace.unique_id.tmprl.cloud:port)`.
- - [Paths to the SSL certificate (.pem) and private key (.key)](https://docs.temporal.io/cloud/saml#integrate-saml-with-your-temporal-cloud-account) registered to your Namespace and stored on your Worker's file system.
-
- Copy the Namespace Id and the gRPC endpoint from the Namespace detail Web page on [Temporal Cloud Namespaces](https://cloud.temporal.io/namespaces). Click on a Namespace name to open the Namespace details.
-
- For information about managing and generating client certificates for Temporal Cloud, see [How to manage certificates in Temporal Cloud](https://docs.temporal.io/cloud/certificates#issue-certificates).
-
- For information about configuring TLS to secure inter- and intra-network communication for a Temporal Cluster, see [Temporal Customization Samples](https://github.com/temporalio/samples-server).
-
+You'll use:
+
+- The [Temporal Cloud Namespace Id](https://docs.temporal.io/cloud/namespaces#temporal-cloud-namespace-id).
+- The [Namespace's gRPC endpoint](https://docs.temporal.io/cloud/namespaces#temporal-cloud-grpc-endpoint).
+ The endpoint uses this format `(namespace.unique_id.tmprl.cloud:port)`.
+- [Paths to the SSL certificate (.pem) and private key (.key)](https://docs.temporal.io/cloud/saml#integrate-saml-with-your-temporal-cloud-account) registered to your Namespace and stored on your Worker's file system.
+
+Copy the Namespace Id and the gRPC endpoint from the Namespace detail Web page on [Temporal Cloud Namespaces](https://cloud.temporal.io/namespaces). Click on a Namespace name to open the Namespace details.
+
+For information about managing and generating client certificates for Temporal Cloud, see [How to manage certificates in Temporal Cloud](https://docs.temporal.io/cloud/certificates#issue-certificates).
+
+For information about configuring TLS to secure inter- and intra-network communication for a Temporal Cluster, see [Temporal Customization Samples](https://github.com/temporalio/samples-server).
#### Run a Self-hosted Worker {#dockerfile}
@@ -753,8 +754,7 @@ Example output:
Copy the IP address part.
-
-Set IP address and port in the Service Stubs Options and the Namespace in the
+Set IP address and port in the Service Stubs Options and the Namespace in the
Temporal Client options.
@@ -806,8 +806,8 @@ public class SelfHostedWorker {
factory.start();
}
}
-
```
+
Add a Docker file to the root of your Background Check application project.
@@ -1058,12 +1058,12 @@ Make sure to set the version that matches your dependency version of the [Tempor
### Testing Activities {#test-framework}
-
Temporal provides the `TestActivityEnvironment` and `TestActivityExtension` classes
to allow for testing Activities outside the scope of a Workflow. Testing
Activities is similar to testing non-Temporal java code.
Some examples of things an Activity can be tested for are:
+
- Exceptions thrown when invoking the Activity Execution.
- Exceptions thrown when checking for the result of the Activity Execution.
- Activity return values. Check to ensure the return value is expected.
@@ -1073,7 +1073,6 @@ This example asserts that the expected value was returned by the invocation of t
```java
-
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -1105,10 +1104,10 @@ public class BackgroundCheckBoilerplateActivitiesTest {
}
```
-Temporal provides the `TestActivityExtension` class to simplify the creation of
-the test environment. Using this extension you provide your Activity
-to register with a Worker created by the testing framework to be used during testing.
-The extension provides a a stubbed Activity object to each test as well as
+Temporal provides the `TestActivityExtension` class to simplify the creation of
+the test environment. Using this extension you provide your Activity
+to register with a Worker created by the testing framework to be used during testing.
+The extension provides a a stubbed Activity object to each test as well as
manage the lifecycle of the test environment.
If you require more granular control of the test environments, you can manually create
and destroy all these parts in methods annotated with `@BeforeEach` and `@AfterEach`
@@ -1123,16 +1122,17 @@ to allow for testing Workflows. There are two ways to test Workflows; the first
is to test the Workflow code without invoking the real Activities by mocking
the Workflow's Activities and the second is to test the Workflow and its Activities
in their entirety. This section will focus on the first scenario while a following
-section will cover the later.
+section will cover the later.
-Testing your Workflows without invoking your Activities can be useful for testing
-Workflow specific logic without having to worry about the Activity invocation
-producing a side-effect or having any Activity downstream dependency, such as a
+Testing your Workflows without invoking your Activities can be useful for testing
+Workflow specific logic without having to worry about the Activity invocation
+producing a side-effect or having any Activity downstream dependency, such as a
microservice, be available during the duration of your testing.
As for the actual testing code, testing Workflows is similar to testing non-Temporal java code.
Some examples of things an Workflow can be tested for are:
+
- Exceptions thrown when invoking the Workflow Execution.
- Exceptions thrown when checking for the result of the Workflow Execution.
- Workflow return values. Check to ensure the return value is expected.
@@ -1142,7 +1142,6 @@ We can also perform a Workflow Replay test, and we'll provide detailed coverage
```java
-
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -1193,18 +1192,16 @@ public class BackgroundCheckBoilerplateWorkflowTest {
}
```
-
-
As for the code, first you register your Workflow with the `TestWorkflowExtension`.
-This extension allows you to pass in a `TestWorklowEnvironment`, `Worker`, and
-an instance of your Workflow into your tests. To test your Workflow using mocked
-activities you then create a mocked object of your Activity class to be used for
-testing. Then you mock the Activity method, in this case `ssNTraceAcvitity`, so
-that when when a specific value is passed to the Activity it returns a specific result.
+This extension allows you to pass in a `TestWorklowEnvironment`, `Worker`, and
+an instance of your Workflow into your tests. To test your Workflow using mocked
+activities you then create a mocked object of your Activity class to be used for
+testing. Then you mock the Activity method, in this case `ssNTraceAcvitity`, so
+that when when a specific value is passed to the Activity it returns a specific result.
Then the mocked object is used to register the mocked Activities with the Worker
-being used in the test environment. Then you start the test environment, invoke
-your Workflow as usual, passing in the specific value for your Activity so that
-the Activity returns the result you are expecting. Then you assert that the
+being used in the test environment. Then you start the test environment, invoke
+your Workflow as usual, passing in the specific value for your Activity so that
+the Activity returns the result you are expecting. Then you assert that the
results are what you expected.
Doiong this allows you to test the Workflow code without having to worry
@@ -1212,17 +1209,17 @@ about actually invoking the Activity.
### Testing Workflow and Activity together (Integration Testing) {#test-framework}
-
Temporal provides the `TestWorkflowEnvironment` and `TestWorkflowExtension` classes
to allow for testing Workflows. There are two ways to test Workflows; the first
is to test the Workflow code without invoking the real Activities by mocking
the Workflow's Activities and the second is to test the Workflow and its Activities
in their entirety. This section will focus on the second scenario while a previous
-section will cover the first.
+section will cover the first.
As for the actual testing code, testing Workflows is similar to testing non-Temporal java code.
Some examples of things an Workflow can be tested for are:
+
- Exceptions thrown when invoking the Workflow Execution.
- Exceptions thrown when checking for the result of the Workflow Execution.
- Workflow return values. Check to ensure the return value is expected.
@@ -1232,7 +1229,6 @@ We can also perform a Workflow Replay test, and we'll provide detailed coverage
```java
-
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -1272,8 +1268,6 @@ public class BackgroundCheckBoilerplateWorkflowIntegrationTest {
}
```
-
-
This example tests a complete Workflow by invoking the Activities the Workflow
calls. This is, in reality, an integration test. Integration testing is useful
for ensuring the complete success of your entire Workflow. However, note that
@@ -1282,11 +1276,10 @@ must be online for the testing. Furthermore, any mutations the Activity would ty
perform as part of its regular execution will be performed as part of testing.
We recommend either having an entirely separate testing environment for testing
your Workflows, or testing your Workflow and Activity code in isolation, as
-detailed in prior sections in this guide.
+detailed in prior sections in this guide.
As for the code, first you register your Workflow with the `TestWorkflowExtension`.
-This extension allows you to pass in a `TestWorkflowEnvironment`, `Worker`, and
+This extension allows you to pass in a `TestWorkflowEnvironment`, `Worker`, and
an instance of your Workflow into your tests. From there you register your Activities
-with the Worker, start the test environment, and invoke your Workflow as you would
+with the Worker, start the test environment, and invoke your Workflow as you would
typically. Then you assert that the results are what you expected.
-
diff --git a/docs/tutorials/python/background-check/durable-execution.mdx b/docs/tutorials/python/background-check/durable-execution.mdx
index db882f41..b101d784 100644
--- a/docs/tutorials/python/background-check/durable-execution.mdx
+++ b/docs/tutorials/python/background-check/durable-execution.mdx
@@ -154,7 +154,9 @@ Run the tests in the test directory (pytest).
If the Workflow Definition and the Event History are incompatible, then the test fails.
+
[docs/tutorials/python/background-check/code/backgroundcheck_replay/tests/replay_dacx_test.py](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/python/background-check/code/backgroundcheck_replay/tests/replay_dacx_test.py)
+
```py
@pytest.mark.asyncio
async def test_replay_workflow_history_from_file():
@@ -164,6 +166,7 @@ async def test_replay_workflow_history_from_file():
WorkflowHistory.from_json("backgroundcheck_workflow", history_json)
)
```
+
[WorkflowEnvironment](https://python.temporal.io/temporalio.testing.WorkflowEnvironment.html) is a class in the Temporal Python SDK that provides a testing suite for running Workflows and Activity code.
@@ -294,7 +297,9 @@ The Temporal Python SDK offers deterministic implementations to the following AP
Use the `workflow.logger` API to log from Workflows to avoid seeing repeated logs from the Replay of the Workflow code.
+
[docs/tutorials/python/background-check/code/backgroundcheck_replay/backgroundcheck_dacx.py](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/python/background-check/code/backgroundcheck_replay/backgroundcheck_dacx.py)
+
```py
import asyncio
from datetime import timedelta
@@ -318,6 +323,7 @@ class BackgroundCheck:
schedule_to_close_timeout=timedelta(seconds=5),
)
```
+
### Inspect the new Event History {#inspect-new-event-history}
diff --git a/docs/tutorials/python/background-check/introduction.mdx b/docs/tutorials/python/background-check/introduction.mdx
index e2008f0d..f4e1695a 100644
--- a/docs/tutorials/python/background-check/introduction.mdx
+++ b/docs/tutorials/python/background-check/introduction.mdx
@@ -11,7 +11,6 @@ tags:
- guide-context
---
-
Welcome to Temporal Python SDK Background Check tutorial!
:::info Temporal Python SDK API reference
@@ -137,4 +136,3 @@ Additional Python code samples are in the [temporalio/samples-python](https://gi
The Temporal Python SDK is MIT licensed, and contributions are welcome.
Please review our [contribution guidelines](https://github.com/temporalio/sdk-python#development).
-
diff --git a/docs/tutorials/python/background-check/project-setup.mdx b/docs/tutorials/python/background-check/project-setup.mdx
index 46bd3c81..5e7c3155 100644
--- a/docs/tutorials/python/background-check/project-setup.mdx
+++ b/docs/tutorials/python/background-check/project-setup.mdx
@@ -71,11 +71,11 @@ Reference [the documentation](https://docs.temporal.io/cli) for detailed install
### Install via download
1. Download the version for your OS and architecture:
- - [Linux amd64](https://temporal.download/cli/archive/latest?platform=linux&arch=amd64)
- - [Linux arm64](https://temporal.download/cli/archive/latest?platform=linux&arch=arm64)
- - [macOS amd64](https://temporal.download/cli/archive/latest?platform=darwin&arch=amd64)
- - [macOS arm64](https://temporal.download/cli/archive/latest?platform=darwin&arch=arm64) (Apple silicon)
- - [Windows amd64](https://temporal.download/cli/archive/latest?platform=windows&arch=amd64)
+ - [Linux amd64](https://temporal.download/cli/archive/latest?platform=linux&arch=amd64)
+ - [Linux arm64](https://temporal.download/cli/archive/latest?platform=linux&arch=arm64)
+ - [macOS amd64](https://temporal.download/cli/archive/latest?platform=darwin&arch=amd64)
+ - [macOS arm64](https://temporal.download/cli/archive/latest?platform=darwin&arch=arm64) (Apple silicon)
+ - [Windows amd64](https://temporal.download/cli/archive/latest?platform=windows&arch=amd64)
2. Extract the downloaded archive.
3. Add the `temporal` binary to your `PATH` (`temporal.exe` for Windows).
@@ -90,6 +90,7 @@ Reference [the documentation](https://docs.temporal.io/cli) for detailed install
3. Switch to cloned directory, and run `go build ./cmd/temporal`
:::note
+
- The executable will be at `temporal` (`temporal.exe` for Windows).
Reference [the documentation](https://docs.temporal.io/cli) for detailed usage information.
@@ -308,7 +309,9 @@ In the Temporal Python SDK programming model, a Workflow Definition is defined a
The `BackgroundCheck class` below is an example of a basic Workflow Definition.
+
[docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/workflows/backgroundcheck.py](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/workflows/backgroundcheck.py)
+
```py
from datetime import timedelta
@@ -326,8 +329,8 @@ class BackgroundCheck:
ssn,
schedule_to_close_timeout=timedelta(seconds=5),
)
-
```
+
Use the `@workflow.defn` decorator on the `BackgroundCheck` class to identify a Workflow.
@@ -347,15 +350,17 @@ You can use asynchronous, synchronous multithreaded, and synchronous multiproces
Below is an example of an Activity defined as a function.
+
[docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/activities/ssntraceactivity.py](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/activities/ssntraceactivity.py)
+
```py
from temporalio import activity
@activity.defn
async def ssn_trace_activity(ssn) -> str:
return "pass"
-
```
+
The `ssn_trace_activity` function passes a string and returns `pass`.
@@ -392,7 +397,9 @@ To run a Worker Process with a local development server, define the following st
In regards to organization, we recommend keeping Worker code separate from Workflow and Activity code.
+
[docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/dev_server_worker/main.py](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/dev_server_worker/main.py)
+
```py
import asyncio
@@ -418,8 +425,8 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
-
```
+
### Run a Temporal Cloud Worker {#cloud-worker}
@@ -431,7 +438,9 @@ A Temporal Cloud Worker requires that you specify the following in the Client co
- Certificate and private key associated with the Namespace
+
[docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/cloud_worker/main.py](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/cloud_worker/main.py)
+
```py
import asyncio
import os
@@ -469,8 +478,8 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
-
```
+
To run a Temporal Cloud Worker, you'll change some parameters in your Client connection code, such as updating the namespace and gRPC endpoint.
@@ -550,7 +559,9 @@ Copy the IP address part.
Set IP address, port, and Namespace in the Temporal Client options.
+
[docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/self_hosted_worker/main.py](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/self_hosted_worker/main.py)
+
```py
import asyncio
@@ -576,8 +587,8 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
-
```
+
#### Build and deploy Docker image {#dockerfile}
@@ -802,7 +813,9 @@ Then, it executes the `BackgroundCheck.run` method with a social security number
The test is marked with `@pytest.mark.asyncio` to indicate that it is an asynchronous test.
+
[docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/tests/workflow_test.py](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/tests/workflow_test.py)
+
```py
import uuid
@@ -830,8 +843,8 @@ async def test_execute_workflow():
id=str(uuid.uuid4()),
task_queue=task_queue_name,
)
-
```
+
### Add Activity function tests {#test-activity-code}
@@ -842,7 +855,9 @@ The function takes a social security number as input and returns a string indica
The test checks if the function returns "pass" when given the SSN "55-55-555".
+
[docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/tests/activity_test.py](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/python/background-check/code/backgroundcheck_boilerplate/tests/activity_test.py)
+
```py
import pytest
from temporalio.testing import ActivityEnvironment
@@ -855,6 +870,6 @@ async def test_ssn_trace_activity() -> str:
assert expected_output == await activity_environment.run(
ssn_trace_activity, "55-55-555"
)
-
```
+
diff --git a/docs/tutorials/typescript/background-check/durable-execution.mdx b/docs/tutorials/typescript/background-check/durable-execution.mdx
index c5e85c13..af1236ac 100644
--- a/docs/tutorials/typescript/background-check/durable-execution.mdx
+++ b/docs/tutorials/typescript/background-check/durable-execution.mdx
@@ -143,13 +143,13 @@ If replay fails for any other reason, [ReplayError](https://typescript.temporal.
In the following example, a single Event History is loaded from a JSON file on disk (as obtained from the [Web UI](https://docs.temporal.io/web-ui) or the [Temporal CLI](https://docs.temporal.io/cli/workflow#show)):
```ts
-const filePath = "./history_file.json";
-const history = await JSON.parse(fs.promises.readFile(filePath, "utf8"));
+const filePath = './history_file.json';
+const history = await JSON.parse(fs.promises.readFile(filePath, 'utf8'));
await Worker.runReplayHistory(
{
- workflowsPath: require.resolve("./your/workflows"),
+ workflowsPath: require.resolve('./your/workflows'),
},
- history
+ history,
);
```
@@ -157,14 +157,14 @@ Alternatively, we can download the Event History programmatically using a Client
```ts
const connection = await Connection.connect({ address });
-const client = new Client({ connection, namespace: "your-namespace" });
-const handle = client.workflow.getHandle("your-workflow-id");
+const client = new Client({ connection, namespace: 'your-namespace' });
+const handle = client.workflow.getHandle('your-workflow-id');
const history = await handle.fetchHistory();
await Worker.runReplayHistory(
{
- workflowsPath: require.resolve("./your/workflows"),
+ workflowsPath: require.resolve('./your/workflows'),
},
- history
+ history,
);
```
@@ -181,13 +181,13 @@ const executions = client.workflow.list({
const histories = executions.intoHistories();
const results = Worker.runReplayHistories(
{
- workflowsPath: require.resolve("./your/workflows"),
+ workflowsPath: require.resolve('./your/workflows'),
},
- histories
+ histories,
);
for await (const result of results) {
if (result.error) {
- console.error("Replay failed", result);
+ console.error('Replay failed', result);
}
}
```
@@ -249,23 +249,27 @@ One way to produce a non-deterministic error is to use a random number to determ
Eventually, the way that sleep has been implemented here will produce a non-determinism error.
+
[docs/tutorials/typescript/background-check/code/chapter_durable_execution/backgroundcheck_nondeterministic/src/workflow.ts](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/typescript/background-check/code/chapter_durable_execution/backgroundcheck_nondeterministic/src/workflow.ts)
+
```ts
-import { proxyActivities, log, sleep } from "@temporalio/workflow";
-import type * as activities from "./activities";
+import { log, proxyActivities, sleep } from '@temporalio/workflow';
+import type * as activities from './activities';
const { ssnTraceActivity } = proxyActivities({
- startToCloseTimeout: "10 seconds",
+ startToCloseTimeout: '10 seconds',
});
// backgroundCheckNonDeterministic is an anti-pattern Workflow Definition
-export async function backgroundCheckNonDeterministic(ssn: string): Promise {
+export async function backgroundCheckNonDeterministic(
+ ssn: string,
+): Promise {
// CAUTION, the following code is an anti-pattern showing what NOT to do
if (getRandomNumber(1, 100) > 50) {
- await sleep("10 seconds");
+ await sleep('10 seconds');
}
- log.info("Preparing to run daily report", {});
+ log.info('Preparing to run daily report', {});
try {
const ssnTraceResult = await ssnTraceActivity(ssn);
@@ -281,6 +285,7 @@ function getRandomNumber(min: number, max: number) {
return min + (seed % (max - min + 1));
}
```
+
The Worker logs will show something similar to the following:
@@ -492,19 +497,19 @@ Use the `sleep()` API to cause the Workflow to sleep for a minute before the cal
By using Temporal's logging API, the Worker is able to suppress these log messages during replay so that log statements from the original execution aren't duplicated by the re-execution.
```typescript
-import { log } from "@temporalio/workflow";
-import { proxyActivities, sleep } from "@temporalio/workflow";
-import type * as activities from "./activities"; // Assuming 'activities' is the file containing your activity definitions
+import { log } from '@temporalio/workflow';
+import { proxyActivities, sleep } from '@temporalio/workflow';
+import type * as activities from './activities'; // Assuming 'activities' is the file containing your activity definitions
const { ssnTraceActivity } = proxyActivities({
- startToCloseTimeout: "10 seconds",
+ startToCloseTimeout: '10 seconds',
});
export async function backgroundCheckWorkflow(param: string): Promise {
// Sleep for 1 minute
- log.info("Sleeping for 1 minute...");
+ log.info('Sleeping for 1 minute...');
await sleep(60 * 1000); // sleep for 60 seconds
- log.info("Finished sleeping");
+ log.info('Finished sleeping');
// Execute the SSNTraceActivity synchronously
try {
diff --git a/docs/tutorials/typescript/background-check/introduction.mdx b/docs/tutorials/typescript/background-check/introduction.mdx
index f5bf1f24..147d158b 100644
--- a/docs/tutorials/typescript/background-check/introduction.mdx
+++ b/docs/tutorials/typescript/background-check/introduction.mdx
@@ -11,7 +11,6 @@ tags:
- guide-context
---
-
Welcome to the Temporal TypeScript SDK Background Check tutorial!
:::info Temporal TypeScript SDK API reference
@@ -101,4 +100,3 @@ Further resources for learning how to use the SDK include the following:
The Temporal TypeScript SDK is MIT licensed, and contributions are welcome.
Please review our [contribution guidelines](https://github.com/temporalio/sdk-typescript/blob/main/CONTRIBUTING.md).
-
diff --git a/docs/tutorials/typescript/background-check/project-setup.mdx b/docs/tutorials/typescript/background-check/project-setup.mdx
index a88c8866..1119119e 100644
--- a/docs/tutorials/typescript/background-check/project-setup.mdx
+++ b/docs/tutorials/typescript/background-check/project-setup.mdx
@@ -92,11 +92,11 @@ Reference [the documentation](https://docs.temporal.io/cli) for detailed install
### Install via download
1. Download the version for your OS and architecture:
- - [Linux amd64](https://temporal.download/cli/archive/latest?platform=linux&arch=amd64)
- - [Linux arm64](https://temporal.download/cli/archive/latest?platform=linux&arch=arm64)
- - [macOS amd64](https://temporal.download/cli/archive/latest?platform=darwin&arch=amd64)
- - [macOS arm64](https://temporal.download/cli/archive/latest?platform=darwin&arch=arm64) (Apple silicon)
- - [Windows amd64](https://temporal.download/cli/archive/latest?platform=windows&arch=amd64)
+ - [Linux amd64](https://temporal.download/cli/archive/latest?platform=linux&arch=amd64)
+ - [Linux arm64](https://temporal.download/cli/archive/latest?platform=linux&arch=arm64)
+ - [macOS amd64](https://temporal.download/cli/archive/latest?platform=darwin&arch=amd64)
+ - [macOS arm64](https://temporal.download/cli/archive/latest?platform=darwin&arch=arm64) (Apple silicon)
+ - [Windows amd64](https://temporal.download/cli/archive/latest?platform=windows&arch=amd64)
2. Extract the downloaded archive.
3. Add the `temporal` binary to your `PATH` (`temporal.exe` for Windows).
@@ -111,6 +111,7 @@ Reference [the documentation](https://docs.temporal.io/cli) for detailed install
3. Switch to cloned directory, and run `go build ./cmd/temporal`
:::note
+
- The executable will be at `temporal` (`temporal.exe` for Windows).
Reference [the documentation](https://docs.temporal.io/cli) for detailed usage information.
@@ -387,7 +388,9 @@ Define the Activity Execution options. `StartToCloseTimeout` or `ScheduleToClose
The `backgroundCheck` function that follows is an example of a basic Workflow Definition.
+
[docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/workflows.ts](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/workflows.ts)
+
```ts
import * as workflow from '@temporalio/workflow';
import type * as activities from './activities';
@@ -400,6 +403,7 @@ export async function backgroundCheck(ssn: string): Promise {
return await ssnTrace(ssn);
}
```
+
Temporal Workflows may have any number of custom parameters. However, we
@@ -445,7 +449,9 @@ You'll define your Activities in this file.
Add the following code to define your Activity:
+
[docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/activities.ts](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/activities.ts)
+
```ts
export async function ssnTrace(param: string): Promise {
// This is where a call to another service is made
@@ -453,6 +459,7 @@ export async function ssnTrace(param: string): Promise {
return 'pass';
}
```
+
This Activity definition uses a single input parameter and returns a string.
@@ -477,7 +484,9 @@ In regards to organization, we recommend keeping Worker code separate from Workf
Add the following code to `src/worker.ts` to define a worker process that communicates with a local development server:
+
[docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/worker.ts](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/worker.ts)
+
```ts
import { NativeConnection, Worker } from '@temporalio/worker';
import * as activities from './activities';
@@ -517,8 +526,8 @@ run().catch((err) => {
console.error(err);
process.exit(1);
});
-
```
+
:::info Auto restart Worker when code changes
@@ -543,11 +552,13 @@ Add the following code to `src/worker.ts` to define a worker process that commun
configuration provided via environment variables:
+
[docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/worker-cloud.ts](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/worker-cloud.ts)
+
```ts
import fs from 'fs/promises';
-import { Worker, NativeConnection } from '@temporalio/worker';
+import { NativeConnection, Worker } from '@temporalio/worker';
import * as activities from './activities';
// Note that serverNameOverride and serverRootCACertificate are optional.
@@ -625,8 +636,8 @@ export function getEnv(): Env {
taskQueue: process.env.TEMPORAL_TASK_QUEUE || 'hello-world-mtls',
};
}
-
```
+
To run a Temporal Cloud Worker, you'll change some parameters in your Client connection code, such as updating the namespace and gRPC endpoint.
@@ -710,7 +721,9 @@ To use a Worker with a self-hosted Temporal Cluster, set the IP address, port, a
Add the following code to `src/worker.ts` to define a worker process that communicates with a self-hosted Temporal cluster using a specific namespace and IP address:
+
[docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/worker-self-hosted.ts](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/worker-self-hosted.ts)
+
```ts
import { NativeConnection, Worker } from '@temporalio/worker';
import * as activities from './activities';
@@ -742,8 +755,8 @@ run().catch((err) => {
console.error(err);
process.exit(1);
});
-
```
+
#### Build and deploy Docker image {#dockerfile}
@@ -987,13 +1000,15 @@ You can test Workflow code for the following conditions:
Add the following code to `src/mocha/backgroundcheck.test.ts` to test that the Workflow executes successfully.
+
[docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/mocha/backgroundcheck.test.ts](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/mocha/backgroundcheck.test.ts)
+
```ts
import { TestWorkflowEnvironment } from '@temporalio/testing';
-import { before, describe, it } from 'mocha';
import { Worker } from '@temporalio/worker';
-import { backgroundCheck } from '../workflows';
import assert from 'assert';
+import { before, describe, it } from 'mocha';
+import { backgroundCheck } from '../workflows';
describe('Background check workflow', () => {
let testEnv: TestWorkflowEnvironment;
@@ -1030,8 +1045,8 @@ describe('Background check workflow', () => {
assert.equal(result, 'pass');
});
});
-
```
+
This test uses a local testing server that ships with the Temporal TypeScript SDK.
@@ -1059,12 +1074,14 @@ Add the following code to `src/mocha/ssntrace.test.ts` to test the `ssnTrace`
Activity and ensure it returns the expected value:
+
[docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/mocha/ssntrace.test.ts](https://github.com/temporalio/temporal-learning/blob/main/docs/tutorials/typescript/background-check/code/chapter_project_setup/backgroundcheck/src/mocha/ssntrace.test.ts)
+
```ts
import { MockActivityEnvironment } from '@temporalio/testing';
+import assert from 'assert';
import { describe, it } from 'mocha';
import * as activities from '../activities';
-import assert from 'assert';
describe('ssnTrace activity', async () => {
it('successfully passes the ssn trace', async () => {
@@ -1074,8 +1091,8 @@ describe('ssnTrace activity', async () => {
assert.equal(result, 'pass');
});
});
-
```
+
## Conclusion {#conclusion}
diff --git a/docs/tutorials/typescript/work-queue-slack-app/build/index.mdx b/docs/tutorials/typescript/work-queue-slack-app/build/index.mdx
index 4db89dad..e99d6483 100644
--- a/docs/tutorials/typescript/work-queue-slack-app/build/index.mdx
+++ b/docs/tutorials/typescript/work-queue-slack-app/build/index.mdx
@@ -264,7 +264,9 @@ Next, define the common types used across the application.
Create a file `types.ts` in the `common-types` directory and define a Work Item data object and its statuses:
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/common-types/types.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/common-types/types.ts)
+
```ts
export interface WorkqueueData {
id: string;
@@ -284,6 +286,7 @@ export enum WorkqueueStatus {
Done = 3,
}
```
+
Now that that is set up, you can start building the Work Queue Workflow.
@@ -322,20 +325,22 @@ As you add and remove work items from the Work Queue, the Event History grows.
When you continue the Workflow as a new one, you will pass the latest Work Queue data to the new Workflow instance, leaving the old Event History behind, but retaining the state of the Work Queue.
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/workflows/workqueue.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/workflows/workqueue.ts)
+
```ts
import {
- isCancellation,
+ condition,
continueAsNew,
+ isCancellation,
workflowInfo,
- condition,
-// ...
-} from "@temporalio/workflow";
-import {WorkqueueData} from "../../../common-types/types";
+ // ...
+} from '@temporalio/workflow';
+import { WorkqueueData } from '../../../common-types/types';
// ...
export async function workqueue(existingData?: WorkqueueData[]): Promise {
const wqdata: WorkqueueData[] = existingData ?? [];
-// ...
+ // ...
try {
// Await until suggestion to Continue-As-New due to History size
// If a Cancellation request exists, the condition call will throw the Cancellation error
@@ -353,6 +358,7 @@ export async function workqueue(existingData?: WorkqueueData[]): Promise {
await continueAsNew(wqdata);
}
```
+
What's also handy about the `condition` API is that if there is a Cancellation request, the condition call will throw a Cancellation error.
@@ -373,26 +379,32 @@ You will use a Query to get the current state of the Work Queue.
It is a good practice to define the Signals and Queries outside of the Workflow and handle them right after declaring local state variables within the Workflow.
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/workflows/workqueue.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/workflows/workqueue.ts)
+
```ts
import {
-// ...
+ // ...
defineQuery,
defineSignal,
setHandler,
-} from "@temporalio/workflow";
+} from '@temporalio/workflow';
// ...
-export const getWorkqueueDataQuery =
- defineQuery("getWorkqueueData");
-export const addWorkToQueueSignal =
- defineSignal<[WorkqueueData]>("addWorkqueueData");
-export const claimWorkSignal =
- defineSignal<[{workId: string; claimantId: string}]>("claimWork");
-export const completeWorkSignal =
- defineSignal<[{workId: string}]>("completeWork");
+export const getWorkqueueDataQuery = defineQuery(
+ 'getWorkqueueData',
+);
+export const addWorkToQueueSignal = defineSignal<[WorkqueueData]>(
+ 'addWorkqueueData',
+);
+export const claimWorkSignal = defineSignal<
+ [{ workId: string; claimantId: string }]
+>('claimWork');
+export const completeWorkSignal = defineSignal<[{ workId: string }]>(
+ 'completeWork',
+);
export async function workqueue(existingData?: WorkqueueData[]): Promise {
-// ...
+ // ...
// Register a Query handler for 'getWorkqueueData'
setHandler(getWorkqueueDataQuery, () => {
return wqdata;
@@ -404,7 +416,7 @@ export async function workqueue(existingData?: WorkqueueData[]): Promise {
});
// Register Signal handler for claiming work
- setHandler(claimWorkSignal, ({workId, claimantId}) => {
+ setHandler(claimWorkSignal, ({ workId, claimantId }) => {
const workItem = wqdata.find((item) => item.id === workId);
if (workItem) {
workItem.claimantId = claimantId;
@@ -413,15 +425,16 @@ export async function workqueue(existingData?: WorkqueueData[]): Promise {
});
// Register Signal handler for completing work
- setHandler(completeWorkSignal, ({workId}) => {
+ setHandler(completeWorkSignal, ({ workId }) => {
const index = wqdata.findIndex((item) => item.id === workId);
if (index !== -1) {
wqdata.splice(index, 1);
}
});
-// ...
+ // ...
}
```
+
Now, register your Workflow with a Temporal Worker.
@@ -433,17 +446,19 @@ You need the Worker code to run your Workflow code.
If you don't already have it, create `worker.ts` inside of `temporal-application/src` and add the following code:
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/dev-worker.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/dev-worker.ts)
+
```ts
-import "dotenv/config";
-import path from "path";
-import {Worker, NativeConnection} from "@temporalio/worker";
+import 'dotenv/config';
+import { NativeConnection, Worker } from '@temporalio/worker';
+import path from 'path';
async function run() {
try {
const worker = await Worker.create({
- namespace: process.env.TEMPORAL_DEV_NAMESPACE || "",
- workflowsPath: path.resolve(__dirname, "./workflows"),
+ namespace: process.env.TEMPORAL_DEV_NAMESPACE || '',
+ workflowsPath: path.resolve(__dirname, './workflows'),
taskQueue: `${process.env.ENV}-temporal-iq-task-queue`,
});
@@ -456,6 +471,7 @@ async function run() {
run();
```
+
Make sure your `package.json` file in the `temporal-application` project has a script to run the Worker:
@@ -494,10 +510,12 @@ Your main `slack_bot.ts` file will initialize the Slack App and the Temporal Cli
First, you will need to create and export a Temporal Client in `bot/modules/temporal-client.ts`.
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/dev-temporal-client.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/dev-temporal-client.ts)
+
```ts
-import "dotenv/config";
-import {Client, Connection} from "@temporalio/client";
+import 'dotenv/config';
+import { Client, Connection } from '@temporalio/client';
export let temporalClient: Client;
@@ -510,6 +528,7 @@ export async function initializeTemporalClient() {
});
}
```
+
Now, you can initialize the Slack App in `bot/slack_bot.ts`.
@@ -517,14 +536,16 @@ Now, you can initialize the Slack App in `bot/slack_bot.ts`.
In the root of the `bot` project, create a file called `slack_bot.ts` and initialize the Slack bot, making sure to import and initialize the Temporal Client module:
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/bot/slack_bot.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/bot/slack_bot.ts)
+
```ts
-import "dotenv/config";
+import 'dotenv/config';
import {
App,
-// ...
-} from "@slack/bolt";
-import {initializeTemporalClient} from "./modules/dev-temporal-client";
+ // ...
+} from '@slack/bolt';
+import { initializeTemporalClient } from './modules/dev-temporal-client';
// ...
// Initializes your app with your bot token, app token, and signing secret
const app = new App({
@@ -535,11 +556,11 @@ const app = new App({
});
// ...
// Register Slack bot error handler
-app.error(async ({error}: {error: Error}) => {
+app.error(async ({ error }: { error: Error }) => {
if (error instanceof Error) {
console.error(`Error: ${error.name}, Message: ${error.message}`);
} else {
- console.error("An unknown error occurred", error);
+ console.error('An unknown error occurred', error);
}
});
@@ -548,12 +569,13 @@ app.error(async ({error}: {error: Error}) => {
try {
await app.start();
await initializeTemporalClient();
- console.log("⚡️ Bolt app is running!");
+ console.log('⚡️ Bolt app is running!');
} catch (error) {
- console.error("Failed to start Bolt app:", error);
+ console.error('Failed to start Bolt app:', error);
}
})();
```
+
Now, you can create the `workqueue` module that interact with the Work Queue Workflow.
@@ -564,31 +586,33 @@ This is where a majority of the Slack Command, work claiming, and work completin
Here you will export a function that looks at the command text and decides what to do based on the text.
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/workqueue.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/workqueue.ts)
+
```ts
// ...
import {
- SayFn,
RespondFn,
+ SayFn,
SlackCommandMiddlewareArgs,
+ // ...
+} from '@slack/bolt';
+import { WorkqueueData, WorkqueueStatus } from '../../common-types/types';
+import { temporalClient } from './dev-temporal-client';
// ...
-} from "@slack/bolt";
-import {WorkqueueData, WorkqueueStatus} from "../../common-types/types";
-import {temporalClient} from "./dev-temporal-client";
-// ...
-import {WorkflowExecutionAlreadyStartedError} from "@temporalio/client";
+import { WorkflowExecutionAlreadyStartedError } from '@temporalio/client';
// ...
// Handles and routes all incoming Work Queue Slash Commands
export async function handleWorkqueueCommand(
- command: SlackCommandMiddlewareArgs["command"],
+ command: SlackCommandMiddlewareArgs['command'],
say: SayFn,
- respond: RespondFn
+ respond: RespondFn,
) {
const commandText = command.text?.trim();
- if (commandText === "!delete") {
+ if (commandText === '!delete') {
await deleteWorkqueue(command, say);
- } else if (commandText === "") {
+ } else if (commandText === '') {
await displayWorkQueue(command, respond);
} else {
await addWorkToQueue(command, say);
@@ -596,6 +620,7 @@ export async function handleWorkqueueCommand(
return;
}
```
+
In the preceeding snippet you can see that the there are three possible ways to use the `workqueue` Slash Command.
@@ -614,14 +639,16 @@ If it does, then in this case you will just ignore the error and Query the Workf
Define three functions, `displayWorkQueue`, `createNewWorkqueue`, and `queryWorkqueue` in the `workqueue.ts` module.
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/workqueue.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/workqueue.ts)
+
```ts
// ...
// Display the Work Queue for the channel
// Creates a new Work Queue if it does not exist
async function displayWorkQueue(
- command: SlackCommandMiddlewareArgs["command"],
- respond: RespondFn
+ command: SlackCommandMiddlewareArgs['command'],
+ respond: RespondFn,
) {
// Get the channel name in plain text
const channelName = command.channel_name;
@@ -631,21 +658,21 @@ async function displayWorkQueue(
const data = await queryWorkQueue(channelName, respond);
await replyEphemeral(
respond,
- "Work Queue cannot display",
- formatWorkqueueDataForSlack(channelName, data)
+ 'Work Queue cannot display',
+ formatWorkqueueDataForSlack(channelName, data),
);
}
// Create a new Work Queue for the channel if one does not exist
async function createNewWorkQueue(workflowid: string): Promise {
try {
- await temporalClient.workflow.start("workqueue", {
+ await temporalClient.workflow.start('workqueue', {
taskQueue: `${process.env.ENV}-temporal-iq-task-queue`,
workflowId: workflowid,
});
} catch (e) {
if (e instanceof WorkflowExecutionAlreadyStartedError) {
- console.log("Workflow already started");
+ console.log('Workflow already started');
} else {
throw e;
}
@@ -655,20 +682,21 @@ async function createNewWorkQueue(workflowid: string): Promise {
// Read the state of the Work Queue for the channel using a Query
async function queryWorkQueue(
workflowId: string,
- say: SayFn
+ say: SayFn,
): Promise {
try {
const handle = temporalClient.workflow.getHandle(workflowId);
const result = await handle.query(getWorkqueueDataQuery);
- console.log("Current workqueue data:", result);
+ console.log('Current workqueue data:', result);
return result;
} catch (error) {
- console.error("Error querying workqueue data:", error);
- await say("An error occurred while Querying the Work Queue.");
+ console.error('Error querying workqueue data:', error);
+ await say('An error occurred while Querying the Work Queue.');
return [];
}
}
```
+
In the preceding snippet, the `createNewWorkqueue` function attempts to start a new Work Queue Workflow.
@@ -684,13 +712,15 @@ This function needs to build the Work Item data object and call another function
Click the link at the top of the code snippet to visit the source code and see the full code implementation for building the Work Item data object.
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/workqueue.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/workqueue.ts)
+
```ts
// ...
// Add work to the queue using a Signal
async function addWorkToQueue(
- command: SlackCommandMiddlewareArgs["command"],
- say: SayFn
+ command: SlackCommandMiddlewareArgs['command'],
+ say: SayFn,
) {
// Get the channel name in plain text
const channelId = command.channel_id;
@@ -703,18 +733,19 @@ async function addWorkToQueue(
// ...
async function signalAddWork(params: WorkqueueData, say: SayFn): Promise {
try {
- await temporalClient.workflow.signalWithStart("workqueue", {
+ await temporalClient.workflow.signalWithStart('workqueue', {
workflowId: params.channelName,
taskQueue: `${process.env.ENV}-temporal-iq-task-queue`,
signal: addWorkToQueueSignal,
signalArgs: [params],
});
} catch (error) {
- console.error("Error signaling workqueue data:", error);
- await say("An error occurred while Signaling the Work Queue.");
+ console.error('Error signaling workqueue data:', error);
+ await say('An error occurred while Signaling the Work Queue.');
}
}
```
+
The key part of this functionality is using the Temporal Client's `signalWithStart` API.
@@ -726,39 +757,44 @@ Next, implement the functionality that will allow a user to claim a work item fr
In the `slack_bot.ts` file, you will need to add a listener for the `wq_claim` button click event.
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/bot/slack_bot.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/bot/slack_bot.ts)
+
```ts
// ...
import {
-// ...
+ // ...
signalClaimWork,
-// ...
-} from "./modules/workqueue";
+ // ...
+} from './modules/workqueue';
// ...
// Listen for Work Item Claim
app.action>(
- "wq_claim",
- async ({ack, say, body}) => {
+ 'wq_claim',
+ async ({ ack, say, body }) => {
await ack();
// Ensure the body.actions[0] is a ButtonAction
const action = body.actions[0] as ButtonAction;
if (action.value) {
- const [channelName, workId, userId] = action.value.split("_");
+ const [channelName, workId, userId] = action.value.split('_');
const claimantId = body.user.id;
// Send signal to the Temporal workflow to claim the work
await signalClaimWork(channelName, workId, claimantId, userId, say);
} else {
- console.error("Action value is undefined.");
+ console.error('Action value is undefined.');
}
- }
+ },
);
```
+
Then, in `workqueue.ts` module, define a `claimWork` function that sends a Signal to the Work Queue Workflow to claim the work item.
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/workqueue.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/workqueue.ts)
+
```ts
// ...
export async function signalClaimWork(
@@ -766,21 +802,22 @@ export async function signalClaimWork(
workId: string,
claimantId: string,
userId: string,
- say: SayFn
+ say: SayFn,
) {
try {
const handle = temporalClient.workflow.getHandle(channelName);
- await handle.signal(claimWorkSignal, {workId, claimantId});
+ await handle.signal(claimWorkSignal, { workId, claimantId });
console.log(`Work item ${workId} claimed by ${claimantId}`);
await reply(
say,
- `<@${userId}> Work item ${workId} claimed by <@${claimantId}>.`
+ `<@${userId}> Work item ${workId} claimed by <@${claimantId}>.`,
);
} catch (error) {
- console.error("Failed to signal claim work:", error);
+ console.error('Failed to signal claim work:', error);
}
}
```
+
When someone finishes working on the task they will need to be able to mark it as complete.
@@ -788,37 +825,42 @@ When someone finishes working on the task they will need to be able to mark it a
In the `slack_bot.ts` file, you will need to add a listener for the`wq_complete` button click event.
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/bot/slack_bot.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/bot/slack_bot.ts)
+
```ts
// ...
import {
-// ...
+ // ...
signalCompleteWork,
-} from "./modules/workqueue";
+} from './modules/workqueue';
// ...
// Listen for Work Item Completion
app.action>(
- "wq_complete",
- async ({ack, say, body}) => {
+ 'wq_complete',
+ async ({ ack, say, body }) => {
await ack();
const action = body.actions[0] as ButtonAction;
if (action.value) {
- const [channelName, workId, userId] = action.value.split("_");
+ const [channelName, workId, userId] = action.value.split('_');
const message = body.message as GenericMessageEvent;
// Send signal to the Temporal workflow to complete the work
await signalCompleteWork(channelName, workId, message, userId, say);
} else {
- console.error("Action value is undefined.");
+ console.error('Action value is undefined.');
}
- }
+ },
);
```
+
Then, in the `workqueue.ts` module, define a function `completeWork` that sends a Signal to the Work Queue Workflow to mark the work item as complete.
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/workqueue.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/workqueue.ts)
+
```ts
// ...
export async function signalCompleteWork(
@@ -826,18 +868,19 @@ export async function signalCompleteWork(
workId: string,
message: GenericMessageEvent,
userId: string,
- say: SayFn
+ say: SayFn,
) {
try {
const handle = temporalClient.workflow.getHandle(channelId);
- await handle.signal(completeWorkSignal, {workId});
+ await handle.signal(completeWorkSignal, { workId });
console.log(`Work item ${workId} marked as complete`);
await reply(say, `<@${userId}> Work item ${workId} marked as complete.`);
} catch (error) {
- console.error("Failed to signal complete work:", error);
+ console.error('Failed to signal complete work:', error);
}
}
```
+
Lastly, you will want to have the compatibility to delete a Work Queue for the channel.
@@ -848,13 +891,15 @@ To send a Cancellation Request, in the `workqueue.ts` module, define a function
This Slack App assumes that the Slack channel name is unique and therefor can be used as the Workflow ID.
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/workqueue.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/workqueue.ts)
+
```ts
// ...
// Delete the Work Queue for the channel with a Cancellation Request
export async function deleteWorkqueue(
- command: SlackCommandMiddlewareArgs["command"],
- say: SayFn
+ command: SlackCommandMiddlewareArgs['command'],
+ say: SayFn,
): Promise {
const workflowId = command.channel_name;
try {
@@ -868,6 +913,7 @@ export async function deleteWorkqueue(
}
}
```
+
By using the Slack channel name as the Workflow ID, you can tell which Workflow corresponds to which channel in the Temporal UI if you need to do any debugging.
@@ -929,18 +975,20 @@ The Temporal TypeScript SDK comes equipped with a Test Suite and a pattern for t
Set up the Test Suite like this:
-[docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/__tests__/workqueue.test.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/__tests__/workqueue.test.ts)
+
+[docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/**tests**/workqueue.test.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/__tests__/workqueue.test.ts)
+
```ts
-import {TestWorkflowEnvironment} from "@temporalio/testing";
-import {WorkflowCoverage} from "@temporalio/nyc-test-coverage";
-import {Worker, Runtime, DefaultLogger} from "@temporalio/worker";
+import { WorkflowCoverage } from '@temporalio/nyc-test-coverage';
+import { TestWorkflowEnvironment } from '@temporalio/testing';
+import { DefaultLogger, Runtime, Worker } from '@temporalio/worker';
// ...
-describe("Work Queue Workflow", () => {
+describe('Work Queue Workflow', () => {
let testEnv: TestWorkflowEnvironment;
const workflowCoverage = new WorkflowCoverage();
beforeAll(async () => {
- Runtime.install({logger: new DefaultLogger("WARN")});
+ Runtime.install({ logger: new DefaultLogger('WARN') });
testEnv = await TestWorkflowEnvironment.createLocal();
});
@@ -951,9 +999,10 @@ describe("Work Queue Workflow", () => {
afterAll(() => {
workflowCoverage.mergeIntoGlobalCoverage();
});
-// ...
+ // ...
});
```
+
You can test for many scenarios.
@@ -967,40 +1016,43 @@ For example, you could test for the following:
The basic pattern to test adding work to the Work Queue looks like this:
-[docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/__tests__/workqueue.test.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/__tests__/workqueue.test.ts)
+
+[docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/**tests**/workqueue.test.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/__tests__/workqueue.test.ts)
+
```ts
// ...
- test("should add work to the queue", async () => {
- // Get a test environment Temporal Client
- const {client, nativeConnection} = testEnv;
- // Create a test environment Worker
- const worker = await Worker.create(
- workflowCoverage.augmentWorkerOptions({
- connection: nativeConnection,
- taskQueue: "test",
- workflowsPath: require.resolve("../workflows"),
- })
- );
-// ...
- // Run the Worker
- await worker.runUntil(async () => {
- const handle = await client.workflow.start(workqueue, {
- args: [],
- workflowId: workflowId,
- taskQueue: "test",
- });
- const workItem: WorkqueueData = {
-// ...
- };
- // Add work to the queue
- await handle.signal(addWorkToQueueSignal, workItem);
- // Check to see if the data is there
- const result = await handle.query(getWorkqueueDataQuery);
- // Compare the data
- expect(result).toContainEqual(workItem);
+test('should add work to the queue', async () => {
+ // Get a test environment Temporal Client
+ const { client, nativeConnection } = testEnv;
+ // Create a test environment Worker
+ const worker = await Worker.create(
+ workflowCoverage.augmentWorkerOptions({
+ connection: nativeConnection,
+ taskQueue: 'test',
+ workflowsPath: require.resolve('../workflows'),
+ }),
+ );
+ // ...
+ // Run the Worker
+ await worker.runUntil(async () => {
+ const handle = await client.workflow.start(workqueue, {
+ args: [],
+ workflowId: workflowId,
+ taskQueue: 'test',
});
+ const workItem: WorkqueueData = {
+ // ...
+ };
+ // Add work to the queue
+ await handle.signal(addWorkToQueueSignal, workItem);
+ // Check to see if the data is there
+ const result = await handle.query(getWorkqueueDataQuery);
+ // Compare the data
+ expect(result).toContainEqual(workItem);
});
+});
```
+
For more test examples, see the Work Queue Workflow test file by clicking the link at the top of the preceding code snippet.
diff --git a/docs/tutorials/typescript/work-queue-slack-app/deploy/index.mdx b/docs/tutorials/typescript/work-queue-slack-app/deploy/index.mdx
index 2d88449e..02c2f3e9 100644
--- a/docs/tutorials/typescript/work-queue-slack-app/deploy/index.mdx
+++ b/docs/tutorials/typescript/work-queue-slack-app/deploy/index.mdx
@@ -81,10 +81,12 @@ You will need to update your Temporal Client and your Temporal Worker code.
When developing locally, your Temporal Client, located in `bot/modules/temporal-client.ts`, looks like this:
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/dev-temporal-client.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/dev-temporal-client.ts)
+
```ts
-import "dotenv/config";
-import {Client, Connection} from "@temporalio/client";
+import 'dotenv/config';
+import { Client, Connection } from '@temporalio/client';
export let temporalClient: Client;
@@ -97,22 +99,25 @@ export async function initializeTemporalClient() {
});
}
```
+
To use Temporal Cloud, change the Temporal Client code to read your Namespace certificate key and pem env variables.
Then change the connection object to includes the Namespace and certificate information:
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/cloud-temporal-client.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/bot/modules/cloud-temporal-client.ts)
+
```ts
-import "dotenv/config";
-import {Client, Connection} from "@temporalio/client";
+import 'dotenv/config';
+import { Client, Connection } from '@temporalio/client';
export let temporalClient: Client;
export async function initializeTemporalClient() {
- const key = Buffer.from(process.env.TEMPORAL_CLOUD_PRIVATE_KEY!, "utf-8");
- const cert = Buffer.from(process.env.TEMPORAL_CLOUD_PEM!, "utf-8");
+ const key = Buffer.from(process.env.TEMPORAL_CLOUD_PRIVATE_KEY!, 'utf-8');
+ const cert = Buffer.from(process.env.TEMPORAL_CLOUD_PEM!, 'utf-8');
const address = process.env.TEMPORAL_CLOUD_ADDRESS!;
const namespace = process.env.TEMPORAL_CLOUD_NAMESPACE!;
const connection = await Connection.connect({
@@ -131,6 +136,7 @@ export async function initializeTemporalClient() {
});
}
```
+
Then update the code for the Temporal Worker to change how it connects.
@@ -138,17 +144,19 @@ Then update the code for the Temporal Worker to change how it connects.
When developing locally, your Temporal Worker, located in `temporal-application/src/worker.ts`, looks like this:
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/dev-worker.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/dev-worker.ts)
+
```ts
-import "dotenv/config";
-import path from "path";
-import {Worker, NativeConnection} from "@temporalio/worker";
+import 'dotenv/config';
+import { NativeConnection, Worker } from '@temporalio/worker';
+import path from 'path';
async function run() {
try {
const worker = await Worker.create({
- namespace: process.env.TEMPORAL_DEV_NAMESPACE || "",
- workflowsPath: path.resolve(__dirname, "./workflows"),
+ namespace: process.env.TEMPORAL_DEV_NAMESPACE || '',
+ workflowsPath: path.resolve(__dirname, './workflows'),
taskQueue: `${process.env.ENV}-temporal-iq-task-queue`,
});
@@ -161,6 +169,7 @@ async function run() {
run();
```
+
To use Temporal Cloud, you'll change the connection information for your Worker in the same way you changed your client.
@@ -168,21 +177,23 @@ Read the certificate env variables and update the connection object to include t
Alter the `worker.ts` file so it looks like the following:
+
[docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/cloud-worker.ts](https://github.com/temporalio/temporal-learning/blob/edu-2636-workqueue-slackbot-tut/docs/tutorials/typescript/work-queue-slack-app/build/code/temporal-application/src/cloud-worker.ts)
+
```ts
-import "dotenv/config";
-import path from "path";
-import {Worker, NativeConnection} from "@temporalio/worker";
+import 'dotenv/config';
+import { NativeConnection, Worker } from '@temporalio/worker';
+import path from 'path';
async function run() {
try {
const key = Buffer.from(
- process.env.TEMPORAL_CLOUD_PRIVATE_KEY || "",
- "utf-8"
+ process.env.TEMPORAL_CLOUD_PRIVATE_KEY || '',
+ 'utf-8',
);
- const cert = Buffer.from(process.env.TEMPORAL_CLOUD_PEM || "", "utf-8");
+ const cert = Buffer.from(process.env.TEMPORAL_CLOUD_PEM || '', 'utf-8');
const connection = await NativeConnection.connect({
- address: process.env.TEMPORAL_CLOUD_ADDRESS || "",
+ address: process.env.TEMPORAL_CLOUD_ADDRESS || '',
tls: {
clientCertPair: {
crt: cert,
@@ -193,8 +204,8 @@ async function run() {
const worker = await Worker.create({
connection,
- namespace: process.env.TEMPORAL_CLOUD_NAMESPACE || "",
- workflowsPath: path.resolve(__dirname, "./workflows"),
+ namespace: process.env.TEMPORAL_CLOUD_NAMESPACE || '',
+ workflowsPath: path.resolve(__dirname, './workflows'),
taskQueue: `${process.env.ENV}-temporal-iq-task-queue`,
});
@@ -207,6 +218,7 @@ async function run() {
run();
```
+
You can now run your application locally to ensure it works with Temporal Cloud.
diff --git a/docsync.sh b/docsync.sh
deleted file mode 100644
index dc83d6cd..00000000
--- a/docsync.sh
+++ /dev/null
@@ -1,569 +0,0 @@
-#va!/usr/bin/env bash
-
-# Go prereqs
-
-mkdir -p docs/getting_started/go/dev_environment/
-cp ~/dev/documentation/docs/go/tutorial-prerequisites.md docs/getting_started/go/dev_environment/index.md2
-
-sed -e '/^id\:/a\
-sidebar_position: 1'\
- -e 's|/go/|https://docs.temporal.io/go/|g' \
- -e 's/^title:.*/title: Set up a Local Development Environment for Temporal and Go/g' \
- -e '/^id\:/a\
-description: Set up a local development environment for developing Temporal applications using the Go programming language.' \
- -e '/^sidebar_label/d' \
- -e 's|^id:.*|id: go-dev-env|' \
- -e 's|/clusters/|https://docs.temporal.io/clusters/|g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, development environment]' \
- -e '/^id\:/a\
-tags: [Go, SDK, development environment]' \
- -e '/^id\:/a\
-last_update:'\
- -e '/^id\:/a\
- date: 2021-10-01' \
-docs/getting_started/go/dev_environment/index.md2 > docs/getting_started/go/dev_environment/index.md
-rm docs/getting_started/go/dev_environment/index.md2
-
-
-# first_program
-# go
-mkdir -p docs/getting_started/go/first_program_in_go/images/
-cp -r ~/dev/documentation/static/img/tutorials/go/run-your-first-app-tutorial/* docs/getting_started/go/first_program_in_go/images/
-cp ~/dev/documentation/docs/go/run-your-first-app-tutorial.md docs/getting_started/go/first_program_in_go/index_tmp.md
-sed -e '/^id\:/a\
-sidebar_position: 2'\
- -e '/^id\:/a\
-description: In this tutorial you will run your first Temporal app using the Go SDK' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e '/^id\:/a\
-tags: [Go, SDK]' \
- -e 's|/img/tutorials/go/run-your-first-app-tutorial/|images/|g' \
- -e 's|../../src/components|@site/src/components|g' \
- -e '/^sidebar_label/d' \
- -e '/Keep reading or follow along with this video walkthrough:/d' \
- -e '/ docs/getting_started/go/first_program_in_go/index.md
- rm docs/getting_started/go/first_program_in_go/index_tmp.md
-
-# hello world
-mkdir -p docs/getting_started/go/hello_world_in_go/images/
-cp ~/dev/documentation/docs/go/hello-world-tutorial.md docs/getting_started/go/hello_world_in_go/index_tmp.md
-sed -e '/^id\:/a\
-sidebar_position: 2' \
- -e '/^id\:/a\
-description: In this tutorial you will build your first Temporal app using the Go SDK' \
- -e '/^id\:/a\
-keywords: [golang,go,temporal,sdk,tutorial]' \
- -e '/^sidebar_label/d' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/concepts/|https://docs.temporal.io/concepts/|g' \
- -e 's|/application-development-guide|https://docs.temporal.io/application-development-guide|g' \
- -e 's|/go/|https://docs.temporal.io/go/|g' \
- -e 's|^##.*Lore check$|## Review|' \
- -e '/^id\:/a\
-last_update:'\
- -e '/^id\:/a\
- date: 2021-10-01' \
- docs/getting_started/go/hello_world_in_go/index_tmp.md > docs/getting_started/go/hello_world_in_go/index.md
-rm docs/getting_started/go/hello_world_in_go/index_tmp.md
-
-# Java
-
-# Prereqs
-
-mkdir -p docs/getting_started/java/dev_environment/
-cp ~/dev/documentation/docs/java/tutorial-prerequisites.md docs/getting_started/java/dev_environment/index.md2
-
-sed -e '/^id\:/a\
-sidebar_position: 1'\
- -e 's|/go/|https://docs.temporal.io/go/|g' \
- -e 's/^title:.*/title: Set up a Local Development Environment for Temporal and Java/g' \
- -e '/^sidebar_label/d' \
- -e 's|^id:.*|id: java-dev-env|' \
- -e 's|/clusters/|https://docs.temporal.io/clusters/|g' \
- -e '/^id\:/a\
-description: Set up a local development environment for developing Temporal applications using the Java programming language.' \
- -e '/^id\:/a\
-tags: [Java, SDK, development environment]' \
- -e '/^id\:/a\
-keywords: [Java, JRE, Temporal, IntelliJ, Gradle, development environment]' \
- -e '/^id\:/a\
-last_update:'\
- -e '/^id\:/a\
- date: 2021-10-01' \
-docs/getting_started/java/dev_environment/index.md2 > docs/getting_started/java/dev_environment/index.md
-rm docs/getting_started/java/dev_environment/index.md2
-
-# first program
-
-mkdir -p docs/getting_started/java/first_program_in_java/images/
-#cp -r ~/dev/documentation/static/img/tutorials/java/run-your-first-app-tutorial/* docs/getting_started/java/first_program_in_java/images/
-#cp -r ~/dev/documentation/static/img/tutorials/go/run-your-first-app-tutorial/* docs/getting_started/java/first_program_in_java/images/
-cp ~/dev/documentation/docs/java/run-your-first-app-tutorial.md docs/getting_started/java/first_program_in_java/index_tmp.md
-# rewrite images
-sed -e '/^id\:/a\
-sidebar_position: 2' \
- -e '/^id\:/a\
-description: In this tutorial you will run your first Temporal app using the Java SDK' \
- -e '/^id\:/a\
-keywords: [ava, temporal, sdk, tutorial]' \
- -e '/^id\:/a\
-tags: [Java, SDK]' \
- -e '/^sidebar_label/d' \
- -e 's|../../src/components|@site/src/components|g' \
- -e '/Keep reading or follow along with this video walkthrough:/d' \
- -e '/ docs/getting_started/java/first_program_in_java/index.md
-rm docs/getting_started/java/first_program_in_java/index_tmp.md
-
-
-# hello world
-
-mkdir -p docs/getting_started/java/hello_world_in_java/images/
-cp ~/dev/documentation/docs/java/hello-world-tutorial.md docs/getting_started/java/hello_world_in_java/index_tmp.md
-sed -e '/^id\:/a\
-sidebar_position: 3' \
- -e '/^id\:/a\
-description: In this tutorial you will build your first Temporal app using the Java SDK' \
- -e '/^id\:/a\
-keywords: [Java,java,temporal,sdk,tutorial,learn]' \
- -e '/^sidebar_label/d' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/concepts/|https://docs.temporal.io/concepts/|g' \
- -e 's|/application-development-guide|https://docs.temporal.io/application-development-guide|g' \
- -e 's|/java/|https://docs.temporal.io/java/|g' \
- -e 's|^##.*Lore check$|## Review|' \
- -e '/^id\:/a\
-last_update:'\
- -e '/^id\:/a\
- date: 2021-10-01' \
- docs/getting_started/java/hello_world_in_java/index_tmp.md > docs/getting_started/java/hello_world_in_java/index.md
-rm docs/getting_started/java/hello_world_in_java/index_tmp.md
-
-# typescript
-
-
-
-mkdir -p docs/getting_started/typescript/hello_world_in_typescript/images/
-cp ~/dev/documentation/docs/typescript/hello-world.md docs/getting_started/typescript/hello_world_in_typescript/index_tmp.md
-sed -e '/^id\:/a\
-sidebar_position: 1' \
- -e '/^id\:/a\
-keywords: [typescript, javascript,temporal,sdk,tutorial,learn]' \
- -e '/^id\:/a\
-tags: [TypeScript, SDK]' \
- -e '/^sidebar_label/d' \
- -e 's/^title:.*/title: Build a Temporal "Hello World!" app from scratch in TypeScript/g' \
- -e 's|{"enable_source_link": false}||g' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/concepts/|https://docs.temporal.io/concepts/|g' \
- -e 's|/application-development-guide|https://docs.temporal.io/application-development-guide|g' \
- -e 's|/typescript/|https://docs.temporal.io/typescript/|g' \
- -e 's|/typescript/nextjs-tutorial|/docs/tutorials/typescript/nextjs/index.md|g' \
- -e '/^id\:/a\
-last_update:'\
- -e '/^id\:/a\
- date: 2021-10-01' \
- docs/getting_started/typescript/hello_world_in_typescript/index_tmp.md > docs/getting_started/typescript/hello_world_in_typescript/index.md
-rm docs/getting_started/typescript/hello_world_in_typescript/index_tmp.md
-
-
-mkdir -p docs/tutorials/typescript/nextjs/images
-cp -r ~/dev/documentation/docs/typescript/nextjs.md docs/tutorials/typescript/nextjs/index.md2
-sed -e '/^id\:/a\
-sidebar_position: 2' \
- -e '/^id\:/a\
-keywords: [TypeScript, temporal, sdk, tutorial, NextJS]' \
- -e '/^id\:/a\
-tags: [TypeScript, SDK]' \
- -e '/^sidebar_label/d' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/concepts/|https://docs.temporal.io/concepts/|g' \
- -e 's|/tctl/|https://docs.temporal.io/tctl/|g' \
- -e 's|/application-development-guide|https://docs.temporal.io/application-development-guide|g' \
- -e 's|/typescript/|https://docs.temporal.io/typescript/|g' \
- -e '/^id\:/a\
-last_update:'\
- -e '/^id\:/a\
- date: 2021-10-01' \
- docs/tutorials/typescript/nextjs/index.md2 \
- > docs/tutorials/typescript/nextjs/index.md
-rm docs/tutorials/typescript/nextjs/index.md2
-
-
-mkdir -p docs/tutorials/typescript/subscriptions/
-cp -r ~/dev/documentation/docs/typescript/tutorial-subscription.md docs/tutorials/typescript/subscriptions/index.md2
-sed -e '/^id\:/a\
-sidebar_position: 3' \
- -e '/^id\:/a\
-keywords: [TypeScript, temporal, sdk, tutorial]' \
- -e '/^id\:/a\
-tags: [TypeScript, SDK]' \
- -e '/^sidebar_label/d' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/concepts/|https://docs.temporal.io/concepts/|g' \
- -e 's|/application-development-guide|https://docs.temporal.io/application-development-guide|g' \
- -e 's|/typescript/|https://docs.temporal.io/typescript/|g' \
- -e 's|/typescript/nextjs-tutorial|/docs/tutorials/typescript/nextjs/index.md|g' \
- -e '/^id\:/a\
-last_update:'\
- -e '/^id\:/a\
- date: 2021-10-01' \
- docs/tutorials/typescript/subscriptions/index.md2 \
- > docs/tutorials/typescript/subscriptions/index.md
-rm docs/tutorials/typescript/subscriptions/index.md2
-
-mkdir -p docs/tutorials/typescript/chatbot/
-cp -r ~/dev/documentation/docs/typescript/tutorial-chatbot.md docs/tutorials/typescript/chatbot/index.md2
-sed -e '/^id\:/a\
-sidebar_position: 4' \
- -e '/^id\:/a\
-keywords: [TypeScript, temporal, sdk, tutorial]' \
- -e '/^id\:/a\
-tags: [TypeScript, SDK]' \
- -e '/^sidebar_label/d' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/concepts/|https://docs.temporal.io/concepts/|g' \
- -e 's|/application-development-guide|https://docs.temporal.io/application-development-guide|g' \
- -e 's|/typescript/|https://docs.temporal.io/typescript/|g' \
- -e '/^id\:/a\
-last_update:'\
- -e '/^id\:/a\
- date: 2021-10-01' \
- docs/tutorials/typescript/chatbot/index.md2 \
- > docs/tutorials/typescript/chatbot/index.md
-rm docs/tutorials/typescript/chatbot/index.md2
-
-# PHP
-mkdir -p docs/getting_started/php/hello_world_in_php/images/
-cp ~/dev/documentation/docs/php/hello-world.md docs/getting_started/php/hello_world_in_php/index_tmp.md
-sed -e '/^id\:/a\
-sidebar_position: 1' \
- -e '/^id\:/a\
-keywords: [PHP, temporal, sdk, tutorial]' \
- -e '/^id\:/a\
-tags: [PHP, SDK]' \
- -e '/^sidebar_label/d' \
- -e 's/^title:.*/title: Build a Temporal "Hello World!" app from scratch in PHP/g' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/concepts/|https://docs.temporal.io/concepts/|g' \
- -e 's|/web-ui|https://docs.temporal.io/web-ui|g' \
- -e 's|/application-development-guide|https://docs.temporal.io/application-development-guide|g' \
- -e 's|/php/|https://docs.temporal.io/php/|g' \
- -e 's|Conclusion and Next Steps|Conclusion|' \
- -e '/longform workshops/d' \
- -e '/^id\:/a\
-last_update:'\
- -e '/^id\:/a\
- date: 2021-10-01' \
- docs/getting_started/php/hello_world_in_php/index_tmp.md > docs/getting_started/php/hello_world_in_php/index.md
-rm docs/getting_started/php/hello_world_in_php/index_tmp.md
-
-# PHP
-mkdir -p docs/tutorials/php/booking_saga/images/
-cp ~/dev/documentation/static/img/tutorials/booking-saga-flow.png docs/tutorials/php/booking_saga/images/
-cp ~/dev/documentation/docs/php/booking-saga-tutorial.md docs/tutorials/php/booking_saga/index_tmp.md
-sed -e '/^id\:/a\
-sidebar_position: 1' \
- -e '/^sidebar_label/d' \
- -e '/^id\:/a\
-keywords: [PHP, temporal, sdk, tutorial, saga pattern, transactions]' \
- -e '/^id\:/a\
-tags: [PHP, SDK, Saga]' \
- -e 's|/img/tutorials/|images/|g' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/concepts/|https://docs.temporal.io/concepts/|g' \
- -e 's|/application-development-guide|https://docs.temporal.io/application-development-guide|g' \
- -e 's|/php/|https://docs.temporal.io/php/|g' \
- -e '/^id\:/a\
-last_update:'\
- -e '/^id\:/a\
- date: 2021-10-01' \
- docs/tutorials/php/booking_saga/index_tmp.md > docs/tutorials/php/booking_saga/index.md
-rm docs/tutorials/php/booking_saga/index_tmp.md
-
-mkdir -p docs/tutorials/php/subscriptions/images/
-cp ~/dev/documentation/docs/php/subscription-tutorial.md docs/tutorials/php/subscriptions/index_tmp.md
-sed -e '/^id\:/a\
-sidebar_position: 1' \
- -e '/^sidebar_label/d' \
- -e '/^id\:/a\
-keywords: [PHP, temporal, sdk, tutorial, subscriptions]' \
- -e '/^id\:/a\
-tags: [PHP, SDK]' \
- -e 's|/php/|https://docs.temporal.io/php/|g' \
- -e 's|/php/hello-world|/getting_started/php/hello_world_in_php/|g' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/concepts/|https://docs.temporal.io/concepts/|g' \
- -e 's|/application-development-guide|https://docs.temporal.io/application-development-guide|g' \
- -e '/^id\:/a\
-last_update:'\
- -e '/^id\:/a\
- date: 2021-10-01' \
- docs/tutorials/php/subscriptions/index_tmp.md > docs/tutorials/php/subscriptions/index.md
-rm docs/tutorials/php/subscriptions/index_tmp.md
-
-# background-check-app
-mkdir -p docs/examples/go/background-checks/images
-cp -r ~/dev/documentation/static/diagrams/background-checks/* docs/examples/go/background-checks/images
-
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/index.md docs/examples/go/background-checks/index.md2
-sed -e '/^id\:/a\
-sidebar_position: 1' \
- -e '/^sidebar_label/d' \
- -e 's|/learning-paths/background-checks/||g' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/index.md2 \
- > docs/examples/go/background-checks/index.md
-rm docs/examples/go/background-checks/index.md2
-
-# change paths
-cp ~/dev/documentation/docs/learning-paths/background-checks/project-narrative.md docs/examples/go/background-checks/index.md2
-sed -e '/^id\:/a\
-sidebar_position: 1' \
- -e '/^sidebar_label/d' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/concepts/|https://docs.temporal.io/concepts/|g' \
- -e 's|/application-development-guide/|https://docs.temporal.io/application-development-guide/|g' \
- -e 's|/go/|https://docs.temporal.io/go/|g' \
- -e 's|/blog/|https://docs.temporal.io/blog/|g' \
- -e 's|/learning-paths/background-checks/||g' \
- -e 's/^title:.*/title: Background Check Application in Go/' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/index.md2 \
- > docs/examples/go/background-checks/index.md
-rm docs/examples/go/background-checks/index.md2
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/how-to-use.md docs/examples/go/background-checks/how-to-use.md2
-sed -e '/^id\:/a\
-sidebar_position: 2' \
- -e '/^sidebar_label/d' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/concepts/|https://docs.temporal.io/concepts/|g' \
- -e 's|/application-development-guide/|https://docs.temporal.io/application-development-guide/|g' \
- -e 's|/go/|https://docs.temporal.io/go/|g' \
- -e 's|/learning-paths/background-checks/||g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/how-to-use.md2 \
- > docs/examples/go/background-checks/how-to-use.md
-rm docs/examples/go/background-checks/how-to-use.md2
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/application-requirements.md docs/examples/go/background-checks/application-requirements.md2
-sed -e '/^id\:/a\
-sidebar_position: 3' \
- -e '/^sidebar_label/d' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/learning-paths/background-checks/||g' \
- -e 's|/diagrams/background-checks/|images/|g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/application-requirements.md2 \
- > docs/examples/go/background-checks/application-requirements.md
-rm docs/examples/go/background-checks/application-requirements.md2
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/application-design-and-implementation.md docs/examples/go/background-checks/application-design-and-implementation.md2
-sed -e '/^id\:/a\
-sidebar_position: 4' \
- -e '/^sidebar_label/d' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/concepts/|https://docs.temporal.io/concepts/|g' \
- -e 's|/learning-paths/background-checks/||g' \
- -e 's|/diagrams/background-checks/|images/|g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/application-design-and-implementation.md2 \
- > docs/examples/go/background-checks/application-design-and-implementation.md
-rm docs/examples/go/background-checks/application-design-and-implementation.md2
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/main-background-check.md docs/examples/go/background-checks/main-background-check.md2
-sed -e '/^id\:/a\
-sidebar_position: 5' \
- -e '/^sidebar_label/d' \
- -e 's|../../src/components|@site/src/components|g' \
- -e 's|/concepts/|https://docs.temporal.io/concepts/|g' \
- -e 's|/application-development-guide/|https://docs.temporal.io/application-development-guide/|g' \
- -e 's|/go/|https://docs.temporal.io/go/|g' \
- -e 's|/learning-paths/background-checks/||g' \
- -e 's|/diagrams/background-checks/|images/|g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/main-background-check.md2 \
- > docs/examples/go/background-checks/main-background-check.md
-rm docs/examples/go/background-checks/main-background-check.md2
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/candidate-acceptance.md docs/examples/go/background-checks/candidate-acceptance.md2
-sed -e '/^id\:/a\
-sidebar_position: 6' \
- -e '/^sidebar_label/d' \
- -e 's|/learning-paths/background-checks/||g' \
- -e 's|/diagrams/background-checks/|images/|g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/candidate-acceptance.md2 \
- > docs/examples/go/background-checks/candidate-acceptance.md
-rm docs/examples/go/background-checks/candidate-acceptance.md2
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/ssn-trace.md docs/examples/go/background-checks/ssn-trace.md2
-sed -e '/^id\:/a\
-sidebar_position: 7' \
- -e '/^sidebar_label/d' \
- -e 's|/learning-paths/background-checks/||g' \
- -e 's|/diagrams/background-checks/|images/|g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/ssn-trace.md2 \
- > docs/examples/go/background-checks/ssn-trace.md
-rm docs/examples/go/background-checks/ssn-trace.md2
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/federal-criminal.md docs/examples/go/background-checks/federal-criminal.md2
-sed -e '/^id\:/a\
-sidebar_position: 8' \
- -e '/^sidebar_label/d' \
- -e 's|/learning-paths/background-checks/||g' \
- -e 's|/diagrams/background-checks/|images/|g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/federal-criminal.md2 \
- > docs/examples/go/background-checks/federal-criminal.md
-rm docs/examples/go/background-checks/federal-criminal.md2
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/state-criminal-search.md docs/examples/go/background-checks/state-criminal-search.md2
-sed -e '/^id\:/a\
-sidebar_position: 9' \
- -e '/^sidebar_label/d' \
- -e 's|/learning-paths/background-checks/||g' \
- -e 's|/diagrams/background-checks/|images/|g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/state-criminal-search.md2 \
- > docs/examples/go/background-checks/state-criminal-search.md
-rm docs/examples/go/background-checks/state-criminal-search.md2
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/motor-vehicle-search.md docs/examples/go/background-checks/motor-vehicle-search.md2
-sed -e '/^id\:/a\
-sidebar_position: 10' \
- -e '/^sidebar_label/d' \
- -e 's|/learning-paths/background-checks/||g' \
- -e 's|/diagrams/background-checks/|images/|g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/motor-vehicle-search.md2 \
- > docs/examples/go/background-checks/motor-vehicle-search.md
-rm docs/examples/go/background-checks/motor-vehicle-search.md2
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/employment-verification.md docs/examples/go/background-checks/employment-verification.md2
-sed -e '/^id\:/a\
-sidebar_position: 11' \
- -e '/^sidebar_label/d' \
- -e 's|/learning-paths/background-checks/||g' \
- -e 's|/diagrams/background-checks/|images/|g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/employment-verification.md2 \
- > docs/examples/go/background-checks/employment-verification.md
-rm docs/examples/go/background-checks/employment-verification.md2
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/application-deployment.md docs/examples/go/background-checks/application-deployment.md2
-sed -e '/^id\:/a\
-sidebar_position: 12' \
- -e '/^sidebar_label/d' \
- -e 's|/learning-paths/background-checks/||g' \
- -e 's|/diagrams/background-checks/|images/|g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/application-deployment.md2 \
- > docs/examples/go/background-checks/application-deployment.md
-rm docs/examples/go/background-checks/application-deployment.md2
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/api-reference.md docs/examples/go/background-checks/api-reference.md2
-sed -e '/^id\:/a\
-sidebar_position: 13' \
--e 's/^tags(.*)path//' \
- -e '/^sidebar_label/d' \
- -e 's|/learning-paths/background-checks/||g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- -e 's/^tags:.*/tags: [Go, SDK]/' \
- -e '/ - reference/d' \
- -e '/ - learning-path/d' \
- docs/examples/go/background-checks/api-reference.md2 \
- > docs/examples/go/background-checks/api-reference.md
-rm docs/examples/go/background-checks/api-reference.md2
-
-cp ~/dev/documentation/docs/learning-paths/background-checks/cli-reference.md docs/examples/go/background-checks/cli-reference.md2
-sed -e '/^id\:/a\
-sidebar_position: 14' \
- -e '/^sidebar_label/d' \
- -e 's|/learning-paths/background-checks/||g' \
- -e '/^id\:/a\
-keywords: [go, golang, temporal, sdk, tutorial]' \
- docs/examples/go/background-checks/cli-reference.md2 \
- > docs/examples/go/background-checks/cli-reference.md
-rm docs/examples/go/background-checks/cli-reference.md2
-
diff --git a/dprint.json b/dprint.json
new file mode 100644
index 00000000..d20ba0a1
--- /dev/null
+++ b/dprint.json
@@ -0,0 +1,33 @@
+{
+ "lineWidth": 80,
+ "typescript": {
+ "quoteStyle": "alwaysSingle"
+ },
+ "json": {},
+ "markdown": {
+ "associations": ["**/*.mdx", "**/*.md"],
+ "newLineKind": "lf",
+ "textWrap": "maintain",
+ "emphasisKind": "underscores",
+ "strongKind": "asterisks",
+ "ignoreDirective": "dprint-ignore",
+ "ignoreFileDirective": "dprint-ignore-file",
+ "ignoreStartDirective": "dprint-ignore-start",
+ "ignoreEndDirective": "dprint-ignore-end"
+ },
+ "includes": ["docs/**/*.mdx", "vercel.json"],
+ "excludes": [
+ "website/docs/components",
+ "**/node_modules",
+ "**/*-lock.json",
+ ".docusaurus/",
+ ".github",
+ "website/build"
+ ],
+ "incremental": true,
+ "plugins": [
+ "https://plugins.dprint.dev/typescript-0.88.8.wasm",
+ "https://plugins.dprint.dev/json-0.19.1.wasm",
+ "https://plugins.dprint.dev/markdown-0.16.3.wasm"
+ ]
+}
diff --git a/package.json b/package.json
index 9e56b3bb..ef71c7f8 100644
--- a/package.json
+++ b/package.json
@@ -4,6 +4,7 @@
"private": true,
"scripts": {
"docusaurus": "docusaurus",
+ "format": "dprint fmt",
"start": "docusaurus start",
"build": "docusaurus build",
"build_all": "npm-run-all --serial getsnips build",
@@ -43,6 +44,7 @@
"husky": "^6.0.0",
"lint-staged": "^11.1.2",
"npm-run-all": "^4.1.5",
+ "dprint": "^0.45.0",
"prettier": "^2.5.1"
},
"browserslist": {
diff --git a/yarn.lock b/yarn.lock
index 5a2ddec7..cc0cfb86 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2138,7 +2138,7 @@
"@docusaurus/theme-search-algolia" "2.4.3"
"@docusaurus/types" "2.4.3"
-"@docusaurus/react-loadable@5.5.2":
+"@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2":
version "5.5.2"
resolved "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz"
integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==
@@ -2283,6 +2283,41 @@
url-loader "^4.1.1"
webpack "^5.73.0"
+"@dprint/darwin-arm64@0.45.1":
+ version "0.45.1"
+ resolved "https://registry.yarnpkg.com/@dprint/darwin-arm64/-/darwin-arm64-0.45.1.tgz#3c989b5fd7122a61f20ec95db1a3e6f020634a90"
+ integrity sha512-pH0/uKLJ5SJPoHhOwLWFMhCmL0BY3FzWQbull8OGMK/FRkIPgOl2adZSovtUZpUMGWyDOzIWH1fW9X2DuMhnEg==
+
+"@dprint/darwin-x64@0.45.1":
+ version "0.45.1"
+ resolved "https://registry.yarnpkg.com/@dprint/darwin-x64/-/darwin-x64-0.45.1.tgz#f024fa56804ecdb7b52e31e698b95c5f8fc9e8d1"
+ integrity sha512-YUj421LmBLDlxpIER3pORKfQmpmXD50n5mClHjpZrnl17WTiHtQ+jHvDJdJoxH2eS66W0mQyxLoGo5SfFfiM7A==
+
+"@dprint/linux-arm64-glibc@0.45.1":
+ version "0.45.1"
+ resolved "https://registry.yarnpkg.com/@dprint/linux-arm64-glibc/-/linux-arm64-glibc-0.45.1.tgz#e31be90fd8483f8b79c0a7081c7befb167c5865e"
+ integrity sha512-lJ7s/pOQWRJ0mstjZQnVyX2/3QRXZ9cpFHJDZ7e81Y8QSn/iqxTrnK0DPgxUrDG8hYKQmWQdQLU4sP5DKBz0Jg==
+
+"@dprint/linux-arm64-musl@0.45.1":
+ version "0.45.1"
+ resolved "https://registry.yarnpkg.com/@dprint/linux-arm64-musl/-/linux-arm64-musl-0.45.1.tgz#ff5ad5ce0d55d8ff35139992f283765326a0bc2b"
+ integrity sha512-un2awe1L1sAJLsCPSEUrE0/cgupdzbYFoyBOutyU1zHR9KQn47AtIDw+chvuinU4xleHDuEGyXGuJ6NE+Ky6vw==
+
+"@dprint/linux-x64-glibc@0.45.1":
+ version "0.45.1"
+ resolved "https://registry.yarnpkg.com/@dprint/linux-x64-glibc/-/linux-x64-glibc-0.45.1.tgz#890a1c42507746d2082778ec67d6e2873b6c7f71"
+ integrity sha512-5Civht90S/g8zlyYB7n4oH78p+sLbNqeFCFuImJRK7uRxZwCRya7lji6RwlB6DQ7qngVqovTHj9RLOYfZzfVlg==
+
+"@dprint/linux-x64-musl@0.45.1":
+ version "0.45.1"
+ resolved "https://registry.yarnpkg.com/@dprint/linux-x64-musl/-/linux-x64-musl-0.45.1.tgz#53508925c105c8392335f0b6e15c49334e631c96"
+ integrity sha512-p2/gjnHDd8GRCvtey5HZO4o/He6pSmY/zpcCuIXprFW9P0vNlEj3DFhz4FPpOKXM+csrsVWWs2E0T/xr5QZtVg==
+
+"@dprint/win32-x64@0.45.1":
+ version "0.45.1"
+ resolved "https://registry.yarnpkg.com/@dprint/win32-x64/-/win32-x64-0.45.1.tgz#6d08308cf08e4b751efb0692ded28b57d42a365d"
+ integrity sha512-2l78XM7KsW46P2Yv6uPB3fE+y92EsBlrCxi+RVQ0pbznPFdMdkLyGgaCuh683zdld14jHlaADpIQ7YchGAEMAg==
+
"@eslint/eslintrc@^0.4.3":
version "0.4.3"
resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz"
@@ -4518,6 +4553,19 @@ dot-prop@^5.2.0:
dependencies:
is-obj "^2.0.0"
+dprint@^0.45.0:
+ version "0.45.1"
+ resolved "https://registry.yarnpkg.com/dprint/-/dprint-0.45.1.tgz#3cab696fb0eb0f95d975eb534832f2d998aa8819"
+ integrity sha512-OYefcDgxd6jSdig/Cfkw1vdvyiOIRruCPnqGBbXpc95buDt9kvwL+Lic1OHc+SaQSsQub0BUZMd5+TNgy8Sh3A==
+ optionalDependencies:
+ "@dprint/darwin-arm64" "0.45.1"
+ "@dprint/darwin-x64" "0.45.1"
+ "@dprint/linux-arm64-glibc" "0.45.1"
+ "@dprint/linux-arm64-musl" "0.45.1"
+ "@dprint/linux-x64-glibc" "0.45.1"
+ "@dprint/linux-x64-musl" "0.45.1"
+ "@dprint/win32-x64" "0.45.1"
+
duplexer3@^0.1.4:
version "0.1.4"
resolved "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz"
@@ -7867,14 +7915,6 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1:
dependencies:
"@babel/runtime" "^7.10.3"
-"react-loadable@npm:@docusaurus/react-loadable@5.5.2":
- version "5.5.2"
- resolved "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz"
- integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==
- dependencies:
- "@types/react" "*"
- prop-types "^15.6.2"
-
react-player@^2.10.1:
version "2.10.1"
resolved "https://registry.npmjs.org/react-player/-/react-player-2.10.1.tgz"