| 3773 | } |
| 3774 | |
| 3775 | func (c *Cache) wait( |
| 3776 | ctx context.Context, |
| 3777 | sessionID string, |
| 3778 | resolver TypeResolver, |
| 3779 | oc *ongoingCall, |
| 3780 | req *CallRequest, |
| 3781 | ) (AnyResult, error) { |
| 3782 | var ( |
| 3783 | completionErr error |
| 3784 | canceledErr error |
| 3785 | completed bool |
| 3786 | ) |
| 3787 | |
| 3788 | select { |
| 3789 | case <-oc.waitCh: |
| 3790 | completed = true |
| 3791 | case <-ctx.Done(): |
| 3792 | canceledErr = context.Cause(ctx) |
| 3793 | } |
| 3794 | |
| 3795 | if completed { |
| 3796 | completionErr = oc.err |
| 3797 | } |
| 3798 | |
| 3799 | if !completed { |
| 3800 | c.callsMu.Lock() |
| 3801 | oc.waiters-- |
| 3802 | lastWaiter := oc.waiters == 0 |
| 3803 | releaseHandoff := lastWaiter && oc.handoffHoldActive |
| 3804 | if lastWaiter { |
| 3805 | delete(c.ongoingCalls, oc.callConcurrencyKeys) |
| 3806 | oc.cancel(canceledErr) |
| 3807 | } |
| 3808 | c.callsMu.Unlock() |
| 3809 | if releaseHandoff && oc.res != nil { |
| 3810 | c.egraphMu.Lock() |
| 3811 | queue, decErr := c.decrementIncomingOwnershipLocked(ctx, oc.res, nil) |
| 3812 | collectReleases, collectErr := c.collectUnownedResultsLocked(context.WithoutCancel(ctx), queue) |
| 3813 | c.egraphMu.Unlock() |
| 3814 | oc.handoffHoldActive = false |
| 3815 | if relErr := errors.Join(decErr, collectErr, runOnReleaseFuncs(context.WithoutCancel(ctx), collectReleases)); relErr != nil { |
| 3816 | return nil, errors.Join(canceledErr, relErr) |
| 3817 | } |
| 3818 | } |
| 3819 | return nil, canceledErr |
| 3820 | } |
| 3821 | |
| 3822 | if completionErr != nil { |
| 3823 | c.callsMu.Lock() |
| 3824 | oc.waiters-- |
| 3825 | lastWaiter := oc.waiters == 0 |
| 3826 | if lastWaiter { |
| 3827 | delete(c.ongoingCalls, oc.callConcurrencyKeys) |
| 3828 | oc.cancel(completionErr) |
| 3829 | } |
| 3830 | c.callsMu.Unlock() |
| 3831 | return nil, completionErr |
| 3832 | } |