_examples/federation/products/graph/federation.go (272 lines of code) (raw):

// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. package graph import ( "context" "errors" "fmt" "strings" "sync" "github.com/99designs/gqlgen/plugin/federation/fedruntime" ) var ( ErrUnknownType = errors.New("unknown type") ErrTypeNotFound = errors.New("type not found") ) func (ec *executionContext) __resolve__service(ctx context.Context) (fedruntime.Service, error) { if ec.DisableIntrospection { return fedruntime.Service{}, errors.New("federated introspection disabled") } var sdl []string for _, src := range sources { if src.BuiltIn { continue } sdl = append(sdl, src.Input) } return fedruntime.Service{ SDL: strings.Join(sdl, "\n"), }, nil } func (ec *executionContext) __resolve_entities(ctx context.Context, representations []map[string]interface{}) []fedruntime.Entity { list := make([]fedruntime.Entity, len(representations)) repsMap := ec.buildRepresentationGroups(ctx, representations) switch len(repsMap) { case 0: return list case 1: for typeName, reps := range repsMap { ec.resolveEntityGroup(ctx, typeName, reps, list) } return list default: var g sync.WaitGroup g.Add(len(repsMap)) for typeName, reps := range repsMap { go func(typeName string, reps []EntityWithIndex) { ec.resolveEntityGroup(ctx, typeName, reps, list) g.Done() }(typeName, reps) } g.Wait() return list } } type EntityWithIndex struct { // The index in the original representation array index int entity EntityRepresentation } // EntityRepresentation is the JSON representation of an entity sent by the Router // used as the inputs for us to resolve. // // We make it a map because we know the top level JSON is always an object. type EntityRepresentation map[string]any // We group entities by typename so that we can parallelize their resolution. // This is particularly helpful when there are entity groups in multi mode. func (ec *executionContext) buildRepresentationGroups( ctx context.Context, representations []map[string]any, ) map[string][]EntityWithIndex { repsMap := make(map[string][]EntityWithIndex) for i, rep := range representations { typeName, ok := rep["__typename"].(string) if !ok { // If there is no __typename, we just skip the representation; // we just won't be resolving these unknown types. ec.Error(ctx, errors.New("__typename must be an existing string")) continue } repsMap[typeName] = append(repsMap[typeName], EntityWithIndex{ index: i, entity: rep, }) } return repsMap } func (ec *executionContext) resolveEntityGroup( ctx context.Context, typeName string, reps []EntityWithIndex, list []fedruntime.Entity, ) { if isMulti(typeName) { err := ec.resolveManyEntities(ctx, typeName, reps, list) if err != nil { ec.Error(ctx, err) } } else { // if there are multiple entities to resolve, parallelize (similar to // graphql.FieldSet.Dispatch) var e sync.WaitGroup e.Add(len(reps)) for i, rep := range reps { i, rep := i, rep go func(i int, rep EntityWithIndex) { entity, err := ec.resolveEntity(ctx, typeName, rep.entity) if err != nil { ec.Error(ctx, err) } else { list[rep.index] = entity } e.Done() }(i, rep) } e.Wait() } } func isMulti(typeName string) bool { switch typeName { default: return false } } func (ec *executionContext) resolveEntity( ctx context.Context, typeName string, rep EntityRepresentation, ) (e fedruntime.Entity, err error) { // we need to do our own panic handling, because we may be called in a // goroutine, where the usual panic handling can't catch us defer func() { if r := recover(); r != nil { err = ec.Recover(ctx, r) } }() switch typeName { case "Manufacturer": resolverName, err := entityResolverNameForManufacturer(ctx, rep) if err != nil { return nil, fmt.Errorf(`finding resolver for Entity "Manufacturer": %w`, err) } switch resolverName { case "findManufacturerByID": id0, err := ec.unmarshalNString2string(ctx, rep["id"]) if err != nil { return nil, fmt.Errorf(`unmarshalling param 0 for findManufacturerByID(): %w`, err) } entity, err := ec.resolvers.Entity().FindManufacturerByID(ctx, id0) if err != nil { return nil, fmt.Errorf(`resolving Entity "Manufacturer": %w`, err) } return entity, nil } case "Product": resolverName, err := entityResolverNameForProduct(ctx, rep) if err != nil { return nil, fmt.Errorf(`finding resolver for Entity "Product": %w`, err) } switch resolverName { case "findProductByManufacturerIDAndID": id0, err := ec.unmarshalNString2string(ctx, rep["manufacturer"].(map[string]interface{})["id"]) if err != nil { return nil, fmt.Errorf(`unmarshalling param 0 for findProductByManufacturerIDAndID(): %w`, err) } id1, err := ec.unmarshalNString2string(ctx, rep["id"]) if err != nil { return nil, fmt.Errorf(`unmarshalling param 1 for findProductByManufacturerIDAndID(): %w`, err) } entity, err := ec.resolvers.Entity().FindProductByManufacturerIDAndID(ctx, id0, id1) if err != nil { return nil, fmt.Errorf(`resolving Entity "Product": %w`, err) } return entity, nil case "findProductByUpc": id0, err := ec.unmarshalNString2string(ctx, rep["upc"]) if err != nil { return nil, fmt.Errorf(`unmarshalling param 0 for findProductByUpc(): %w`, err) } entity, err := ec.resolvers.Entity().FindProductByUpc(ctx, id0) if err != nil { return nil, fmt.Errorf(`resolving Entity "Product": %w`, err) } return entity, nil } } return nil, fmt.Errorf("%w: %s", ErrUnknownType, typeName) } func (ec *executionContext) resolveManyEntities( ctx context.Context, typeName string, reps []EntityWithIndex, list []fedruntime.Entity, ) (err error) { // we need to do our own panic handling, because we may be called in a // goroutine, where the usual panic handling can't catch us defer func() { if r := recover(); r != nil { err = ec.Recover(ctx, r) } }() switch typeName { default: return errors.New("unknown type: " + typeName) } } func entityResolverNameForManufacturer(ctx context.Context, rep EntityRepresentation) (string, error) { for { var ( m EntityRepresentation val interface{} ok bool ) _ = val // if all of the KeyFields values for this resolver are null, // we shouldn't use use it allNull := true m = rep val, ok = m["id"] if !ok { break } if allNull { allNull = val == nil } if allNull { break } return "findManufacturerByID", nil } return "", fmt.Errorf("%w for Manufacturer", ErrTypeNotFound) } func entityResolverNameForProduct(ctx context.Context, rep EntityRepresentation) (string, error) { for { var ( m EntityRepresentation val interface{} ok bool ) _ = val // if all of the KeyFields values for this resolver are null, // we shouldn't use use it allNull := true m = rep val, ok = m["manufacturer"] if !ok { break } if m, ok = val.(map[string]interface{}); !ok { break } val, ok = m["id"] if !ok { break } if allNull { allNull = val == nil } m = rep val, ok = m["id"] if !ok { break } if allNull { allNull = val == nil } if allNull { break } return "findProductByManufacturerIDAndID", nil } for { var ( m EntityRepresentation val interface{} ok bool ) _ = val // if all of the KeyFields values for this resolver are null, // we shouldn't use use it allNull := true m = rep val, ok = m["upc"] if !ok { break } if allNull { allNull = val == nil } if allNull { break } return "findProductByUpc", nil } return "", fmt.Errorf("%w for Product", ErrTypeNotFound) }