Dapr Go SDK

repository·main·Indexed 19 days ago

https://github.com/dapr/go-sdk

A client library providing idiomatic Go wrappers for public Dapr APIs, including state management, pub/sub, service invocation, and actor patterns. It enables Go developers to build applications that interact with the Dapr runtime, supporting both HTTP and gRPC protocols.

Tokens
18.2K
Snippets
67
Records
75
Agent score
65%

What's inside dapr-go-sdk

  1. Host actors over gRPC using SubscribeActorEventsAlpha1

    main

    You can host actors using an app-initiated actor event stream (SubscribeActorEventsAlpha1) instead of exposing standard HTTP actor endpoints. In this model, the application dials the Dapr sidecar's gRPC port and receives all actor callbacks—including method invocations, reminders, timers, and deactivations—over a single bidirectional stream.

    Important Requirements:

    • This feature is currently in Alpha.
    • The Dapr sidecar must be run with the --app-protocol grpc flag.
    • The application must listen on a gRPC port (e.g., :50051) to back the sidecar's app channel.

    Key Behavior:

    • Actor callbacks are delivered over the event stream, not via direct calls to the application's gRPC port.
    • The stream automatically handles reconnections and re-registers actor types if the sidecar restarts or the stream drops.
    // The implementation logic is similar to the standard HTTP actor example,
    // but uses the client.SubscribeActorEvents method to host the actor.
    client.SubscribeActorEvents(...)
  2. Manage State with the Dapr client

    main

    The Dapr Go client provides simple methods for state management, as well as advanced options for bulk operations and transactions.

    Simple State Operations

    Use SaveState, GetState, and DeleteState for basic key-value operations.

    Advanced State Operations

    • Bulk Operations: Use SaveBulkState to save multiple *dapr.SetStateItem objects at once, or GetBulkState to retrieve multiple keys in a single call.
    • Transactions: Use ExecuteStateTransaction to perform multiple upsert or delete operations atomically using *dapr.StateOperation objects.
    // Simple Save
    if err := client.SaveState(ctx, store, "key1", data, nil); err != nil {
        panic(err)
    }
    
    // Bulk Save with SetStateItem
    item1 := &dapr.SetStateItem{
        Key:   "key1",
        Value: []byte("hello"),
        Options: &dapr.StateOptions{
            Concurrency: dapr.StateConcurrencyLastWrite,
            Consistency: dapr.StateConsistencyStrong,
        },
    }
    if err := client.SaveBulkState(ctx, store, item1); err != nil {
        panic(err)
    }
    
    // Transactional Operations
    ops := []*dapr.StateOperation{
        {
            Type: dapr.StateOperationTypeUpsert,
            Item: &dapr.SetStateItem{Key: "key1", Value: []byte(data)},
        },
        {
            Type: dapr.StateOperationTypeDelete,
            Item: &dapr.SetStateItem{Key: "key2"},
        },
    }
    err := client.ExecuteStateTransaction(ctx, store, map[string]string{}, ops)
  3. Configure Dapr API Authentication

    main

    If your Dapr sidecar is configured with token-based authentication, you can provide the token in two ways:

    1. Environment Variable: Set DAPR_API_TOKEN. The SDK will automatically use this for all invocations.
    2. Explicitly on Client: Use the WithAuthToken method on a client instance. This is useful if you need to manage multiple clients with different tokens.
    client, err := dapr.NewClient()
    if err != nil {
        panic(err)
    }
    defer client.Close()
    client.WithAuthToken("your-Dapr-API-token-here")
  4. Perform State Management operations

    main

    The Dapr Go SDK provides several ways to interact with a state store:

    Simple Operations

    Use SaveState, GetState, and DeleteState for basic key-value operations.

    Bulk and Transactional Operations

    • Bulk Save: Use SaveBulkState to save multiple *dapr.SetStateItem objects at once.
    • Bulk Get: Use GetBulkState to retrieve multiple keys in a single operation.
    • Transactions: Use ExecuteStateTransaction to execute multiple *dapr.StateOperation (Upsert or Delete) operations atomically.

    Querying State

    Use QueryState to retrieve, filter, and sort data. Note: This API is currently in alpha.

    Granular Control

    The dapr.SetStateItem type allows you to specify Etag, Metadata, and dapr.StateOptions (for Concurrency and Consistency) for individual items.

    // Simple Save/Get/Delete
    if err := client.SaveState(ctx, store, "key1", data, nil); err != nil { panic(err) }
    item, err := client.GetState(ctx, store, "key1", nil)
    if err := client.DeleteState(ctx, store, "key1", nil); err != nil { panic(err) }
    
    // Bulk Save
    item1 := &dapr.SetStateItem{
        Key: "key1",
        Value: []byte("hello"),
        Options: &dapr.StateOptions{
            Concurrency: dapr.StateConcurrencyLastWrite,
            Consistency: dapr.StateConsistencyStrong,
        },
    }
    client.SaveBulkState(ctx, store, item1)
    
    // Transactional
    ops := []*dapr.StateOperation{
        {Type: dapr.StateOperationTypeUpsert, Item: &dapr.SetStateItem{Key: "key1", Value: data}},
        {Type: dapr.StateOperationTypeDelete, Item: &dapr.SetStateItem{Key: "key2"}},
    }
    client.ExecuteStateTransaction(ctx, store, meta, ops)
    
    // Query (Alpha)
    query := `{"filter": {"EQ": {"value.Id": "1"}}, "sort": [{"key": "value.Balance", "order": "DESC"}]}`
    queryResponse, err := client.QueryState(ctx, "querystore", query)
  5. Quickstart: Hello World with Dapr Go SDK

    main

    This tutorial demonstrates how to instrument a Go application with Dapr to perform state management operations (Save, Get, Delete) and run it locally using the Dapr CLI.

    Prerequisites

    Workflow

    1. Build the application: Use go build to create the executable.
    2. Run with Dapr: Use the dapr run command to launch your application within the Dapr runtime.
    3. Interact with State: Use the application's CLI commands to trigger Dapr sidecar operations like put, get, or del.
    # Build the app
    go mod vendor
    go build -o order order.go
    
    # Run the app with Dapr to persist state
    dapr run --app-id order-app --dapr-grpc-port 3500 --log-level error -- ./order put --id 20
    
    # Run the app with Dapr to retrieve state
    dapr run --app-id order-app --dapr-grpc-port 3500 --log-level error ./order get
  6. Run the Dapr Go client example

    main

    The examples/service directory demonstrates a complete interaction pattern between a serving app (the provider) and a client app (the consumer). The serving app can be configured to use either HTTP or gRPC protocols. The client app uses the Dapr Go SDK to interact with state, events, and service invocation.

    Prerequisites

    • Dapr must be installed on your system.
    • Configuration files must be available in a ./config directory.
    ### 1. Start the serving app (HTTP mode)
    ```bash
    dapr run --app-id serving \
             --app-protocol http \
             --app-port 8080 \
             --dapr-http-port 3500 \
             --log-level debug \
             --resources-path ./config \
             go run ./serving/http/main.go

    2. Start the client app

    dapr run --app-id caller \
             --resources-path ./config \
             --log-level debug \
             go run ./client/main.go
  7. Run a Dapr application with Unix domain sockets

    main

    To run an application using Unix domain sockets, use the dapr run command with the --unix-domain-socket flag. This flag specifies the directory where the socket file will be created.

    Running a single command with Dapr

    To run a specific command (like put or get) through the Dapr runtime:

    dapr run --app-id order-app --log-level error --unix-domain-socket /tmp -- ./order put --id 20

    Running a standalone Dapr runtime

    Alternatively, you can start the Dapr runtime in the background and call your application directly from another shell:

    1. Start the runtime:
    dapr run --app-id order-app --log-level error --unix-domain-socket /tmp
    1. Execute your app commands:
    ./order put --id 10
    ./order get
  8. Configure Authentication with API Tokens

    main

    If the Dapr API is configured with token-based authentication, you can provide the token in two ways:

    1. Environment Variable: Define DAPR_API_TOKEN. The SDK will automatically use it for all invocations.
    2. Explicit Method: Use client.WithAuthToken("your-token") on a specific client instance. This is useful when managing multiple clients for different endpoints.
    client, err := dapr.NewClient()
    if err != nil {
        panic(err)
    }
    defer client.Close()
    client.WithAuthToken("your-Dapr-API-token-here")
  9. Initialize and start a Dapr HTTP Service

    main

    To create a Dapr HTTP service, import github.com/dapr/go-sdk/service/http and use NewService to specify the listening address. If you have an existing http.ServeMux that you want to integrate with Dapr, use NewServiceWithMux instead. After attaching your handlers (events, bindings, or service invocations), call Start() to begin listening for requests.

    import (
    	"log"
    	"net/http"
    	daprd "github.com/dapr/go-sdk/service/http"
    )
    
    // Option 1: Create a new service with a specific address
    s := daprd.NewService(":8080")
    
    // Option 2: Combine with an existing http.ServeMux
    mux := http.NewServeMux()
    mux.HandleFunc("/", myOtherHandler)
    s := daprd.NewServiceWithMux(":8080", mux)
    
    // Start the service
    if err := s.Start(); err != nil && err != http.ErrServerClosed {
    	log.Fatalf("error: %v", err)
    }