mirror of
https://github.com/hatchet-dev/hatchet.git
synced 2026-04-18 07:20:58 -05:00
Fe overhaul docs (#1640)
* api changes * doc changes * move docs * generated * generate * pkg * backmerge main * revert to main * revert main * race? * remove go tests
This commit is contained in:
19
.github/dependabot.yml
vendored
19
.github/dependabot.yml
vendored
@@ -9,3 +9,22 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
|
||||
# // We need to update the quickstart examples for typescript, go, and python
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/examples/typescript"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/examples/go/quickstart"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
# TODO python quickstart
|
||||
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/examples/python/quickstart"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
29
.github/workflows/sync-go-quickstart.yml
vendored
Normal file
29
.github/workflows/sync-go-quickstart.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Sync Go Quickstart
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'examples/go/quickstart/**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
manual_trigger:
|
||||
description: 'Manually trigger the sync'
|
||||
default: 'true'
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run sync script
|
||||
env:
|
||||
SYNC_TOKEN: ${{ secrets.SYNC_TOKEN }}
|
||||
run: |
|
||||
./hack/sync-quickstart.sh --source-dir "examples/go/quickstart" --target-repo "hatchet-dev/hatchet-go-quickstart"
|
||||
29
.github/workflows/sync-python-quickstart.yml
vendored
Normal file
29
.github/workflows/sync-python-quickstart.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Sync Python Quickstart
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'examples/python/quickstart/**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
manual_trigger:
|
||||
description: 'Manually trigger the sync'
|
||||
default: 'true'
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run sync script
|
||||
env:
|
||||
SYNC_TOKEN: ${{ secrets.SYNC_TOKEN }}
|
||||
run: |
|
||||
./hack/sync-quickstart.sh --source-dir "examples/python/quickstart" --target-repo "hatchet-dev/hatchet-python-quickstart"
|
||||
29
.github/workflows/sync-typescript-quickstart.yml
vendored
Normal file
29
.github/workflows/sync-typescript-quickstart.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Sync TypeScript Quickstart
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'examples/typescript/quickstart/**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
manual_trigger:
|
||||
description: 'Manually trigger the sync'
|
||||
default: 'true'
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run sync script
|
||||
env:
|
||||
SYNC_TOKEN: ${{ secrets.SYNC_TOKEN }}
|
||||
run: |
|
||||
./hack/sync-typescript-quickstart.sh --source-dir "examples/typescript/quickstart" --target-repo "grutt/hatchet-typescript-quickstart"
|
||||
137
.github/workflows/test.yml
vendored
137
.github/workflows/test.yml
vendored
@@ -68,7 +68,7 @@ jobs:
|
||||
run: go generate ./...
|
||||
|
||||
- name: Test
|
||||
run: go test ./... -v -failfast
|
||||
run: go test $(go list ./... | grep -v "quickstart") -v -failfast
|
||||
|
||||
integration:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -109,7 +109,7 @@ jobs:
|
||||
task generate-local-encryption-keys
|
||||
|
||||
- name: Test
|
||||
run: go test -tags integration ./... -v -failfast
|
||||
run: go test -tags integration $(go list ./... | grep -v "quickstart") -v -failfast
|
||||
|
||||
- name: Teardown
|
||||
run: docker compose down
|
||||
@@ -293,11 +293,8 @@ jobs:
|
||||
load:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
migrate-strategy: ["latest", "penultimate"]
|
||||
rabbitmq-enabled: ["true", "false"]
|
||||
pg-version: ["17-alpine", "16-alpine", "15-alpine"]
|
||||
env:
|
||||
DATABASE_URL: postgresql://hatchet:hatchet@127.0.0.1:5431/hatchet?sslmode=disable
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -315,13 +312,131 @@ jobs:
|
||||
version: 9.15.4
|
||||
run_install: false
|
||||
|
||||
- name: Install Atlas
|
||||
run: |
|
||||
curl -sSf https://atlasgo.sh | sh
|
||||
|
||||
- name: Compose
|
||||
run: docker compose up -d
|
||||
|
||||
- name: Go deps
|
||||
run: go mod download
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
cat > .env <<EOF
|
||||
DATABASE_URL='postgresql://hatchet:hatchet@127.0.0.1:5431/hatchet'
|
||||
SERVER_TLS_CERT_FILE=./hack/dev/certs/cluster.pem
|
||||
SERVER_TLS_KEY_FILE=./hack/dev/certs/cluster.key
|
||||
SERVER_TLS_ROOT_CA_FILE=./hack/dev/certs/ca.cert
|
||||
SERVER_PORT=8080
|
||||
SERVER_URL=http://localhost:8080
|
||||
SERVER_AUTH_COOKIE_SECRETS="something something"
|
||||
SERVER_AUTH_COOKIE_DOMAIN=app.dev.hatchet-tools.com
|
||||
SERVER_AUTH_COOKIE_INSECURE=false
|
||||
SERVER_AUTH_SET_EMAIL_VERIFIED=true
|
||||
SERVER_LOGGER_LEVEL=warn
|
||||
SERVER_LOGGER_FORMAT=console
|
||||
DATABASE_LOGGER_LEVEL=warn
|
||||
DATABASE_LOGGER_FORMAT=console
|
||||
EOF
|
||||
|
||||
- name: Generate
|
||||
run: |
|
||||
go run ./cmd/hatchet-migrate
|
||||
task generate-go
|
||||
task generate-certs
|
||||
task generate-local-encryption-keys
|
||||
|
||||
- name: Setup
|
||||
run: |
|
||||
set -a
|
||||
. .env
|
||||
set +a
|
||||
|
||||
go run ./cmd/hatchet-admin quickstart --generated-config-dir ./generated/
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
export HATCHET_CLIENT_TOKEN="$(go run ./cmd/hatchet-admin token create --config ./generated/ --tenant-id 707d0855-80ab-4e1f-a156-f1c4546cbf52)"
|
||||
|
||||
go test -tags load ./... -p 1 -v -race -failfast
|
||||
env:
|
||||
TESTING_MATRIX_MIGRATE: ${{ matrix.migrate-strategy }}
|
||||
TESTING_MATRIX_RABBITMQ_ENABLED: ${{ matrix.rabbitmq-enabled }}
|
||||
TESTING_MATRIX_PG_VERSION: ${{ matrix.pg-version }}
|
||||
|
||||
- name: Teardown
|
||||
run: docker compose down
|
||||
|
||||
load-pgmq:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
DATABASE_URL: postgresql://hatchet:hatchet@127.0.0.1:5431/hatchet?sslmode=disable
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Task
|
||||
uses: arduino/setup-task@v2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 9.15.4
|
||||
run_install: false
|
||||
|
||||
- name: Install Atlas
|
||||
run: |
|
||||
curl -sSf https://atlasgo.sh | sh
|
||||
|
||||
- name: Compose
|
||||
run: docker compose up -d
|
||||
|
||||
- name: Go deps
|
||||
run: go mod download
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
cat > .env <<EOF
|
||||
DATABASE_URL='postgresql://hatchet:hatchet@127.0.0.1:5431/hatchet'
|
||||
SERVER_TLS_CERT_FILE=./hack/dev/certs/cluster.pem
|
||||
SERVER_TLS_KEY_FILE=./hack/dev/certs/cluster.key
|
||||
SERVER_TLS_ROOT_CA_FILE=./hack/dev/certs/ca.cert
|
||||
SERVER_PORT=8080
|
||||
SERVER_URL=http://localhost:8080
|
||||
SERVER_AUTH_COOKIE_SECRETS="something something"
|
||||
SERVER_AUTH_COOKIE_DOMAIN=app.dev.hatchet-tools.com
|
||||
SERVER_AUTH_COOKIE_INSECURE=false
|
||||
SERVER_AUTH_SET_EMAIL_VERIFIED=true
|
||||
SERVER_LOGGER_LEVEL=warn
|
||||
SERVER_LOGGER_FORMAT=console
|
||||
DATABASE_LOGGER_LEVEL=warn
|
||||
DATABASE_LOGGER_FORMAT=console
|
||||
SERVER_TASKQUEUE_KIND=postgres
|
||||
EOF
|
||||
|
||||
- name: Generate
|
||||
run: |
|
||||
go run ./cmd/hatchet-migrate
|
||||
task generate-go
|
||||
task generate-certs
|
||||
task generate-local-encryption-keys
|
||||
|
||||
- name: Setup
|
||||
run: |
|
||||
set -a
|
||||
. .env
|
||||
set +a
|
||||
|
||||
go run ./cmd/hatchet-admin quickstart --generated-config-dir ./generated/
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
export HATCHET_CLIENT_TOKEN="$(go run ./cmd/hatchet-admin token create --config ./generated/ --tenant-id 707d0855-80ab-4e1f-a156-f1c4546cbf52)"
|
||||
|
||||
RAMP_UP_DURATION_TIMEOUT=20s go test -tags load ./... -p 1 -v -race -failfast
|
||||
|
||||
- name: Teardown
|
||||
run: docker compose down
|
||||
|
||||
@@ -56,6 +56,7 @@ tasks:
|
||||
pre:
|
||||
cmds:
|
||||
# FIXME: Remove this once we have a better way to handle pre-commit reliably
|
||||
- cd frontend/snips/ && pnpm i && pnpm generate && pnpm run copy:all
|
||||
- pre-commit run --all-files
|
||||
- pre-commit run --all-files
|
||||
- pre-commit run --all-files
|
||||
|
||||
@@ -10,7 +10,7 @@ RUN go mod download
|
||||
COPY /pkg ./pkg
|
||||
COPY /internal ./internal
|
||||
COPY /api ./api
|
||||
COPY /examples/loadtest/cli ./cli
|
||||
COPY /examples/go/z_v0/loadtest/cli ./cli
|
||||
|
||||
# Go build environment
|
||||
# --------------------
|
||||
|
||||
28
examples/README.md
Normal file
28
examples/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
## Hatchet Examples
|
||||
|
||||
### Contributing
|
||||
These examples are generated from SDK source where they include, to contribute updates to these docs please make these changes in the sdk source:
|
||||
|
||||
- Typescript: ../sdks/typescript/src/v1/examples
|
||||
- Python: ../sdks/python/examples
|
||||
- Go: ../pkg/examples
|
||||
|
||||
#### Comment Markup
|
||||
|
||||
We use a special comment markup to generate code snips for our docs. Markups support single line comments in typescript/go `//` or python `#`.
|
||||
|
||||
##### Blocks
|
||||
|
||||
```
|
||||
// > Block Title
|
||||
BLOCK CONTENT
|
||||
// !!
|
||||
```
|
||||
|
||||
##### Highlights
|
||||
```
|
||||
HH-name 1 hello
|
||||
hello world
|
||||
```
|
||||
|
||||
Where 1 is the number of lines to highlight and hello are strings to specifically highlight.
|
||||
233
examples/go/migration-guides/mergent.go
Normal file
233
examples/go/migration-guides/mergent.go
Normal file
@@ -0,0 +1,233 @@
|
||||
package migration_guides
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/create"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/factory"
|
||||
v1worker "github.com/hatchet-dev/hatchet/pkg/v1/worker"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/workflow"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
// ProcessImage simulates image processing
|
||||
func ProcessImage(imageURL string, filters []string) (map[string]interface{}, error) {
|
||||
// Do some image processing
|
||||
return map[string]interface{}{
|
||||
"url": imageURL,
|
||||
"size": 100,
|
||||
"format": "png",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// > Before (Mergent)
|
||||
type MergentRequest struct {
|
||||
ImageURL string `json:"image_url"`
|
||||
Filters []string `json:"filters"`
|
||||
}
|
||||
|
||||
type MergentResponse struct {
|
||||
Success bool `json:"success"`
|
||||
ProcessedURL string `json:"processed_url"`
|
||||
}
|
||||
|
||||
func ProcessImageMergent(req MergentRequest) (*MergentResponse, error) {
|
||||
result, err := ProcessImage(req.ImageURL, req.Filters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &MergentResponse{
|
||||
Success: true,
|
||||
ProcessedURL: result["url"].(string),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
// > After (Hatchet)
|
||||
type ImageProcessInput struct {
|
||||
ImageURL string `json:"image_url"`
|
||||
Filters []string `json:"filters"`
|
||||
}
|
||||
|
||||
type ImageProcessOutput struct {
|
||||
ProcessedURL string `json:"processed_url"`
|
||||
Metadata struct {
|
||||
Size int `json:"size"`
|
||||
Format string `json:"format"`
|
||||
AppliedFilters []string `json:"applied_filters"`
|
||||
} `json:"metadata"`
|
||||
}
|
||||
|
||||
func ImageProcessor(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[ImageProcessInput, ImageProcessOutput] {
|
||||
processor := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "image-processor",
|
||||
},
|
||||
func(ctx worker.HatchetContext, input ImageProcessInput) (*ImageProcessOutput, error) {
|
||||
result, err := ProcessImage(input.ImageURL, input.Filters)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("processing image: %w", err)
|
||||
}
|
||||
|
||||
if result["url"] == "" {
|
||||
return nil, fmt.Errorf("processing failed to generate URL")
|
||||
}
|
||||
|
||||
output := &ImageProcessOutput{
|
||||
ProcessedURL: result["url"].(string),
|
||||
Metadata: struct {
|
||||
Size int `json:"size"`
|
||||
Format string `json:"format"`
|
||||
AppliedFilters []string `json:"applied_filters"`
|
||||
}{
|
||||
Size: result["size"].(int),
|
||||
Format: result["format"].(string),
|
||||
AppliedFilters: input.Filters,
|
||||
},
|
||||
}
|
||||
|
||||
return output, nil
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
// Example of running a task
|
||||
_ = func() error {
|
||||
// > Running a task
|
||||
result, err := processor.Run(context.Background(), ImageProcessInput{
|
||||
ImageURL: "https://example.com/image.png",
|
||||
Filters: []string{"blur"},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Result: %+v\n", result)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Example of registering a task on a worker
|
||||
_ = func() error {
|
||||
// > Declaring a Worker
|
||||
w, err := hatchet.Worker(v1worker.WorkerOpts{
|
||||
Name: "image-processor-worker",
|
||||
Workflows: []workflow.WorkflowBase{
|
||||
processor,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = w.StartBlocking(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return processor
|
||||
}
|
||||
|
||||
func RunMergentTask() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func RunningTasks(hatchet v1.HatchetClient) error {
|
||||
// > Running a task (Mergent)
|
||||
task := struct {
|
||||
Request struct {
|
||||
URL string `json:"url"`
|
||||
Body string `json:"body"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
} `json:"request"`
|
||||
Name string `json:"name"`
|
||||
Queue string `json:"queue"`
|
||||
}{
|
||||
Request: struct {
|
||||
URL string `json:"url"`
|
||||
Body string `json:"body"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
}{
|
||||
URL: "https://example.com",
|
||||
Headers: map[string]string{
|
||||
"Authorization": "fake-secret-token",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
Body: "Hello, world!",
|
||||
},
|
||||
Name: "4cf95241-fa19-47ef-8a67-71e483747649",
|
||||
Queue: "default",
|
||||
}
|
||||
|
||||
taskJSON, err := json.Marshal(task)
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshaling task: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, "https://api.mergent.co/v2/tasks", bytes.NewBuffer(taskJSON))
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Add("Authorization", "Bearer <API_KEY>")
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
client := &http.Client{}
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("sending request: %w", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
fmt.Printf("Mergent task created with status: %d\n", res.StatusCode)
|
||||
|
||||
// > Running a task (Hatchet)
|
||||
processor := ImageProcessor(hatchet)
|
||||
|
||||
result, err := processor.Run(context.Background(), ImageProcessInput{
|
||||
ImageURL: "https://example.com/image.png",
|
||||
Filters: []string{"blur"},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Result: %+v\n", result)
|
||||
|
||||
// > Scheduling tasks (Hatchet)
|
||||
// Schedule the task to run at a specific time
|
||||
scheduleRef, err := processor.Schedule(
|
||||
context.Background(),
|
||||
time.Now().Add(time.Second*10),
|
||||
ImageProcessInput{
|
||||
ImageURL: "https://example.com/image.png",
|
||||
Filters: []string{"blur"},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// or schedule to run every hour
|
||||
cronRef, err := processor.Cron(
|
||||
context.Background(),
|
||||
"run-hourly",
|
||||
"0 * * * *",
|
||||
ImageProcessInput{
|
||||
ImageURL: "https://example.com/image.png",
|
||||
Filters: []string{"blur"},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Scheduled tasks with refs: %+v, %+v\n", scheduleRef, cronRef)
|
||||
return nil
|
||||
}
|
||||
48
examples/go/quickstart/README.md
Normal file
48
examples/go/quickstart/README.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# Hatchet First Workflow Example
|
||||
|
||||
This is an example project demonstrating how to use Hatchet with Go. For detailed setup instructions, see the [Hatchet Setup Guide](https://docs.hatchet.run/home/setup).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before running this project, make sure you have the following:
|
||||
|
||||
1. [Go v1.22 or higher](https://go.dev/doc/install)
|
||||
|
||||
## Setup
|
||||
|
||||
1. Clone the repository:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/hatchet-dev/hatchet-go-quickstart.git
|
||||
cd hatchet-go-quickstart
|
||||
```
|
||||
|
||||
2. Set the required environment variable `HATCHET_CLIENT_TOKEN` created in the [Getting Started Guide](https://docs.hatchet.run/home/hatchet-cloud-quickstart).
|
||||
|
||||
```bash
|
||||
export HATCHET_CLIENT_TOKEN=<token>
|
||||
```
|
||||
|
||||
> Note: If you're self hosting you may need to set `HATCHET_CLIENT_TLS_STRATEGY=none` to disable TLS
|
||||
|
||||
3. Install the project dependencies:
|
||||
|
||||
```bash
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
### Running an example
|
||||
|
||||
1. Start a Hatchet worker:
|
||||
|
||||
```bash
|
||||
go run cmd/worker/main.go
|
||||
```
|
||||
|
||||
2. In a new terminal, run the example task:
|
||||
|
||||
```bash
|
||||
go run cmd/run/main.go
|
||||
```
|
||||
|
||||
This will trigger the task on the worker running in the first terminal and print the output to the second terminal.
|
||||
32
examples/go/quickstart/cmd/run/main.go
Normal file
32
examples/go/quickstart/cmd/run/main.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
hatchet_client "github.com/hatchet-dev/hatchet/pkg/examples/quickstart/hatchet_client"
|
||||
workflows "github.com/hatchet-dev/hatchet/pkg/examples/quickstart/workflows"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hatchet, err := hatchet_client.HatchetClient()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
simple := workflows.FirstTask(hatchet)
|
||||
|
||||
result, err := simple.Run(context.Background(), workflows.SimpleInput{
|
||||
Message: "Hello, World!",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(
|
||||
"Finished running task, and got the transformed message! The transformed message is:",
|
||||
result.ToLower.TransformedMessage,
|
||||
)
|
||||
}
|
||||
44
examples/go/quickstart/cmd/worker/main.go
Normal file
44
examples/go/quickstart/cmd/worker/main.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
hatchet_client "github.com/hatchet-dev/hatchet/pkg/examples/quickstart/hatchet_client"
|
||||
workflows "github.com/hatchet-dev/hatchet/pkg/examples/quickstart/workflows"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/cmdutils"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/worker"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/workflow"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
hatchet, err := hatchet_client.HatchetClient()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
worker, err := hatchet.Worker(
|
||||
worker.WorkerOpts{
|
||||
Name: "first-worker",
|
||||
Workflows: []workflow.WorkflowBase{
|
||||
workflows.FirstTask(hatchet),
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// we construct an interrupt context to handle Ctrl+C
|
||||
// you can pass in your own context.Context here to the worker
|
||||
interruptCtx, cancel := cmdutils.NewInterruptContext()
|
||||
|
||||
defer cancel()
|
||||
|
||||
err = worker.StartBlocking(interruptCtx)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
14
examples/go/quickstart/hatchet_client/hatchet_client.go
Normal file
14
examples/go/quickstart/hatchet_client/hatchet_client.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package hatchet_client
|
||||
|
||||
import (
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func HatchetClient() (v1.HatchetClient, error) {
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v1.NewHatchetClient()
|
||||
}
|
||||
47
examples/go/quickstart/workflows/first_task.go
Normal file
47
examples/go/quickstart/workflows/first_task.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package workflows
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/create"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/factory"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/workflow"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
type SimpleInput struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type LowerOutput struct {
|
||||
TransformedMessage string `json:"transformed_message"`
|
||||
}
|
||||
|
||||
type SimpleResult struct {
|
||||
ToLower LowerOutput
|
||||
}
|
||||
|
||||
func FirstTask(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[SimpleInput, SimpleResult] {
|
||||
simple := factory.NewWorkflow[SimpleInput, SimpleResult](
|
||||
create.WorkflowCreateOpts[SimpleInput]{
|
||||
Name: "first-task",
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
simple.Task(
|
||||
create.WorkflowTask[SimpleInput, SimpleResult]{
|
||||
Name: "first-task",
|
||||
},
|
||||
func(ctx worker.HatchetContext, input SimpleInput) (any, error) {
|
||||
fmt.Println("first-task task called")
|
||||
return &LowerOutput{
|
||||
TransformedMessage: strings.ToLower(input.Message),
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
|
||||
return simple
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
v1_workflows "github.com/hatchet-dev/hatchet/examples/v1/workflows"
|
||||
v1_workflows "github.com/hatchet-dev/hatchet/examples/go/workflows"
|
||||
"github.com/hatchet-dev/hatchet/pkg/client"
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/rest"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
41
examples/go/run/bulk.go
Normal file
41
examples/go/run/bulk.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
v1_workflows "github.com/hatchet-dev/hatchet/examples/go/workflows"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func bulk() {
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
hatchet, err := v1.NewHatchetClient()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
// > Bulk Run Tasks
|
||||
simple := v1_workflows.Simple(hatchet)
|
||||
bulkRunIds, err := simple.RunBulkNoWait(ctx, []v1_workflows.SimpleInput{
|
||||
{
|
||||
Message: "Hello, World!",
|
||||
},
|
||||
{
|
||||
Message: "Hello, Moon!",
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(bulkRunIds)
|
||||
}
|
||||
56
examples/go/run/cron.go
Normal file
56
examples/go/run/cron.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
v1_workflows "github.com/hatchet-dev/hatchet/examples/go/workflows"
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/rest"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func cron() {
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
hatchet, err := v1.NewHatchetClient()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// > Create
|
||||
simple := v1_workflows.Simple(hatchet)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
result, err := simple.Cron(
|
||||
ctx,
|
||||
"daily-run",
|
||||
"0 0 * * *",
|
||||
v1_workflows.SimpleInput{
|
||||
Message: "Hello, World!",
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// it may be useful to save the cron id for later
|
||||
fmt.Println(result.Metadata.Id)
|
||||
|
||||
// > Delete
|
||||
hatchet.Crons().Delete(ctx, result.Metadata.Id)
|
||||
|
||||
// > List
|
||||
crons, err := hatchet.Crons().List(ctx, rest.CronWorkflowListParams{
|
||||
AdditionalMetadata: &[]string{"user:daily-run"},
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(crons)
|
||||
}
|
||||
34
examples/go/run/event.go
Normal file
34
examples/go/run/event.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
v1_workflows "github.com/hatchet-dev/hatchet/examples/go/workflows"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func event() {
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
hatchet, err := v1.NewHatchetClient()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// > Pushing an Event
|
||||
err = hatchet.Events().Push(
|
||||
context.Background(),
|
||||
"simple-event:create",
|
||||
v1_workflows.SimpleInput{
|
||||
Message: "Hello, World!",
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
58
examples/go/run/priority.go
Normal file
58
examples/go/run/priority.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
v1_workflows "github.com/hatchet-dev/hatchet/examples/go/workflows"
|
||||
"github.com/hatchet-dev/hatchet/pkg/client"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func priority() {
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
hatchet, err := v1.NewHatchetClient()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
priorityWorkflow := v1_workflows.Priority(hatchet)
|
||||
|
||||
// > Running a Task with Priority
|
||||
priority := int32(3)
|
||||
|
||||
runId, err := priorityWorkflow.RunNoWait(ctx, v1_workflows.PriorityInput{
|
||||
UserId: "1234",
|
||||
}, client.WithPriority(priority))
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(runId)
|
||||
|
||||
// > Schedule and cron
|
||||
schedulePriority := int32(3)
|
||||
runAt := time.Now().Add(time.Minute)
|
||||
|
||||
scheduledRunId, _ := priorityWorkflow.Schedule(ctx, runAt, v1_workflows.PriorityInput{
|
||||
UserId: "1234",
|
||||
}, client.WithPriority(schedulePriority))
|
||||
|
||||
cronId, _ := priorityWorkflow.Cron(ctx, "my-cron", "* * * * *", v1_workflows.PriorityInput{
|
||||
UserId: "1234",
|
||||
}, client.WithPriority(schedulePriority))
|
||||
|
||||
fmt.Println(scheduledRunId)
|
||||
fmt.Println(cronId)
|
||||
|
||||
}
|
||||
109
examples/go/run/simple.go
Normal file
109
examples/go/run/simple.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
v1_workflows "github.com/hatchet-dev/hatchet/examples/go/workflows"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func simple() {
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
hatchet, err := v1.NewHatchetClient()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
// > Running a Task
|
||||
simple := v1_workflows.Simple(hatchet)
|
||||
result, err := simple.Run(ctx, v1_workflows.SimpleInput{
|
||||
Message: "Hello, World!",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(result.TransformedMessage)
|
||||
|
||||
// > Running Multiple Tasks
|
||||
var results []string
|
||||
var resultsMutex sync.Mutex
|
||||
var errs []error
|
||||
var errsMutex sync.Mutex
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
result, err := simple.Run(ctx, v1_workflows.SimpleInput{
|
||||
Message: "Hello, World!",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
errsMutex.Lock()
|
||||
errs = append(errs, err)
|
||||
errsMutex.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
resultsMutex.Lock()
|
||||
results = append(results, result.TransformedMessage)
|
||||
resultsMutex.Unlock()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
result, err := simple.Run(ctx, v1_workflows.SimpleInput{
|
||||
Message: "Hello, Moon!",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
errsMutex.Lock()
|
||||
errs = append(errs, err)
|
||||
errsMutex.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
resultsMutex.Lock()
|
||||
results = append(results, result.TransformedMessage)
|
||||
resultsMutex.Unlock()
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
|
||||
// > Running a Task Without Waiting
|
||||
simple = v1_workflows.Simple(hatchet)
|
||||
runRef, err := simple.RunNoWait(ctx, v1_workflows.SimpleInput{
|
||||
Message: "Hello, World!",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// The Run Ref Exposes an ID that can be used to wait for the task to complete
|
||||
// or check on the status of the task
|
||||
runId := runRef.RunId()
|
||||
fmt.Println(runId)
|
||||
|
||||
// > Subscribing to results
|
||||
// finally, we can wait for the task to complete and get the result
|
||||
finalResult, err := runRef.Result()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(finalResult)
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
v1_workflows "github.com/hatchet-dev/hatchet/examples/v1/workflows"
|
||||
v1_workflows "github.com/hatchet-dev/hatchet/examples/go/workflows"
|
||||
"github.com/hatchet-dev/hatchet/pkg/cmdutils"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/worker"
|
||||
46
examples/go/workflows/cancellations.go
Normal file
46
examples/go/workflows/cancellations.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package v1_workflows
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/create"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/factory"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/workflow"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
type CancellationInput struct{}
|
||||
type CancellationResult struct {
|
||||
Completed bool
|
||||
}
|
||||
|
||||
func Cancellation(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[CancellationInput, CancellationResult] {
|
||||
|
||||
// > Cancelled task
|
||||
// Create a task that sleeps for 10 seconds and checks if it was cancelled
|
||||
cancellation := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "cancellation-task",
|
||||
}, func(ctx worker.HatchetContext, input CancellationInput) (*CancellationResult, error) {
|
||||
// Sleep for 10 seconds
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
// Check if the context was cancelled
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, errors.New("Task was cancelled")
|
||||
default:
|
||||
// Continue execution
|
||||
}
|
||||
|
||||
return &CancellationResult{
|
||||
Completed: true,
|
||||
}, nil
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
return cancellation
|
||||
}
|
||||
200
examples/go/workflows/complex-conditions.go
Normal file
200
examples/go/workflows/complex-conditions.go
Normal file
@@ -0,0 +1,200 @@
|
||||
package v1_workflows
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/create"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/factory"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/workflow"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker/condition"
|
||||
)
|
||||
|
||||
// StepOutput represents the output of most tasks in this workflow
|
||||
type StepOutput struct {
|
||||
RandomNumber int `json:"randomNumber"`
|
||||
}
|
||||
|
||||
// RandomSum represents the output of the sum task
|
||||
type RandomSum struct {
|
||||
Sum int `json:"sum"`
|
||||
}
|
||||
|
||||
// TaskConditionWorkflowResult represents the aggregate output of all tasks
|
||||
type TaskConditionWorkflowResult struct {
|
||||
Start StepOutput `json:"start"`
|
||||
WaitForSleep StepOutput `json:"waitForSleep"`
|
||||
WaitForEvent StepOutput `json:"waitForEvent"`
|
||||
SkipOnEvent StepOutput `json:"skipOnEvent"`
|
||||
LeftBranch StepOutput `json:"leftBranch"`
|
||||
RightBranch StepOutput `json:"rightBranch"`
|
||||
Sum RandomSum `json:"sum"`
|
||||
}
|
||||
|
||||
// taskOpts is a type alias for workflow task options
|
||||
type taskOpts = create.WorkflowTask[struct{}, TaskConditionWorkflowResult]
|
||||
|
||||
func TaskConditionWorkflow(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[struct{}, TaskConditionWorkflowResult] {
|
||||
// > Create a workflow
|
||||
wf := factory.NewWorkflow[struct{}, TaskConditionWorkflowResult](
|
||||
create.WorkflowCreateOpts[struct{}]{
|
||||
Name: "TaskConditionWorkflow",
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
// > Add base task
|
||||
start := wf.Task(
|
||||
taskOpts{
|
||||
Name: "start",
|
||||
},
|
||||
func(ctx worker.HatchetContext, _ struct{}) (interface{}, error) {
|
||||
return &StepOutput{
|
||||
RandomNumber: rand.Intn(100) + 1,
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
|
||||
// > Add wait for sleep
|
||||
waitForSleep := wf.Task(
|
||||
taskOpts{
|
||||
Name: "waitForSleep",
|
||||
Parents: []create.NamedTask{start},
|
||||
WaitFor: condition.SleepCondition(time.Second * 10),
|
||||
},
|
||||
func(ctx worker.HatchetContext, _ struct{}) (interface{}, error) {
|
||||
return &StepOutput{
|
||||
RandomNumber: rand.Intn(100) + 1,
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
|
||||
// > Add skip on event
|
||||
skipOnEvent := wf.Task(
|
||||
taskOpts{
|
||||
Name: "skipOnEvent",
|
||||
Parents: []create.NamedTask{start},
|
||||
WaitFor: condition.SleepCondition(time.Second * 30),
|
||||
SkipIf: condition.UserEventCondition("skip_on_event:skip", "true"),
|
||||
},
|
||||
func(ctx worker.HatchetContext, _ struct{}) (interface{}, error) {
|
||||
return &StepOutput{
|
||||
RandomNumber: rand.Intn(100) + 1,
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
|
||||
// > Add branching
|
||||
leftBranch := wf.Task(
|
||||
taskOpts{
|
||||
Name: "leftBranch",
|
||||
Parents: []create.NamedTask{waitForSleep},
|
||||
SkipIf: condition.ParentCondition(waitForSleep, "output.randomNumber > 50"),
|
||||
},
|
||||
func(ctx worker.HatchetContext, _ struct{}) (interface{}, error) {
|
||||
return &StepOutput{
|
||||
RandomNumber: rand.Intn(100) + 1,
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
|
||||
rightBranch := wf.Task(
|
||||
taskOpts{
|
||||
Name: "rightBranch",
|
||||
Parents: []create.NamedTask{waitForSleep},
|
||||
SkipIf: condition.ParentCondition(waitForSleep, "output.randomNumber <= 50"),
|
||||
},
|
||||
func(ctx worker.HatchetContext, _ struct{}) (interface{}, error) {
|
||||
return &StepOutput{
|
||||
RandomNumber: rand.Intn(100) + 1,
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
|
||||
// > Add wait for event
|
||||
waitForEvent := wf.Task(
|
||||
taskOpts{
|
||||
Name: "waitForEvent",
|
||||
Parents: []create.NamedTask{start},
|
||||
WaitFor: condition.Or(
|
||||
condition.SleepCondition(time.Minute),
|
||||
condition.UserEventCondition("wait_for_event:start", "true"),
|
||||
),
|
||||
},
|
||||
func(ctx worker.HatchetContext, _ struct{}) (interface{}, error) {
|
||||
return &StepOutput{
|
||||
RandomNumber: rand.Intn(100) + 1,
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
|
||||
// > Add sum
|
||||
wf.Task(
|
||||
taskOpts{
|
||||
Name: "sum",
|
||||
Parents: []create.NamedTask{
|
||||
start,
|
||||
waitForSleep,
|
||||
waitForEvent,
|
||||
skipOnEvent,
|
||||
leftBranch,
|
||||
rightBranch,
|
||||
},
|
||||
},
|
||||
func(ctx worker.HatchetContext, _ struct{}) (interface{}, error) {
|
||||
var startOutput StepOutput
|
||||
if err := ctx.ParentOutput(start, &startOutput); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var waitForSleepOutput StepOutput
|
||||
if err := ctx.ParentOutput(waitForSleep, &waitForSleepOutput); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var waitForEventOutput StepOutput
|
||||
ctx.ParentOutput(waitForEvent, &waitForEventOutput)
|
||||
|
||||
// Handle potentially skipped tasks
|
||||
var skipOnEventOutput StepOutput
|
||||
var four int
|
||||
|
||||
err := ctx.ParentOutput(skipOnEvent, &skipOnEventOutput)
|
||||
|
||||
if err != nil {
|
||||
four = 0
|
||||
} else {
|
||||
four = skipOnEventOutput.RandomNumber
|
||||
}
|
||||
|
||||
var leftBranchOutput StepOutput
|
||||
var five int
|
||||
|
||||
err = ctx.ParentOutput(leftBranch, leftBranchOutput)
|
||||
if err != nil {
|
||||
five = 0
|
||||
} else {
|
||||
five = leftBranchOutput.RandomNumber
|
||||
}
|
||||
|
||||
var rightBranchOutput StepOutput
|
||||
var six int
|
||||
|
||||
err = ctx.ParentOutput(rightBranch, rightBranchOutput)
|
||||
if err != nil {
|
||||
six = 0
|
||||
} else {
|
||||
six = rightBranchOutput.RandomNumber
|
||||
}
|
||||
|
||||
return &RandomSum{
|
||||
Sum: startOutput.RandomNumber + waitForEventOutput.RandomNumber +
|
||||
waitForSleepOutput.RandomNumber + four + five + six,
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
|
||||
return wf
|
||||
}
|
||||
86
examples/go/workflows/concurrency-rr.go
Normal file
86
examples/go/workflows/concurrency-rr.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package v1_workflows
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/create"
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/types"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/factory"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/workflow"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
type ConcurrencyInput struct {
|
||||
Message string
|
||||
Tier string
|
||||
Account string
|
||||
}
|
||||
|
||||
type TransformedOutput struct {
|
||||
TransformedMessage string
|
||||
}
|
||||
|
||||
func ConcurrencyRoundRobin(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[ConcurrencyInput, TransformedOutput] {
|
||||
// > Concurrency Strategy With Key
|
||||
var maxRuns int32 = 1
|
||||
strategy := types.GroupRoundRobin
|
||||
|
||||
concurrency := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "simple-concurrency",
|
||||
Concurrency: []*types.Concurrency{
|
||||
{
|
||||
Expression: "input.GroupKey",
|
||||
MaxRuns: &maxRuns,
|
||||
LimitStrategy: &strategy,
|
||||
},
|
||||
},
|
||||
}, func(ctx worker.HatchetContext, input ConcurrencyInput) (*TransformedOutput, error) {
|
||||
// Random sleep between 200ms and 1000ms
|
||||
time.Sleep(time.Duration(200+rand.Intn(800)) * time.Millisecond)
|
||||
|
||||
return &TransformedOutput{
|
||||
TransformedMessage: input.Message,
|
||||
}, nil
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
return concurrency
|
||||
}
|
||||
|
||||
func MultipleConcurrencyKeys(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[ConcurrencyInput, TransformedOutput] {
|
||||
// > Multiple Concurrency Keys
|
||||
strategy := types.GroupRoundRobin
|
||||
var maxRuns int32 = 20
|
||||
|
||||
concurrency := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "simple-concurrency",
|
||||
Concurrency: []*types.Concurrency{
|
||||
{
|
||||
Expression: "input.Tier",
|
||||
MaxRuns: &maxRuns,
|
||||
LimitStrategy: &strategy,
|
||||
},
|
||||
{
|
||||
Expression: "input.Account",
|
||||
MaxRuns: &maxRuns,
|
||||
LimitStrategy: &strategy,
|
||||
},
|
||||
},
|
||||
}, func(ctx worker.HatchetContext, input ConcurrencyInput) (*TransformedOutput, error) {
|
||||
// Random sleep between 200ms and 1000ms
|
||||
time.Sleep(time.Duration(200+rand.Intn(800)) * time.Millisecond)
|
||||
|
||||
return &TransformedOutput{
|
||||
TransformedMessage: input.Message,
|
||||
}, nil
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
return concurrency
|
||||
}
|
||||
@@ -22,16 +22,15 @@ type DagResult struct {
|
||||
}
|
||||
|
||||
func DagWorkflow(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[DagInput, DagResult] {
|
||||
// ❓ Declaring a Workflow
|
||||
// > Declaring a Workflow
|
||||
simple := factory.NewWorkflow[DagInput, DagResult](
|
||||
create.WorkflowCreateOpts[DagInput]{
|
||||
Name: "simple-dag",
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
// ‼️
|
||||
|
||||
// ❓ Defining a Task
|
||||
// > Defining a Task
|
||||
simple.Task(
|
||||
create.WorkflowTask[DagInput, DagResult]{
|
||||
Name: "step",
|
||||
@@ -41,9 +40,8 @@ func DagWorkflow(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[DagInput
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
// ‼️
|
||||
|
||||
// ❓ Adding a Task with a parent
|
||||
// > Adding a Task with a parent
|
||||
step1 := simple.Task(
|
||||
create.WorkflowTask[DagInput, DagResult]{
|
||||
Name: "step-1",
|
||||
@@ -73,7 +71,6 @@ func DagWorkflow(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[DagInput
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
// ‼️
|
||||
|
||||
return simple
|
||||
}
|
||||
77
examples/go/workflows/durable-event.go
Normal file
77
examples/go/workflows/durable-event.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package v1_workflows
|
||||
|
||||
import (
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/create"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/factory"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/workflow"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
type DurableEventInput struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
type EventData struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
type DurableEventOutput struct {
|
||||
Data EventData
|
||||
}
|
||||
|
||||
func DurableEvent(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[DurableEventInput, DurableEventOutput] {
|
||||
// > Durable Event
|
||||
durableEventTask := factory.NewDurableTask(
|
||||
create.StandaloneTask{
|
||||
Name: "durable-event",
|
||||
},
|
||||
func(ctx worker.DurableHatchetContext, input DurableEventInput) (*DurableEventOutput, error) {
|
||||
eventData, err := ctx.WaitForEvent("user:update", "")
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v := EventData{}
|
||||
err = eventData.Unmarshal(&v)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &DurableEventOutput{
|
||||
Data: v,
|
||||
}, nil
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
factory.NewDurableTask(
|
||||
create.StandaloneTask{
|
||||
Name: "durable-event",
|
||||
},
|
||||
func(ctx worker.DurableHatchetContext, input DurableEventInput) (*DurableEventOutput, error) {
|
||||
// > Durable Event With Filter
|
||||
eventData, err := ctx.WaitForEvent("user:update", "input.user_id == '1234'")
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v := EventData{}
|
||||
err = eventData.Unmarshal(&v)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &DurableEventOutput{
|
||||
Data: v,
|
||||
}, nil
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
return durableEventTask
|
||||
}
|
||||
43
examples/go/workflows/durable-sleep.go
Normal file
43
examples/go/workflows/durable-sleep.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package v1_workflows
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/create"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/factory"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/workflow"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
type DurableSleepInput struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
type DurableSleepOutput struct {
|
||||
TransformedMessage string
|
||||
}
|
||||
|
||||
func DurableSleep(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[DurableSleepInput, DurableSleepOutput] {
|
||||
// > Durable Sleep
|
||||
simple := factory.NewDurableTask(
|
||||
create.StandaloneTask{
|
||||
Name: "durable-sleep",
|
||||
},
|
||||
func(ctx worker.DurableHatchetContext, input DurableSleepInput) (*DurableSleepOutput, error) {
|
||||
_, err := ctx.SleepFor(10 * time.Second)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &DurableSleepOutput{
|
||||
TransformedMessage: strings.ToLower(input.Message),
|
||||
}, nil
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
return simple
|
||||
}
|
||||
@@ -15,7 +15,7 @@ type NonRetryableResult struct{}
|
||||
|
||||
// NonRetryableError returns a workflow which throws a non-retryable error
|
||||
func NonRetryableError(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[NonRetryableInput, NonRetryableResult] {
|
||||
// ❓ Non Retryable Error
|
||||
// > Non Retryable Error
|
||||
retries := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "non-retryable-task",
|
||||
@@ -25,7 +25,6 @@ func NonRetryableError(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[No
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
// ‼️
|
||||
|
||||
return retries
|
||||
}
|
||||
45
examples/go/workflows/on-cron.go
Normal file
45
examples/go/workflows/on-cron.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package v1_workflows
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/create"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/factory"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/workflow"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
type OnCronInput struct {
|
||||
Message string `json:"Message"`
|
||||
}
|
||||
|
||||
type JobResult struct {
|
||||
TransformedMessage string `json:"TransformedMessage"`
|
||||
}
|
||||
|
||||
type OnCronOutput struct {
|
||||
Job JobResult `json:"job"`
|
||||
}
|
||||
|
||||
// > Workflow Definition Cron Trigger
|
||||
func OnCron(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[OnCronInput, OnCronOutput] {
|
||||
// Create a standalone task that transforms a message
|
||||
cronTask := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "on-cron-task",
|
||||
// 👀 add a cron expression
|
||||
OnCron: []string{"0 0 * * *"}, // Run every day at midnight
|
||||
},
|
||||
func(ctx worker.HatchetContext, input OnCronInput) (*OnCronOutput, error) {
|
||||
return &OnCronOutput{
|
||||
Job: JobResult{
|
||||
TransformedMessage: strings.ToLower(input.Message),
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
return cronTask
|
||||
}
|
||||
58
examples/go/workflows/on-event.go
Normal file
58
examples/go/workflows/on-event.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package v1_workflows
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/create"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/factory"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/workflow"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
type EventInput struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
type LowerTaskOutput struct {
|
||||
TransformedMessage string
|
||||
}
|
||||
|
||||
type UpperTaskOutput struct {
|
||||
TransformedMessage string
|
||||
}
|
||||
|
||||
// > Run workflow on event
|
||||
const SimpleEvent = "simple-event:create"
|
||||
|
||||
func Lower(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[EventInput, LowerTaskOutput] {
|
||||
return factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "lower",
|
||||
// 👀 Declare the event that will trigger the workflow
|
||||
OnEvents: []string{SimpleEvent},
|
||||
}, func(ctx worker.HatchetContext, input EventInput) (*LowerTaskOutput, error) {
|
||||
// Transform the input message to lowercase
|
||||
return &LowerTaskOutput{
|
||||
TransformedMessage: strings.ToLower(input.Message),
|
||||
}, nil
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
func Upper(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[EventInput, UpperTaskOutput] {
|
||||
return factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "upper",
|
||||
OnEvents: []string{SimpleEvent},
|
||||
},
|
||||
func(ctx worker.HatchetContext, input EventInput) (*UpperTaskOutput, error) {
|
||||
return &UpperTaskOutput{
|
||||
TransformedMessage: strings.ToUpper(input.Message),
|
||||
}, nil
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
}
|
||||
51
examples/go/workflows/priority.go
Normal file
51
examples/go/workflows/priority.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package v1_workflows
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/create"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/factory"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/workflow"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
type PriorityInput struct {
|
||||
UserId string `json:"userId"`
|
||||
}
|
||||
|
||||
type PriorityOutput struct {
|
||||
TransformedMessage string `json:"TransformedMessage"`
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
Step PriorityOutput
|
||||
}
|
||||
|
||||
func Priority(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[PriorityInput, Result] {
|
||||
// Create a standalone task that transforms a message
|
||||
|
||||
// > Default priority
|
||||
defaultPriority := int32(1)
|
||||
|
||||
workflow := factory.NewWorkflow[PriorityInput, Result](
|
||||
create.WorkflowCreateOpts[PriorityInput]{
|
||||
Name: "priority",
|
||||
DefaultPriority: &defaultPriority,
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
// > Defining a Task
|
||||
workflow.Task(
|
||||
create.WorkflowTask[PriorityInput, Result]{
|
||||
Name: "step",
|
||||
}, func(ctx worker.HatchetContext, input PriorityInput) (interface{}, error) {
|
||||
time.Sleep(time.Second * 5)
|
||||
return &PriorityOutput{
|
||||
TransformedMessage: input.UserId,
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
return workflow
|
||||
}
|
||||
95
examples/go/workflows/ratelimit.go
Normal file
95
examples/go/workflows/ratelimit.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package v1_workflows
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/create"
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/types"
|
||||
v1 "github.com/hatchet-dev/hatchet/pkg/v1"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/factory"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/features"
|
||||
"github.com/hatchet-dev/hatchet/pkg/v1/workflow"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
type RateLimitInput struct {
|
||||
UserId string `json:"userId"`
|
||||
}
|
||||
|
||||
type RateLimitOutput struct {
|
||||
TransformedMessage string `json:"TransformedMessage"`
|
||||
}
|
||||
|
||||
func upsertRateLimit(hatchet v1.HatchetClient) {
|
||||
// > Upsert Rate Limit
|
||||
hatchet.RateLimits().Upsert(
|
||||
features.CreateRatelimitOpts{
|
||||
Key: "api-service-rate-limit",
|
||||
Limit: 10,
|
||||
Duration: types.Second,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// > Static Rate Limit
|
||||
func StaticRateLimit(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[RateLimitInput, RateLimitOutput] {
|
||||
// Create a standalone task that transforms a message
|
||||
|
||||
// define the parameters for the rate limit
|
||||
rateLimitKey := "api-service-rate-limit"
|
||||
units := 1
|
||||
|
||||
rateLimitTask := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "rate-limit-task",
|
||||
// 👀 add a static rate limit
|
||||
RateLimits: []*types.RateLimit{
|
||||
{
|
||||
Key: rateLimitKey,
|
||||
Units: &units,
|
||||
},
|
||||
},
|
||||
},
|
||||
func(ctx worker.HatchetContext, input RateLimitInput) (*RateLimitOutput, error) {
|
||||
return &RateLimitOutput{
|
||||
TransformedMessage: strings.ToLower(input.UserId),
|
||||
}, nil
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
return rateLimitTask
|
||||
}
|
||||
|
||||
|
||||
// > Dynamic Rate Limit
|
||||
func RateLimit(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[RateLimitInput, RateLimitOutput] {
|
||||
// Create a standalone task that transforms a message
|
||||
|
||||
// define the parameters for the rate limit
|
||||
expression := "input.userId"
|
||||
units := 1
|
||||
duration := types.Second
|
||||
|
||||
rateLimitTask := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "rate-limit-task",
|
||||
// 👀 add a dynamic rate limit
|
||||
RateLimits: []*types.RateLimit{
|
||||
{
|
||||
KeyExpr: &expression,
|
||||
Units: &units,
|
||||
Duration: &duration,
|
||||
},
|
||||
},
|
||||
},
|
||||
func(ctx worker.HatchetContext, input RateLimitInput) (*RateLimitOutput, error) {
|
||||
return &RateLimitOutput{
|
||||
TransformedMessage: strings.ToLower(input.UserId),
|
||||
}, nil
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
return rateLimitTask
|
||||
}
|
||||
@@ -16,7 +16,7 @@ type RetriesResult struct{}
|
||||
|
||||
// Simple retries example that always fails
|
||||
func Retries(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[RetriesInput, RetriesResult] {
|
||||
// ❓ Simple Step Retries
|
||||
// > Simple Step Retries
|
||||
retries := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "retries-task",
|
||||
@@ -26,7 +26,6 @@ func Retries(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[RetriesInput
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
// ‼️
|
||||
|
||||
return retries
|
||||
}
|
||||
@@ -38,7 +37,7 @@ type RetriesWithCountResult struct {
|
||||
|
||||
// Retries example that succeeds after a certain number of retries
|
||||
func RetriesWithCount(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[RetriesWithCountInput, RetriesWithCountResult] {
|
||||
// ❓ Retries with Count
|
||||
// > Retries with Count
|
||||
retriesWithCount := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "fail-twice-task",
|
||||
@@ -59,7 +58,6 @@ func RetriesWithCount(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[Ret
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
// ‼️
|
||||
|
||||
return retriesWithCount
|
||||
}
|
||||
@@ -69,7 +67,7 @@ type BackoffResult struct{}
|
||||
|
||||
// Retries example with simple backoff (no configuration in this API version)
|
||||
func WithBackoff(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[BackoffInput, BackoffResult] {
|
||||
// ❓ Retries with Backoff
|
||||
// > Retries with Backoff
|
||||
withBackoff := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "with-backoff-task",
|
||||
@@ -85,7 +83,6 @@ func WithBackoff(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[BackoffI
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
// ‼️
|
||||
|
||||
return withBackoff
|
||||
}
|
||||
@@ -25,7 +25,7 @@ func Simple(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[SimpleInput,
|
||||
// Create a simple standalone task using the task factory
|
||||
// Note the use of typed generics for both input and output
|
||||
|
||||
// ❓ Declaring a Task
|
||||
// > Declaring a Task
|
||||
simple := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "simple-task",
|
||||
@@ -37,23 +37,21 @@ func Simple(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[SimpleInput,
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
// ‼️
|
||||
|
||||
// Example of running a task
|
||||
_ = func() error {
|
||||
// ❓ Running a Task
|
||||
// > Running a Task
|
||||
result, err := simple.Run(context.Background(), SimpleInput{Message: "Hello, World!"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(result.TransformedMessage)
|
||||
// ‼️
|
||||
return nil
|
||||
}
|
||||
|
||||
// Example of registering a task on a worker
|
||||
_ = func() error {
|
||||
// ❓ Declaring a Worker
|
||||
// > Declaring a Worker
|
||||
w, err := hatchet.Worker(v1worker.WorkerOpts{
|
||||
Name: "simple-worker",
|
||||
Workflows: []workflow.WorkflowBase{
|
||||
@@ -67,7 +65,6 @@ func Simple(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[SimpleInput,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// ‼️
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -76,7 +73,7 @@ func Simple(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[SimpleInput,
|
||||
|
||||
func ParentTask(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[SimpleInput, SimpleResult] {
|
||||
|
||||
// ❓ Spawning Tasks from within a Task
|
||||
// > Spawning Tasks from within a Task
|
||||
simple := Simple(hatchet)
|
||||
|
||||
parent := factory.NewTask(
|
||||
@@ -97,7 +94,6 @@ func ParentTask(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[SimpleInp
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
// ‼️
|
||||
|
||||
return parent
|
||||
}
|
||||
@@ -18,6 +18,7 @@ type TimeoutResult struct {
|
||||
|
||||
func Timeout(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[TimeoutInput, TimeoutResult] {
|
||||
|
||||
// > Execution Timeout
|
||||
// Create a task with a timeout of 3 seconds that tries to sleep for 10 seconds
|
||||
timeout := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
@@ -30,7 +31,40 @@ func Timeout(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[TimeoutInput
|
||||
// Check if the context was cancelled due to timeout
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, errors.New("Task timed out")
|
||||
return nil, errors.New("TASK TIMED OUT")
|
||||
default:
|
||||
// Continue execution
|
||||
}
|
||||
|
||||
return &TimeoutResult{
|
||||
Completed: true,
|
||||
}, nil
|
||||
},
|
||||
hatchet,
|
||||
)
|
||||
|
||||
return timeout
|
||||
}
|
||||
|
||||
func RefreshTimeout(hatchet v1.HatchetClient) workflow.WorkflowDeclaration[TimeoutInput, TimeoutResult] {
|
||||
|
||||
// > Refresh Timeout
|
||||
timeout := factory.NewTask(
|
||||
create.StandaloneTask{
|
||||
Name: "timeout-task",
|
||||
ExecutionTimeout: 3 * time.Second, // Task will timeout after 3 seconds
|
||||
}, func(ctx worker.HatchetContext, input TimeoutInput) (*TimeoutResult, error) {
|
||||
|
||||
// Refresh the timeout by 10 seconds (new timeout will be 13 seconds)
|
||||
ctx.RefreshTimeout("10s")
|
||||
|
||||
// Sleep for 10 seconds
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
// Check if the context was cancelled due to timeout
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, errors.New("TASK TIMED OUT")
|
||||
default:
|
||||
// Continue execution
|
||||
}
|
||||
@@ -26,7 +26,7 @@ func run() (func() error, error) {
|
||||
return nil, fmt.Errorf("error creating worker: %w", err)
|
||||
}
|
||||
|
||||
// ❓ StickyWorker
|
||||
// > StickyWorker
|
||||
|
||||
err = w.RegisterWorkflow(
|
||||
&worker.WorkflowJob{
|
||||
@@ -66,13 +66,12 @@ func run() (func() error, error) {
|
||||
},
|
||||
)
|
||||
|
||||
// ‼️
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error registering workflow: %w", err)
|
||||
}
|
||||
|
||||
// ❓ StickyChild
|
||||
// > StickyChild
|
||||
|
||||
err = w.RegisterWorkflow(
|
||||
&worker.WorkflowJob{
|
||||
@@ -89,7 +88,6 @@ func run() (func() error, error) {
|
||||
},
|
||||
)
|
||||
|
||||
// ‼️
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error registering workflow: %w", err)
|
||||
143
examples/go/z_v0/cron-programmatic/main.go
Normal file
143
examples/go/z_v0/cron-programmatic/main.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client"
|
||||
"github.com/hatchet-dev/hatchet/pkg/cmdutils"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
// > Create
|
||||
// ... normal workflow definition
|
||||
type printOutput struct{}
|
||||
|
||||
func print(ctx context.Context) (result *printOutput, err error) {
|
||||
fmt.Println("called print:print")
|
||||
|
||||
return &printOutput{}, nil
|
||||
}
|
||||
|
||||
// ,
|
||||
func main() {
|
||||
// ... initialize client, worker and workflow
|
||||
err := godotenv.Load()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c, err := client.New()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
w, err := worker.NewWorker(
|
||||
worker.WithClient(
|
||||
c,
|
||||
),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = w.RegisterWorkflow(
|
||||
&worker.WorkflowJob{
|
||||
On: worker.NoTrigger(),
|
||||
Name: "cron-workflow",
|
||||
Description: "Demonstrates a simple cron workflow",
|
||||
Steps: []*worker.WorkflowStep{
|
||||
worker.Fn(print),
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
interrupt := cmdutils.InterruptChan()
|
||||
|
||||
cleanup, err := w.Start()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// ,
|
||||
|
||||
go func() {
|
||||
// 👀 define the cron expression to run every minute
|
||||
cron, err := c.Cron().Create(
|
||||
context.Background(),
|
||||
"cron-workflow",
|
||||
&client.CronOpts{
|
||||
Name: "every-minute",
|
||||
Expression: "* * * * *",
|
||||
Input: map[string]interface{}{
|
||||
"message": "Hello, world!",
|
||||
},
|
||||
AdditionalMetadata: map[string]string{},
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(*cron.Name, cron.Cron)
|
||||
}()
|
||||
|
||||
// ... wait for interrupt signal
|
||||
|
||||
<-interrupt
|
||||
|
||||
if err := cleanup(); err != nil {
|
||||
panic(fmt.Errorf("error cleaning up: %w", err))
|
||||
}
|
||||
|
||||
// ,
|
||||
}
|
||||
|
||||
|
||||
func ListCrons() {
|
||||
|
||||
c, err := client.New()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// > List
|
||||
crons, err := c.Cron().List(context.Background())
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, cron := range *crons.Rows {
|
||||
fmt.Println(cron.Cron, *cron.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteCron(id string) {
|
||||
c, err := client.New()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// > Delete
|
||||
// 👀 id is the cron's metadata id, can get it via cron.Metadata.Id
|
||||
err = c.Cron().Delete(context.Background(), id)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
}
|
||||
83
examples/go/z_v0/cron/main.go
Normal file
83
examples/go/z_v0/cron/main.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client"
|
||||
"github.com/hatchet-dev/hatchet/pkg/cmdutils"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
// > Workflow Definition Cron Trigger
|
||||
// ... normal workflow definition
|
||||
type printOutput struct{}
|
||||
|
||||
func print(ctx context.Context) (result *printOutput, err error) {
|
||||
fmt.Println("called print:print")
|
||||
|
||||
return &printOutput{}, nil
|
||||
}
|
||||
|
||||
// ,
|
||||
func main() {
|
||||
// ... initialize client and worker
|
||||
err := godotenv.Load()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
client, err := client.New()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
w, err := worker.NewWorker(
|
||||
worker.WithClient(
|
||||
client,
|
||||
),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// ,
|
||||
err = w.RegisterWorkflow(
|
||||
&worker.WorkflowJob{
|
||||
// 👀 define the cron expression to run every minute
|
||||
On: worker.Cron("* * * * *"),
|
||||
Name: "cron-workflow",
|
||||
Description: "Demonstrates a simple cron workflow",
|
||||
Steps: []*worker.WorkflowStep{
|
||||
worker.Fn(print),
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// ... start worker
|
||||
|
||||
interrupt := cmdutils.InterruptChan()
|
||||
|
||||
cleanup, err := w.Start()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
<-interrupt
|
||||
|
||||
if err := cleanup(); err != nil {
|
||||
panic(fmt.Errorf("error cleaning up: %w", err))
|
||||
}
|
||||
|
||||
// ,
|
||||
}
|
||||
@@ -77,10 +77,6 @@ func do(duration time.Duration, startEventsPerSecond, amount int, increase, dela
|
||||
|
||||
time.Sleep(after)
|
||||
|
||||
close(scheduled)
|
||||
close(executed)
|
||||
close(hook)
|
||||
|
||||
log.Printf("✅ success")
|
||||
|
||||
return nil
|
||||
@@ -30,11 +30,6 @@ func emit(ctx context.Context, startEventsPerSecond, amount int, increase, durat
|
||||
var eventsPerSecond int
|
||||
go func() {
|
||||
took := <-hook
|
||||
|
||||
if took == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
panic(fmt.Errorf("event took too long to schedule: %s at %d events/s", took, eventsPerSecond))
|
||||
}()
|
||||
for {
|
||||
107
examples/go/z_v0/on-failure/main.go
Normal file
107
examples/go/z_v0/on-failure/main.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client"
|
||||
"github.com/hatchet-dev/hatchet/pkg/cmdutils"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
type stepOneOutput struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// > OnFailure Step
|
||||
// This workflow will fail because the step will throw an error
|
||||
// we define an onFailure step to handle this case
|
||||
|
||||
func StepOne(ctx worker.HatchetContext) (result *stepOneOutput, err error) {
|
||||
// 👀 this step will always raise an exception
|
||||
return nil, fmt.Errorf("test on failure")
|
||||
}
|
||||
|
||||
func OnFailure(ctx worker.HatchetContext) (result *stepOneOutput, err error) {
|
||||
// run cleanup code or notifications here
|
||||
|
||||
// 👀 you can access the error from the failed step(s) like this
|
||||
fmt.Println(ctx.StepRunErrors())
|
||||
|
||||
return &stepOneOutput{
|
||||
Message: "Failure!",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
// ...
|
||||
err := godotenv.Load()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c, err := client.New()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
w, err := worker.NewWorker(
|
||||
worker.WithClient(
|
||||
c,
|
||||
),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 👀 we define an onFailure step to handle this case
|
||||
err = w.On(
|
||||
worker.NoTrigger(),
|
||||
&worker.WorkflowJob{
|
||||
Name: "on-failure-workflow",
|
||||
Description: "This runs at a scheduled time.",
|
||||
Steps: []*worker.WorkflowStep{
|
||||
worker.Fn(StepOne).SetName("step-one"),
|
||||
},
|
||||
OnFailure: &worker.WorkflowJob{
|
||||
Name: "scheduled-workflow-failure",
|
||||
Description: "This runs when the scheduled workflow fails.",
|
||||
Steps: []*worker.WorkflowStep{
|
||||
worker.Fn(OnFailure).SetName("on-failure"),
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
// ...
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
interruptCtx, cancel := cmdutils.InterruptContextFromChan(cmdutils.InterruptChan())
|
||||
defer cancel()
|
||||
|
||||
cleanup, err := w.Start()
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error cleaning up: %w", err))
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-interruptCtx.Done():
|
||||
if err := cleanup(); err != nil {
|
||||
panic(fmt.Errorf("error cleaning up: %w", err))
|
||||
}
|
||||
return
|
||||
default:
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
// ,
|
||||
}
|
||||
97
examples/go/z_v0/retries-with-backoff/main.go
Normal file
97
examples/go/z_v0/retries-with-backoff/main.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client"
|
||||
"github.com/hatchet-dev/hatchet/pkg/cmdutils"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
type stepOneOutput struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// > Backoff
|
||||
|
||||
// ... normal function definition
|
||||
func StepOne(ctx worker.HatchetContext) (result *stepOneOutput, err error) {
|
||||
if ctx.RetryCount() < 3 {
|
||||
return nil, fmt.Errorf("failure")
|
||||
}
|
||||
|
||||
return &stepOneOutput{
|
||||
Message: "Success!",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ,
|
||||
|
||||
func main() {
|
||||
// ...
|
||||
err := godotenv.Load()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c, err := client.New()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
w, err := worker.NewWorker(
|
||||
worker.WithClient(
|
||||
c,
|
||||
),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// ,
|
||||
|
||||
err = w.RegisterWorkflow(
|
||||
&worker.WorkflowJob{
|
||||
Name: "retry-with-backoff-workflow",
|
||||
On: worker.NoTrigger(),
|
||||
Description: "Demonstrates retry with exponential backoff.",
|
||||
Steps: []*worker.WorkflowStep{
|
||||
worker.Fn(StepOne).SetName("with-backoff").
|
||||
SetRetries(10).
|
||||
// 👀 Backoff configuration
|
||||
// 👀 Maximum number of seconds to wait between retries
|
||||
SetRetryBackoffFactor(2.0).
|
||||
// 👀 Factor to increase the wait time between retries.
|
||||
// This sequence will be 2s, 4s, 8s, 16s, 32s, 60s... due to the maxSeconds limit
|
||||
SetRetryMaxBackoffSeconds(60),
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
// ...
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
interruptCtx, cancel := cmdutils.InterruptContextFromChan(cmdutils.InterruptChan())
|
||||
defer cancel()
|
||||
|
||||
cleanup, err := w.Start()
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error cleaning up: %w", err))
|
||||
}
|
||||
|
||||
<-interruptCtx.Done()
|
||||
|
||||
if err := cleanup(); err != nil {
|
||||
panic(fmt.Errorf("error cleaning up: %w", err))
|
||||
}
|
||||
|
||||
// ,
|
||||
}
|
||||
142
examples/go/z_v0/scheduled/main.go
Normal file
142
examples/go/z_v0/scheduled/main.go
Normal file
@@ -0,0 +1,142 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/pkg/client"
|
||||
"github.com/hatchet-dev/hatchet/pkg/cmdutils"
|
||||
"github.com/hatchet-dev/hatchet/pkg/worker"
|
||||
)
|
||||
|
||||
// > Create
|
||||
// ... normal workflow definition
|
||||
type printOutput struct{}
|
||||
|
||||
func print(ctx context.Context) (result *printOutput, err error) {
|
||||
fmt.Println("called print:print")
|
||||
|
||||
return &printOutput{}, nil
|
||||
}
|
||||
|
||||
// ,
|
||||
func main() {
|
||||
// ... initialize client, worker and workflow
|
||||
err := godotenv.Load()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c, err := client.New()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
w, err := worker.NewWorker(
|
||||
worker.WithClient(
|
||||
c,
|
||||
),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = w.RegisterWorkflow(
|
||||
&worker.WorkflowJob{
|
||||
On: worker.NoTrigger(),
|
||||
Name: "schedule-workflow",
|
||||
Description: "Demonstrates a simple scheduled workflow",
|
||||
Steps: []*worker.WorkflowStep{
|
||||
worker.Fn(print),
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
interrupt := cmdutils.InterruptChan()
|
||||
|
||||
cleanup, err := w.Start()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// ,
|
||||
|
||||
go func() {
|
||||
// 👀 define the scheduled workflow to run in a minute
|
||||
schedule, err := c.Schedule().Create(
|
||||
context.Background(),
|
||||
"schedule-workflow",
|
||||
&client.ScheduleOpts{
|
||||
// 👀 define the time to run the scheduled workflow, in UTC
|
||||
TriggerAt: time.Now().UTC().Add(time.Minute),
|
||||
Input: map[string]interface{}{
|
||||
"message": "Hello, world!",
|
||||
},
|
||||
AdditionalMetadata: map[string]string{},
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(schedule.TriggerAt, schedule.WorkflowName)
|
||||
}()
|
||||
|
||||
// ... wait for interrupt signal
|
||||
|
||||
<-interrupt
|
||||
|
||||
if err := cleanup(); err != nil {
|
||||
panic(fmt.Errorf("error cleaning up: %w", err))
|
||||
}
|
||||
|
||||
// ,
|
||||
}
|
||||
|
||||
|
||||
func ListScheduledWorkflows() {
|
||||
c, err := client.New()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// > List
|
||||
schedules, err := c.Schedule().List(context.Background())
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, schedule := range *schedules.Rows {
|
||||
fmt.Println(schedule.TriggerAt, schedule.WorkflowName)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteScheduledWorkflow(id string) {
|
||||
c, err := client.New()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// > Delete
|
||||
// 👀 id is the schedule's metadata id, can get it via schedule.Metadata.Id
|
||||
err = c.Schedule().Delete(context.Background(), id)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ func main() {
|
||||
|
||||
events := make(chan string, 50)
|
||||
|
||||
// ❓ TimeoutStep
|
||||
// > TimeoutStep
|
||||
cleanup, err := run(events, worker.WorkflowJob{
|
||||
Name: "timeout",
|
||||
Description: "timeout",
|
||||
@@ -38,7 +38,6 @@ func main() {
|
||||
}).SetName("step-one").SetTimeout("10s"),
|
||||
},
|
||||
})
|
||||
// ‼️
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
0
examples/python/__init__.py
Normal file
0
examples/python/__init__.py
Normal file
6
examples/python/affinity_workers/trigger.py
Normal file
6
examples/python/affinity_workers/trigger.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from examples.affinity_workers.worker import affinity_worker_workflow
|
||||
from hatchet_sdk import TriggerWorkflowOptions
|
||||
|
||||
affinity_worker_workflow.run(
|
||||
options=TriggerWorkflowOptions(additional_metadata={"hello": "moon"}),
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user