operation_tasks.go ×15

Frontier kind: Code frontier

unlabeled · c_28da804e0b82

16 tests · 4111 LOC · 154 files · introduces 0 tests · 92 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
19 ranges92 lines · 2 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
903 ranges4111 lines · 154 files · Browse complete extent
All tests (intent)
16 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

2 files ranked by introduced lines: 92 introduced LOC across 19 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

go.temporal.io/server/chasm/lib/nexusoperation/operation_tasks.go 81 introduced LOC · 15 ranges

Open complete file

103 }
104
105 > callbackURL, err := buildCallbackURL(h.config.UseSystemCallbackURL(), h.config.CallbackURLTemplate(), ns, endpoint) operation_tasks.go
106 > if err != nil {
107 return fmt.Errorf("failed to build callback URL: %w", err)
108 }
109
110 > token, err := h.generateCallbackToken(args.serializedRef, args.requestID) operation_tasks.go
111 > if err != nil {
112 return err
113 }
114
115 > elapsed := args.currentTime.Sub(args.scheduledTime) operation_tasks.go
116 > callTimeout := h.config.RequestTimeout(ns.Name().String(), attrs.Destination)
117 > var timeoutType enumspb.TimeoutType
118 > // Adjust timeout based on remaining operation timeouts.
119 > // ScheduleToStart takes precedence over ScheduleToClose since it is already capped by it.
120 > if args.scheduleToStartTimeout > 0 {
121 callTimeout = min(callTimeout, args.scheduleToStartTimeout-elapsed)
122 timeoutType = enumspb.TIMEOUT_TYPE_SCHEDULE_TO_START
123 > } else if args.scheduleToCloseTimeout > 0 { operation_tasks.go
124 callTimeout = min(callTimeout, args.scheduleToCloseTimeout-elapsed)
125 timeoutType = enumspb.TIMEOUT_TYPE_SCHEDULE_TO_CLOSE
128 // Inform the handler of the operation timeout via header.
129 // StartToClose takes precedence over ScheduleToClose since it is already capped by it.
130 > opTimeout := maxDuration operation_tasks.go
131 > if args.startToCloseTimeout > 0 {
132 opTimeout = args.startToCloseTimeout
133 }
134 > if args.scheduleToCloseTimeout > 0 { operation_tasks.go
135 opTimeout = min(args.scheduleToCloseTimeout-elapsed, opTimeout)
136 }
137 > header := buildRequestHeader(args.header) operation_tasks.go
138 > // Set the operation timeout header if not already set.
139 > if opTimeoutHeader := header.Get(nexus.HeaderOperationTimeout); opTimeout != maxDuration && opTimeoutHeader == "" {
140 header.Set(nexus.HeaderOperationTimeout, commonnexus.FormatDuration(opTimeout))
141 }
142 // If this request is handled by a newer server that supports Nexus failure serialization, trigger that behavior.
143 > if h.config.UseNewFailureWireFormat(ns.Name().String()) { operation_tasks.go
144 > header.Set(nexusrpc.HeaderTemporalNexusFailureSupport, "true")
145 > }
146
147 > callCtx, cancel := context.WithTimeout(ctx, callTimeout) operation_tasks.go
148 > defer cancel()
149 > // Set this value on the parent context so that our custom HTTP caller can mutate it since we cannot
150 > // access response headers directly.
151 > callCtx = context.WithValue(callCtx, commonnexus.FailureSourceContextKey, &atomic.Value{})
152 >
153 > options := nexus.StartOperationOptions{
154 > Header: header,
155 > CallbackURL: callbackURL,
156 > RequestID: args.requestID,
157 > CallbackHeader: nexus.Header{
158 > commonnexus.CallbackTokenHeader: token,
159 > },
160 > Links: args.nexusLinks,
161 > }
162 >
163 > traceCtx := invocationTraceContext{
164 > operationTag: "StartOperation",
165 > namespaceName: ns.Name().String(),
166 > targetNamespaceID: endpoint.GetEndpoint().GetSpec().GetTarget().GetWorker().GetNamespaceId(),
167 > requestID: args.requestID,
168 > operation: args.operation,
169 > endpointName: args.endpointName,
170 > workflowID: opRef.BusinessID,
171 > runID: opRef.RunID,
172 > attemptStart: args.currentTime.UTC(),
173 > attempt: task.GetAttempt(),
174 > }
175 >
176 > invocation, err := h.newInvocation(
177 > callCtx,
178 > ns,
179 > endpoint,
180 > traceCtx.endpointName,
181 > args.service,
182 > callTimeout,
183 > timeoutType,
184 > traceCtx,
185 > )
186 > if err != nil {
187 return fmt.Errorf("failed to construct invocation: %w", err)
188 }
189 > startTime := time.Now() // nolint:forbidigo // Time can be used for timing metrics. operation_tasks.go
190 > response, callErr := invocation.Start(callCtx, args, options)
191 > callDuration := time.Since(startTime)
192 > if validationErr := h.validateStartResult(ns, response); validationErr != nil {
193 callErr = validationErr
194 }
195 > failureSource := failureSourceFromContext(callCtx) operation_tasks.go
196 >
197 > h.recordCallOutcome(endpoint, startCallOutcomeTag(callCtx, response, callErr), callErr, callDuration, failureSource, traceCtx)
198 >
199 > result, err := newInvocationResult(response, callErr)
200 > if err != nil {
201 return fmt.Errorf("failed to construct invocation result: %w", err)
202 }
203 > _, _, saveErr := chasm.UpdateComponent(ctx, opRef, (*Operation).saveInvocationResult, saveInvocationResultInput{ operation_tasks.go
204 > result: result,
205 > retryPolicy: h.config.RetryPolicy(),
206 > })
207 >
208 > if callErr != nil && isDestinationDown(callErr) {
209 saveErr = queueserrors.NewDestinationDownError(callErr.Error(), saveErr)
210 }
211
212 > return saveErr operation_tasks.go
213 }
214
215 // buildRequestHeader returns a copy of the supplied header, or a new map if nil.
216 > func buildRequestHeader(header map[string]string) nexus.Header { operation_tasks.go
217 > if header == nil {
218 return make(nexus.Header, 2) // To set the failure support and timeout headers.
219 }
242 ns *namespace.Namespace,
243 result *nexusrpc.ClientStartOperationResponse[*commonpb.Payload],
244 > ) error { operation_tasks.go
245 > if result == nil {
246 return nil
247 }
go.temporal.io/server/chasm/lib/nexusoperation/task_handler_helpers.go 11 introduced LOC · 4 ranges

Open complete file

84 }
85
86 > func startCallOutcomeTag(callCtx context.Context, result *nexusrpc.ClientStartOperationResponse[*commonpb.Payload], callErr error) string { task_handler_helpers.go
87 > if callErr != nil {
88 if _, ok := errors.AsType[*operationTimeoutBelowMinError](callErr); ok {
89 return "operation-timeout"
333 ns *namespace.Namespace,
334 endpoint *persistencespb.NexusEndpointEntry,
335 > ) (string, error) { task_handler_helpers.go
336 > if endpoint == nil {
337 return commonnexus.SystemCallbackURL, nil
338 }
369 serializedRef []byte,
370 requestID string,
371 > ) (string, error) { task_handler_helpers.go
372 > token, err := h.callbackTokenGenerator.Tokenize(&tokenspb.NexusOperationCompletion{
373 > ComponentRef: serializedRef,
374 > RequestId: requestID,
375 > })
376 > if err != nil {
377 return "", fmt.Errorf("%w: %w", queueserrors.NewUnprocessableTaskError("failed to generate a callback token"), err)
378 }
379 > return token, nil task_handler_helpers.go
380 }