Title here
Summary here
Build and run your first Resolute workflow in 5 minutes.
Start Temporal if you haven’t already:
temporal server start-devmkdir hello-resolute && cd hello-resolute
go mod init hello-resolute
go get github.com/resolute/resolute/coreCreate main.go with a simple 3-step data processing flow:
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/resolute/resolute/core"
)
// Step 1: Fetch data from a source
type FetchInput struct{}
type FetchOutput struct {
Records []string
}
func fetchData(ctx context.Context, input FetchInput) (FetchOutput, error) {
log.Println("π₯ Fetching records...")
// Simulate fetching from an external API
time.Sleep(500 * time.Millisecond)
return FetchOutput{
Records: []string{"record-1", "record-2", "record-3"},
}, nil
}
// Step 2: Process the data
type ProcessInput struct {
Records []string
}
type ProcessOutput struct {
Processed int
Summary string
}
func processData(ctx context.Context, input ProcessInput) (ProcessOutput, error) {
log.Printf("βοΈ Processing %d records...\n", len(input.Records))
time.Sleep(300 * time.Millisecond)
return ProcessOutput{
Processed: len(input.Records),
Summary: fmt.Sprintf("Processed %d records successfully", len(input.Records)),
}, nil
}
// Step 3: Store the results
type StoreInput struct {
Summary string
}
type StoreOutput struct {
StorageKey string
}
func storeResults(ctx context.Context, input StoreInput) (StoreOutput, error) {
log.Printf("πΎ Storing: %s\n", input.Summary)
time.Sleep(200 * time.Millisecond)
return StoreOutput{
StorageKey: fmt.Sprintf("results-%d", time.Now().Unix()),
}, nil
}
func main() {
// Define nodes for each step
fetchNode := core.NewNode("fetch", fetchData, FetchInput{}).
WithTimeout(1 * time.Minute)
processNode := core.NewNode("process", processData, ProcessInput{}).
WithTimeout(2 * time.Minute)
storeNode := core.NewNode("store", storeResults, StoreInput{}).
WithTimeout(30 * time.Second)
// Build the flow
flow := core.NewFlow("hello-flow").
TriggeredBy(core.Manual("api")).
Then(fetchNode).
Then(processNode).
Then(storeNode).
Build()
log.Printf("π Starting worker for flow: %s\n", flow.Name())
// Run the worker
core.NewWorker().
WithConfig(core.WorkerConfig{
TaskQueue: "hello-queue",
TemporalHost: "localhost:7233",
}).
WithFlow(flow).
Run()
}go run main.goYou should see:
π Starting worker for flow: hello-flowThe worker is now listening for workflow executions.
Open a new terminal and trigger the workflow:
temporal workflow start \
--task-queue hello-queue \
--type hello-flow \
--workflow-id my-first-workflowBack in your worker terminal, you’ll see:
π₯ Fetching records...
βοΈ Processing 3 records...
πΎ Storing: Processed 3 records successfullyOpen http://localhost:8233 in your browser.
You’ll see your workflow execution with:
ββββββββββββββββββββββββββββββββββββββββββββββββ
β hello-flow β
β Trigger: Manual (API) β
ββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββ βββββββββββ βββββββββββ β
β β fetch β β β process β β β store β β
β βββββββββββ βββββββββββ βββββββββββ β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββKey concepts demonstrated:
| Concept | What You Used |
|---|---|
| Flow | NewFlow("hello-flow") - defines the workflow |
| Trigger | Manual("api") - starts via API/CLI |
| Nodes | NewNode(...) - wraps activities with typed I/O |
| Worker | NewWorker() - executes the flow |
| Configuration | WithTimeout(), WorkerConfig |
Resolute provides automatic retries. Enhance your fetch node:
fetchNode := core.NewNode("fetch", fetchData, FetchInput{}).
WithTimeout(1 * time.Minute).
WithRetry(core.RetryPolicy{
InitialInterval: time.Second,
BackoffCoefficient: 2.0,
MaximumInterval: 30 * time.Second,
MaximumAttempts: 5,
})If fetchData fails, Temporal will automatically retry up to 5 times with exponential backoff.
You’ve built your first Resolute workflow! Continue learning: