Select evaluates a series of chained field selections starting from the given object and assigns the final result value into dest. nolint:gocyclo // intrinsically long state machine; refactoring would hurt clarity
(ctx context.Context, self AnyObjectResult, dest any, sels ...Selector)
| 1675 | // |
| 1676 | //nolint:gocyclo // intrinsically long state machine; refactoring would hurt clarity |
| 1677 | func (s *Server) Select(ctx context.Context, self AnyObjectResult, dest any, sels ...Selector) (rerr error) { |
| 1678 | ctx = srvToContext(ctx, s) |
| 1679 | if isNonInternal(ctx) { |
| 1680 | // We only want "non internal" to apply to the immediate call, so flip it |
| 1681 | // from here on; it already did its job in avoiding the withInternal below. |
| 1682 | // |
| 1683 | // FIXME: this is an absurd dance, we should maybe just remove the |
| 1684 | // auto-Internaling, but that'll be a game of wack-a-mole |
| 1685 | ctx = withoutNonInternalTelemetry(ctx) |
| 1686 | } else { |
| 1687 | // Annotate ctx with the internal flag so we can distinguish self-calls from |
| 1688 | // user-calls in the UI. |
| 1689 | // |
| 1690 | // Only do this if we haven't been explicitly told not to (internal=false). |
| 1691 | ctx = withInternal(ctx) |
| 1692 | } |
| 1693 | |
| 1694 | leaseCtx, release, err := withOperationLease(ctx) |
| 1695 | if err != nil { |
| 1696 | return fmt.Errorf("acquire operation lease: %w", err) |
| 1697 | } |
| 1698 | ctx = leaseCtx |
| 1699 | defer func() { |
| 1700 | if releaseErr := release(context.WithoutCancel(ctx)); releaseErr != nil && rerr == nil { |
| 1701 | rerr = releaseErr |
| 1702 | } |
| 1703 | }() |
| 1704 | |
| 1705 | var res AnyResult = self |
| 1706 | for i, sel := range sels { |
| 1707 | nth := sel.Nth |
| 1708 | // if we are selecting the nth element, then select the parent list first and |
| 1709 | // grab the NthValue below |
| 1710 | if nth != 0 { |
| 1711 | sel.Nth = 0 |
| 1712 | } |
| 1713 | var err error |
| 1714 | res, err = self.Select(ctx, s, sel) |
| 1715 | if err != nil { |
| 1716 | return err |
| 1717 | } |
| 1718 | |
| 1719 | if res == nil { |
| 1720 | // null result; nothing to do |
| 1721 | return nil |
| 1722 | } |
| 1723 | unwrap := res.Unwrap() |
| 1724 | if unwrap == nil { |
| 1725 | if shared := res.cacheSharedResult(); shared != nil { |
| 1726 | state := shared.loadPayloadState() |
| 1727 | if state.isObject { |
| 1728 | typeName := sharedResultObjectTypeName(shared, state) |
| 1729 | return fmt.Errorf( |
| 1730 | "select %s returned unresolved object-typed result %q (shared result %d: hasValue=%t, persistedEnvelope=%t)", |
| 1731 | sel.Field, |
| 1732 | typeName, |
| 1733 | shared.id, |
| 1734 | state.hasValue, |