ent/integration: refactor node template to provide .Noder on client (#50)

Summary:
Pull Request resolved: https://github.com/facebookincubator/symphony/pull/50

Pull Request resolved: https://github.com/facebookincubator/ent/pull/149

Noder can be used to implement graphql Node interface over gqlgen.

See https://facebook.github.io/relay/graphql/objectidentification.htm for more info.

Reviewed By: a8m

Differential Revision: D18410318

fbshipit-source-id: 5e9e2f243ab96ef61999f9066ffee65cb39094fe
This commit is contained in:
Alex Snast
2019-11-09 09:32:52 -08:00
committed by Facebook Github Bot
parent 4aa550a68f
commit 782f3d90c9
2 changed files with 46 additions and 30 deletions

View File

@@ -9,6 +9,7 @@ package ent
import (
"context"
"encoding/json"
"fmt"
"sync"
"github.com/facebookincubator/ent/dialect/sql"
@@ -146,12 +147,20 @@ func (u *User) Node(ctx context.Context) (node *Node, err error) {
}
var (
once sync.Once
types []string
typeNodes = make(map[string]func(context.Context, int) (*Node, error))
once sync.Once
types []string
noders = make(map[string]func(context.Context, int) (Noder, error))
)
func (c *Client) Node(ctx context.Context, id int) (*Node, error) {
noder, err := c.Noder(ctx, id)
if err != nil {
return nil, err
}
return noder.Node(ctx)
}
func (c *Client) Noder(ctx context.Context, id int) (Noder, error) {
var err error
once.Do(func() {
err = c.loadTypes(ctx)
@@ -160,7 +169,12 @@ func (c *Client) Node(ctx context.Context, id int) (*Node, error) {
return nil, err
}
idx := id / (1<<32 - 1)
return typeNodes[types[idx]](ctx, id)
if idx >= 0 && idx < len(types) {
if fn, ok := noders[types[idx]]; ok {
return fn(ctx, id)
}
}
return nil, fmt.Errorf("cannot resolve node type for id %v", id)
}
func (c *Client) loadTypes(ctx context.Context) error {
@@ -176,26 +190,14 @@ func (c *Client) loadTypes(ctx context.Context) error {
if err := sql.ScanSlice(rows, &types); err != nil {
return err
}
typeNodes[group.Table] = func(ctx context.Context, id int) (*Node, error) {
nv, err := c.Group.Get(ctx, id)
if err != nil {
return nil, err
}
return nv.Node(ctx)
noders[group.Table] = func(ctx context.Context, id int) (Noder, error) {
return c.Group.Get(ctx, id)
}
typeNodes[pet.Table] = func(ctx context.Context, id int) (*Node, error) {
nv, err := c.Pet.Get(ctx, id)
if err != nil {
return nil, err
}
return nv.Node(ctx)
noders[pet.Table] = func(ctx context.Context, id int) (Noder, error) {
return c.Pet.Get(ctx, id)
}
typeNodes[user.Table] = func(ctx context.Context, id int) (*Node, error) {
nv, err := c.User.Get(ctx, id)
if err != nil {
return nil, err
}
return nv.Node(ctx)
noders[user.Table] = func(ctx context.Context, id int) (Noder, error) {
return c.User.Get(ctx, id)
}
return nil
}

View File

@@ -8,6 +8,11 @@ in the LICENSE file in the root directory of this source tree.
{{ $pkg := base $.Config.Package }}
{{ template "header" $ }}
import (
"github.com/facebookincubator/ent/dialect/sql"
"github.com/facebookincubator/ent/dialect/sql/schema"
)
// Noder wraps the basic Node method.
type Noder interface {
Node(context.Context) (*Node, error)
@@ -83,10 +88,18 @@ type Edge struct {
var (
once sync.Once
types []string
typeNodes = make(map[string]func(context.Context, {{ $.IDType }})(*Node, error))
noders = make(map[string]func(context.Context, {{ $.IDType }}) (Noder, error))
)
func (c *Client) Node(ctx context.Context, id {{ $.IDType }}) (*Node, error) {
noder, err := c.Noder(ctx, id)
if err != nil {
return nil, err
}
return noder.Node(ctx)
}
func (c *Client) Noder(ctx context.Context, id {{ $.IDType }}) (Noder, error) {
var err error
once.Do(func() {
err = c.loadTypes(ctx)
@@ -103,7 +116,12 @@ func (c *Client) Node(ctx context.Context, id {{ $.IDType }}) (*Node, error) {
{{- else }}
idx := id/(1<<32 - 1)
{{- end }}
return typeNodes[types[idx]](ctx, id)
if idx >= 0 && idx < len(types) {
if fn, ok := noders[types[idx]]; ok {
return fn(ctx, id)
}
}
return nil, fmt.Errorf("cannot resolve node type for id %v", id)
}
func (c *Client) loadTypes(ctx context.Context) error {
@@ -120,12 +138,8 @@ func (c *Client) loadTypes(ctx context.Context) error {
return err
}
{{- range $_, $n := $.Nodes }}
typeNodes[{{ $n.Package }}.Table] = func(ctx context.Context, id {{ $.IDType }})(*Node, error) {
nv, err := c.{{ $n.Name }}.Get(ctx, id)
if err != nil {
return nil, err
}
return nv.Node(ctx)
noders[{{ $n.Package }}.Table] = func(ctx context.Context, id {{ $.IDType }}) (Noder, error) {
return c.{{ $n.Name }}.Get(ctx, id)
}
{{- end }}
return nil