Bindings

Creating a binding component requires just a few basic steps.

Import bindings packages

Create the file components/inputbinding.go and add import statements for the state store related packages.

  1. package components
  2. import (
  3. "context"
  4. "github.com/dapr/components-contrib/bindings"
  5. )

Input bindings: Implement the InputBinding interface

Create a type that implements the InputBinding interface.

  1. type MyInputBindingComponent struct {
  2. }
  3. func (component *MyInputBindingComponent) Init(meta bindings.Metadata) error {
  4. // Called to initialize the component with its configured metadata...
  5. }
  6. func (component *MyInputBindingComponent) Read(ctx context.Context, handler bindings.Handler) error {
  7. // Until canceled, check the underlying store for messages and deliver them to the Dapr runtime...
  8. }

Calls to the Read() method are expected to set up a long-lived mechanism for retrieving messages but immediately return nil (or an error, if that mechanism could not be set up). The mechanism should end when canceled (for example, via the ctx.Done() or ctx.Err() != nil). As messages are read from the underlying store of the component, they are delivered to the Dapr runtime via the handler callback, which does not return until the application (served by the Dapr runtime) acknowledges processing of the message.

  1. func (b *MyInputBindingComponent) Read(ctx context.Context, handler bindings.Handler) error {
  2. go func() {
  3. for {
  4. err := ctx.Err()
  5. if err != nil {
  6. return
  7. }
  8. messages := // Poll for messages...
  9. for _, message := range messages {
  10. handler(ctx, &bindings.ReadResponse{
  11. // Set the message content...
  12. })
  13. }
  14. select {
  15. case <-ctx.Done():
  16. case <-time.After(5 * time.Second):
  17. }
  18. }
  19. }()
  20. return nil
  21. }

Output bindings: Implement the OutputBinding interface

Create a type that implements the OutputBinding interface.

  1. type MyOutputBindingComponent struct {
  2. }
  3. func (component *MyOutputBindingComponent) Init(meta bindings.Metadata) error {
  4. // Called to initialize the component with its configured metadata...
  5. }
  6. func (component *MyOutputBindingComponent) Invoke(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
  7. // Called to invoke a specific operation...
  8. }
  9. func (component *MyOutputBindingComponent) Operations() []bindings.OperationKind {
  10. // Called to list the operations that can be invoked.
  11. }

Input and output binding components

A component can be both an input and output binding. Simply implement both interfaces and register the component as both binding types.

Register binding component

In the main application file (for example, main.go), register the binding component with the application.

  1. package main
  2. import (
  3. "example/components"
  4. dapr "github.com/dapr-sandbox/components-go-sdk"
  5. "github.com/dapr-sandbox/components-go-sdk/bindings/v1"
  6. )
  7. func main() {
  8. // Register an import binding...
  9. dapr.Register("my-inputbinding", dapr.WithInputBinding(func() bindings.InputBinding {
  10. return &components.MyInputBindingComponent{}
  11. }))
  12. // Register an output binding...
  13. dapr.Register("my-outputbinding", dapr.WithOutputBinding(func() bindings.OutputBinding {
  14. return &components.MyOutputBindingComponent{}
  15. }))
  16. dapr.MustRun()
  17. }

Next steps