zenyui / gqlgen-dataloader

Demonstrates GqlGen using the graph-gophers/dataloader
27 stars 5 forks source link

Handle errors correctly #7

Closed frederikhors closed 3 years ago

frederikhors commented 3 years ago

As you know Graphql can return data alongside errors list.

For a list I can have:

data: {items: [{}]}
errors: [{}, {}]

With the code in your example I cannot understand how to do this and how to distinguish between an error to be returned in graphql and one to be returned as an error to make the program stop.

Example, given this code:

func (u *userBatcher) get(ctx context.Context, keys dataloader.Keys) []*dataloader.Result {
    fmt.Printf("dataloader.userBatcher.get, users: [%s]\n", strings.Join(keys.Keys(), ","))
    // create a map for remembering the order of keys passed in
    keyOrder := make(map[string]int, len(keys))
    // collect the keys to search for
    var userIDs []string
    for ix, key := range keys {
        userIDs = append(userIDs, key.String())
        keyOrder[key.String()] = ix
    }
    // search for those users
    dbRecords, err := u.db.GetUsers(ctx, userIDs)
    // if DB error, return
    if err != nil {
        return []*dataloader.Result{{Data: nil, Error: err}}
    }
    // construct an output array of dataloader results
    results := make([]*dataloader.Result, len(keys))
    // enumerate records, put into output
    for _, record := range dbRecords {
        ix, ok := keyOrder[record.ID]
        // if found, remove from index lookup map so we know elements were found
        if ok {
            results[ix] = &dataloader.Result{Data: record, Error: nil}
            delete(keyOrder, record.ID)
        }
    }
    // fill array positions with errors where not found in DB
    for userID, ix := range keyOrder {
        err := fmt.Errorf("user not found %s", userID)
        results[ix] = &dataloader.Result{Data: nil, Error: err}
    }
    // return results
    return results
}

Let's say I get an error in db.GetUsers() and use that code I get this error instead:

\n\t\t\tThe batch function supplied did not return an array of responses\n\t\t\tthe same length as the array of keys.\n\n\t\t\tKeys:\n\t\t\t[1 2]\n\n\t\t\tValues:\n\t\t\t[0xc000386600]\n\t\t"

for each element of the list.

So I need another way to handle this.

What do you suggest?

zenyui commented 3 years ago

I believe the proper handling case would be to fill the results array with the db error for each result element. This will allow you to propagate the error through to your resolver, which should return as a graph error.

As I understand, the data loader must return a result for every requested key.