Skip to content

Commit a337386

Browse files
Run snipsync
1 parent 1562976 commit a337386

1 file changed

Lines changed: 123 additions & 0 deletions

File tree

docs/develop/go/context-propagation.mdx

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,102 @@ Here is a propagator that carries a custom key-value pair from the Client to Wor
5656

5757

5858
<!--SNIPSTART samples-go-ctx-propagation-propagator-->
59+
[ctxpropagation/propagator.go](https://github.com/temporalio/samples-go/blob/main/ctxpropagation/propagator.go)
60+
```go
61+
type (
62+
// contextKey is an unexported type used as key for items stored in the
63+
// Context object
64+
contextKey struct{}
65+
66+
// propagator implements the custom context propagator
67+
propagator struct{}
68+
69+
// Values is a struct holding values
70+
Values struct {
71+
Key string `json:"key"`
72+
Value string `json:"value"`
73+
}
74+
)
75+
76+
// PropagateKey is the key used to store the value in the Context object
77+
var PropagateKey = contextKey{}
78+
79+
// HeaderKey is the key used by the propagator to pass values through the
80+
// Temporal server headers
81+
const HeaderKey = "custom-header"
82+
83+
// NewContextPropagator returns a context propagator that propagates a set of
84+
// string key-value pairs across a workflow
85+
func NewContextPropagator() workflow.ContextPropagator {
86+
return &propagator{}
87+
}
88+
89+
// Inject injects values from context into headers for propagation
90+
func (s *propagator) Inject(ctx context.Context, writer workflow.HeaderWriter) error {
91+
value := ctx.Value(PropagateKey)
92+
payload, err := converter.GetDefaultDataConverter().ToPayload(value)
93+
if err != nil {
94+
return err
95+
}
96+
writer.Set(HeaderKey, payload)
97+
return nil
98+
}
99+
100+
// InjectFromWorkflow injects values from context into headers for propagation
101+
func (s *propagator) InjectFromWorkflow(ctx workflow.Context, writer workflow.HeaderWriter) error {
102+
value := ctx.Value(PropagateKey)
103+
payload, err := converter.GetDefaultDataConverter().ToPayload(value)
104+
if err != nil {
105+
return err
106+
}
107+
writer.Set(HeaderKey, payload)
108+
return nil
109+
}
110+
111+
// Extract extracts values from headers and puts them into context
112+
func (s *propagator) Extract(ctx context.Context, reader workflow.HeaderReader) (context.Context, error) {
113+
if value, ok := reader.Get(HeaderKey); ok {
114+
var values Values
115+
if err := converter.GetDefaultDataConverter().FromPayload(value, &values); err != nil {
116+
return ctx, nil
117+
}
118+
ctx = context.WithValue(ctx, PropagateKey, values)
119+
}
120+
121+
return ctx, nil
122+
}
123+
```
59124
<!--SNIPEND-->
60125

61126
## Register the propagator and set context values
62127

63128
Register the propagator on the Client. Then set context values before starting a Workflow:
64129

65130
<!--SNIPSTART samples-go-ctx-propagation-starter-->
131+
[ctxpropagation/starter/main.go](https://github.com/temporalio/samples-go/blob/main/ctxpropagation/starter/main.go)
132+
```go
133+
// The client is a heavyweight object that should be created once per process.
134+
c, err := client.Dial(client.Options{
135+
HostPort: client.DefaultHostPort,
136+
Interceptors: []interceptor.ClientInterceptor{tracingInterceptor},
137+
ContextPropagators: []workflow.ContextPropagator{ctxpropagation.NewContextPropagator()},
138+
})
139+
if err != nil {
140+
log.Fatalln("Unable to create client", err)
141+
}
142+
defer c.Close()
143+
144+
workflowID := "ctx-propagation_" + uuid.New()
145+
workflowOptions := client.StartWorkflowOptions{
146+
ID: workflowID,
147+
TaskQueue: "ctx-propagation",
148+
}
149+
150+
ctx := context.Background()
151+
ctx = context.WithValue(ctx, ctxpropagation.PropagateKey, &ctxpropagation.Values{Key: "test", Value: "tested"})
152+
153+
we, err := c.ExecuteWorkflow(ctx, workflowOptions, ctxpropagation.CtxPropWorkflow)
154+
```
66155
<!--SNIPEND-->
67156

68157
You can also register context propagators through a [Plugin](/develop/plugins-guide) if you are building a reusable library.
@@ -72,9 +161,43 @@ You can also register context propagators through a [Plugin](/develop/plugins-gu
72161
In your Workflow, the propagated values are available on the `workflow.Context`. When the Workflow starts an Activity, the SDK automatically propagates the same values:
73162

74163
<!--SNIPSTART samples-go-ctx-propagation-workflow-->
164+
[ctxpropagation/workflow.go](https://github.com/temporalio/samples-go/blob/main/ctxpropagation/workflow.go)
165+
```go
166+
// CtxPropWorkflow workflow definition
167+
func CtxPropWorkflow(ctx workflow.Context) (err error) {
168+
ao := workflow.ActivityOptions{
169+
StartToCloseTimeout: 2 * time.Second, // such a short timeout to make sample fail over very fast
170+
}
171+
ctx = workflow.WithActivityOptions(ctx, ao)
172+
173+
if val := ctx.Value(PropagateKey); val != nil {
174+
vals := val.(Values)
175+
workflow.GetLogger(ctx).Info("custom context propagated to workflow", vals.Key, vals.Value)
176+
}
177+
178+
var values Values
179+
if err = workflow.ExecuteActivity(ctx, SampleActivity).Get(ctx, &values); err != nil {
180+
workflow.GetLogger(ctx).Error("Workflow failed.", "Error", err)
181+
return err
182+
}
183+
workflow.GetLogger(ctx).Info("context propagated to activity", values.Key, values.Value)
184+
workflow.GetLogger(ctx).Info("Workflow completed.")
185+
return nil
186+
}
187+
```
75188
<!--SNIPEND-->
76189

77190
<!--SNIPSTART samples-go-ctx-propagation-activity-->
191+
[ctxpropagation/activities.go](https://github.com/temporalio/samples-go/blob/main/ctxpropagation/activities.go)
192+
```go
193+
func SampleActivity(ctx context.Context) (*Values, error) {
194+
if val := ctx.Value(PropagateKey); val != nil {
195+
vals := val.(Values)
196+
return &vals, nil
197+
}
198+
return nil, nil
199+
}
200+
```
78201
<!--SNIPEND-->
79202

80203
You can configure multiple context propagators on a single Client, each responsible for its own set of keys.

0 commit comments

Comments
 (0)