executors.go ×18

Frontier kind: Code frontier

unlabeled · c_026d1278ae8a

17 tests · 3346 LOC · 142 files · introduces 0 tests · 70 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
18 ranges70 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
611 ranges3346 lines · 142 files · Browse complete extent
All tests (intent)
17 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.

1 file ranked by introduced lines: 70 introduced LOC across 18 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

go.temporal.io/server/components/nexusoperations/executors.go 70 introduced LOC · 18 ranges

Open complete file

196 }
197
198 > callbackURL, err := buildCallbackURL(e.Config.UseSystemCallbackURL(), e.Config.CallbackURLTemplate(), ns, endpoint) executors.go
199 > if err != nil {
200 return fmt.Errorf("failed to build callback URL: %w", err)
201 }
205 // Operation machine has transitioned.
206 // TODO(bergundy): Remove this before the 1.27 release.
207 > smRef := common.CloneProto(ref.StateMachineRef) executors.go
208 > smRef.MachineTransitionCount = 0
209 >
210 > // Set ms VT to initial version because workflow may switch to a different branch.
211 > smRef.MutableStateVersionedTransition = smRef.MachineInitialVersionedTransition
212 >
213 > token, err := e.CallbackTokenGenerator.Tokenize(&tokenspb.NexusOperationCompletion{
214 > NamespaceId: ref.WorkflowKey.NamespaceID,
215 > WorkflowId: ref.WorkflowKey.WorkflowID,
216 > RunId: ref.WorkflowKey.RunID,
217 > Ref: smRef,
218 > RequestId: args.requestID,
219 > })
220 > if err != nil {
221 return fmt.Errorf("%w: %w", queueserrors.NewUnprocessableTaskError("failed to generate a callback token"), err)
222 }
223
224 > callTimeout := e.Config.RequestTimeout(ns.Name().String(), task.EndpointName) executors.go
225 > var timeoutType enumspb.TimeoutType
226 > // Adjust timeout based on remaining operation timeouts.
227 > // ScheduleToStart takes precedence over ScheduleToClose since it is already capped by it.
228 > if args.scheduleToStartTimeout > 0 {
229 callTimeout = min(callTimeout, args.scheduleToStartTimeout-time.Since(args.scheduledTime))
230 timeoutType = enumspb.TIMEOUT_TYPE_SCHEDULE_TO_START
231 > } else if args.scheduleToCloseTimeout > 0 { executors.go
232 callTimeout = min(callTimeout, args.scheduleToCloseTimeout-time.Since(args.scheduledTime))
233 timeoutType = enumspb.TIMEOUT_TYPE_SCHEDULE_TO_CLOSE
235 // Inform the handler of the operation timeout via header.
236 // StartToClose takes precedence over ScheduleToClose since it is already capped by it.
237 > opTimeout := maxDuration executors.go
238 > if args.startToCloseTimeout > 0 {
239 opTimeout = args.startToCloseTimeout
240 }
241 > if args.scheduleToCloseTimeout > 0 { executors.go
242 opTimeout = min(args.scheduleToCloseTimeout-time.Since(args.scheduledTime), opTimeout)
243 }
244 > header := nexus.Header(args.header) executors.go
245 > if header == nil {
246 header = make(nexus.Header, 1) // It's most likely that we'll only be setting the new wire format header.
247 }
248 // Set the operation timeout header if not already set.
249 > if opTimeoutHeader := header.Get(nexus.HeaderOperationTimeout); opTimeout != maxDuration && opTimeoutHeader == "" { executors.go
250 header[nexus.HeaderOperationTimeout] = commonnexus.FormatDuration(opTimeout)
251 }
252 > if e.Config.UseNewFailureWireFormat(ns.Name().String()) { executors.go
253 // If this request is handled by a newer server that supports Nexus failure serialization, trigger that behavior.
254 header.Set(nexusrpc.HeaderTemporalNexusFailureSupport, "true")
255 }
256
257 > callCtx, cancel := context.WithTimeout(ctx, callTimeout) executors.go
258 > defer cancel()
259 > // Set this value on the parent context so that our custom HTTP caller can mutate it since we cannot access response headers directly.
260 > callCtx = context.WithValue(callCtx, commonnexus.FailureSourceContextKey, &atomic.Value{})
261 >
262 > options := nexus.StartOperationOptions{
263 > Header: header,
264 > CallbackURL: callbackURL,
265 > RequestID: args.requestID,
266 > CallbackHeader: nexus.Header{
267 > commonnexus.CallbackTokenHeader: token,
268 > },
269 > Links: []nexus.Link{args.nexusLink},
270 > }
271 >
272 > var result *nexusrpc.ClientStartOperationResponse[*commonpb.Payload]
273 > var callErr error
274 > var startTime time.Time
275 > if callTimeout < e.Config.MinRequestTimeout(ns.Name().String()) {
276 startTime = time.Now()
277 callErr = &operationTimeoutBelowMinError{timeoutType: timeoutType}
278 > } else if args.endpointName == commonnexus.SystemEndpoint { executors.go
279 startTime = time.Now()
280 result, callErr = e.startOnHistoryService(callCtx, ns, args, options)
310 }
311
312 > if result != nil { executors.go
313 tokenLimit := e.Config.MaxOperationTokenLength(ns.Name().String())
314 if result.Pending != nil && len(result.Pending.Token) > tokenLimit {
318 }
319 }
320 > failureSource := failureSourceFromContext(callCtx) executors.go
321 >
322 > methodTag := metrics.NexusMethodTag("StartOperation")
323 > namespaceTag := metrics.NamespaceTag(ns.Name().String())
324 > var destTag metrics.Tag
325 > if endpoint != nil {
326 destTag = metrics.DestinationTag(endpoint.Endpoint.Spec.GetName())
327 > } else { executors.go
328 destTag = metrics.DestinationTag(args.endpointName)
329 }
330 > outcomeTag := metrics.OutcomeTag(startCallOutcomeTag(callCtx, result, callErr)) executors.go
331 > failureSourceTag := metrics.FailureSourceTag(failureSource)
332 > chasmnexus.OutboundRequestCounter.With(e.MetricsHandler).Record(1, namespaceTag, destTag, methodTag, outcomeTag, failureSourceTag)
333 > chasmnexus.OutboundRequestLatency.With(e.MetricsHandler).Record(time.Since(startTime), namespaceTag, destTag, methodTag, outcomeTag, failureSourceTag)
334 >
335 > if callErr != nil {
336 if failureSource == commonnexus.FailureSourceWorker || errors.As(callErr, new(*operationTimeoutBelowMinError)) {
337 e.Logger.Debug("Nexus StartOperation request failed", tag.Error(callErr))
341 }
342
343 > err = e.saveResult(ctx, env, ref, result, callErr) executors.go
344 >
345 > if callErr != nil && isDestinationDown(callErr) {
346 err = queueserrors.NewDestinationDownError(callErr.Error(), err)
347 }
348
349 > return err executors.go
350 }
351
964 }
965
966 > func startCallOutcomeTag(callCtx context.Context, result *nexusrpc.ClientStartOperationResponse[*commonpb.Payload], callErr error) string { executors.go
967 >
968 > if callErr != nil {
969 var opTimeoutBelowMinErr *operationTimeoutBelowMinError
970 if errors.As(callErr, &opTimeoutBelowMinErr) {