From fdd0e5b3c749caf9f4aa9b062452d7de151af04f Mon Sep 17 00:00:00 2001 From: Andreas Garnaes Date: Thu, 9 Jun 2016 16:22:01 +0200 Subject: [PATCH] Evaluate list elements concurrently --- executor.go | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/executor.go b/executor.go index 138b0c42..93eb2275 100644 --- a/executor.go +++ b/executor.go @@ -820,13 +820,34 @@ func completeListValue(eCtx *ExecutionContext, returnType *List, fieldASTs []*as panic(gqlerrors.FormatError(err)) } + // concurrently resolve list elements itemType := returnType.OfType - completedResults := []interface{}{} + wg := sync.WaitGroup{} + completedResults := make([]interface{}, resultVal.Len()) + panics := make(chan interface{}, resultVal.Len()) for i := 0; i < resultVal.Len(); i++ { - val := resultVal.Index(i).Interface() - completedItem := completeValueCatchingError(eCtx, itemType, fieldASTs, info, val) - completedResults = append(completedResults, completedItem) + wg.Add(1) + go func(j int) { + defer func() { + if r := recover(); r != nil { + panics <- r + } + wg.Done() + }() + val := resultVal.Index(j).Interface() + completedResults[j] = completeValueCatchingError(eCtx, itemType, fieldASTs, info, val) + }(i) } + + // wait for all routines to complete and then perform clean up + wg.Wait() + close(panics) + + // re-panic if a goroutine panicked + for p := range panics { + panic(p) + } + return completedResults }