aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2018-07-29 20:58:22 +0200
committerMichael Muré <batolettre@gmail.com>2018-07-29 20:58:22 +0200
commitc58aa18a2d0683b0a1e6f0597724e67b500503a0 (patch)
tree06b7611ebce2a4cbe0c99f72729517cb8114e3f1
parent08f03ecf3cbbc350585acf0492966681ec449a94 (diff)
downloadgit-bug-c58aa18a2d0683b0a1e6f0597724e67b500503a0.tar.gz
graphql: lazy loading for the bug relay connection
-rw-r--r--bug/bug.go5
-rw-r--r--cache/cache.go5
-rw-r--r--graphql/connections/connection_template.go8
-rw-r--r--graphql/connections/connections.go2
-rw-r--r--graphql/connections/gen_bug.go21
-rw-r--r--graphql/connections/lazy_bug.go10
-rw-r--r--graphql/resolvers/repo.go45
7 files changed, 77 insertions, 19 deletions
diff --git a/bug/bug.go b/bug/bug.go
index 713d6edc..d3cc41dd 100644
--- a/bug/bug.go
+++ b/bug/bug.go
@@ -204,6 +204,11 @@ func readAllBugs(repo repository.Repo, refPrefix string) <-chan StreamedBug {
return out
}
+// List all the available local bug ids
+func ListLocalIds(repo repository.Repo) ([]string, error) {
+ return repo.ListIds(bugsRefPattern)
+}
+
// IsValid check if the Bug data is valid
func (bug *Bug) IsValid() bool {
// non-empty
diff --git a/cache/cache.go b/cache/cache.go
index 779b95b0..07c5be52 100644
--- a/cache/cache.go
+++ b/cache/cache.go
@@ -23,6 +23,7 @@ type Cacher interface {
type RepoCacher interface {
ResolveBug(id string) (BugCacher, error)
ResolveBugPrefix(prefix string) (BugCacher, error)
+ AllBugIds() ([]string, error)
ClearAllBugs()
}
@@ -155,6 +156,10 @@ func (c RepoCache) ResolveBugPrefix(prefix string) (BugCacher, error) {
return cached, nil
}
+func (c RepoCache) AllBugIds() ([]string, error) {
+ return bug.ListLocalIds(c.repo)
+}
+
func (c RepoCache) ClearAllBugs() {
c.bugs = make(map[string]BugCacher)
}
diff --git a/graphql/connections/connection_template.go b/graphql/connections/connection_template.go
index 3dfaca8f..7f97c00b 100644
--- a/graphql/connections/connection_template.go
+++ b/graphql/connections/connection_template.go
@@ -11,13 +11,13 @@ type EdgeType generic.Type
type ConnectionType generic.Type
type NodeTypeEdger func(value NodeType, offset int) Edge
-type NodeTypeConMaker func(edges []EdgeType, info models.PageInfo, totalCount int) ConnectionType
+type NodeTypeConMaker func(edges []EdgeType, info models.PageInfo, totalCount int) (ConnectionType, error)
func NodeTypeCon(source []NodeType, edger NodeTypeEdger, conMaker NodeTypeConMaker, input models.ConnectionInput) (ConnectionType, error) {
var edges []EdgeType
var pageInfo models.PageInfo
- emptyCon := conMaker(edges, pageInfo, 0)
+ emptyCon, _ := conMaker(edges, pageInfo, 0)
offset := 0
@@ -76,7 +76,5 @@ func NodeTypeCon(source []NodeType, edger NodeTypeEdger, conMaker NodeTypeConMak
}
}
- con := conMaker(edges, pageInfo, len(source))
-
- return con, nil
+ return conMaker(edges, pageInfo, len(source))
}
diff --git a/graphql/connections/connections.go b/graphql/connections/connections.go
index 145bfbbe..84dc3750 100644
--- a/graphql/connections/connections.go
+++ b/graphql/connections/connections.go
@@ -1,4 +1,4 @@
-//go:generate genny -in=connection_template.go -out=gen_bug.go gen "NodeType=bug.Snapshot EdgeType=models.BugEdge ConnectionType=models.BugConnection"
+//go:generate genny -in=connection_template.go -out=gen_bug.go gen "NodeType=string EdgeType=LazyBugEdge ConnectionType=models.BugConnection"
//go:generate genny -in=connection_template.go -out=gen_operation.go gen "NodeType=bug.Operation EdgeType=models.OperationEdge ConnectionType=models.OperationConnection"
//go:generate genny -in=connection_template.go -out=gen_comment.go gen "NodeType=bug.Comment EdgeType=models.CommentEdge ConnectionType=models.CommentConnection"
diff --git a/graphql/connections/gen_bug.go b/graphql/connections/gen_bug.go
index b43d5c11..64458669 100644
--- a/graphql/connections/gen_bug.go
+++ b/graphql/connections/gen_bug.go
@@ -7,18 +7,17 @@ package connections
import (
"fmt"
- "github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/graphql/models"
)
-type BugSnapshotEdger func(value bug.Snapshot, offset int) Edge
-type BugSnapshotConMaker func(edges []models.BugEdge, info models.PageInfo, totalCount int) models.BugConnection
+type StringEdger func(value string, offset int) Edge
+type StringConMaker func(edges []LazyBugEdge, info models.PageInfo, totalCount int) (models.BugConnection, error)
-func BugSnapshotCon(source []bug.Snapshot, edger BugSnapshotEdger, conMaker BugSnapshotConMaker, input models.ConnectionInput) (models.BugConnection, error) {
- var edges []models.BugEdge
+func StringCon(source []string, edger StringEdger, conMaker StringConMaker, input models.ConnectionInput) (models.BugConnection, error) {
+ var edges []LazyBugEdge
var pageInfo models.PageInfo
- emptyCon := conMaker(edges, pageInfo, 0)
+ emptyCon, _ := conMaker(edges, pageInfo, 0)
offset := 0
@@ -43,13 +42,13 @@ func BugSnapshotCon(source []bug.Snapshot, edger BugSnapshotEdger, conMaker BugS
break
}
- edges = append(edges, edge.(models.BugEdge))
+ edges = append(edges, edge.(LazyBugEdge))
}
} else {
- edges = make([]models.BugEdge, len(source))
+ edges = make([]LazyBugEdge, len(source))
for i, value := range source {
- edges[i] = edger(value, i+offset).(models.BugEdge)
+ edges[i] = edger(value, i+offset).(LazyBugEdge)
}
}
@@ -77,7 +76,5 @@ func BugSnapshotCon(source []bug.Snapshot, edger BugSnapshotEdger, conMaker BugS
}
}
- con := conMaker(edges, pageInfo, len(source))
-
- return con, nil
+ return conMaker(edges, pageInfo, len(source))
}
diff --git a/graphql/connections/lazy_bug.go b/graphql/connections/lazy_bug.go
new file mode 100644
index 00000000..35dcb687
--- /dev/null
+++ b/graphql/connections/lazy_bug.go
@@ -0,0 +1,10 @@
+package connections
+
+type LazyBugEdge struct {
+ Id string
+ Cursor string
+}
+
+func (lbe LazyBugEdge) GetCursor() string {
+ return lbe.Cursor
+}
diff --git a/graphql/resolvers/repo.go b/graphql/resolvers/repo.go
index d8190f15..2031d7b6 100644
--- a/graphql/resolvers/repo.go
+++ b/graphql/resolvers/repo.go
@@ -4,6 +4,7 @@ import (
"context"
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/graphql/connections"
"github.com/MichaelMure/git-bug/graphql/models"
)
@@ -13,7 +14,49 @@ type repoResolver struct {
}
func (repoResolver) AllBugs(ctx context.Context, obj *repoResolver, input models.ConnectionInput) (models.BugConnection, error) {
- panic("implement me")
+
+ // Simply pass a []string with the ids to the pagination algorithm
+ source, err := obj.repo.AllBugIds()
+
+ if err != nil {
+ return models.BugConnection{}, err
+ }
+
+ // The edger create a custom edge holding just the id
+ edger := func(id string, offset int) connections.Edge {
+ return connections.LazyBugEdge{
+ Id: id,
+ Cursor: connections.OffsetToCursor(offset),
+ }
+ }
+
+ // The conMaker will finally load and compile bugs from git to replace the selected edges
+ conMaker := func(lazyBugEdges []connections.LazyBugEdge, info models.PageInfo, totalCount int) (models.BugConnection, error) {
+ edges := make([]models.BugEdge, len(lazyBugEdges))
+
+ for i, lazyBugEdge := range lazyBugEdges {
+ b, err := obj.repo.ResolveBug(lazyBugEdge.Id)
+
+ if err != nil {
+ return models.BugConnection{}, err
+ }
+
+ snap := b.Snapshot()
+
+ edges[i] = models.BugEdge{
+ Cursor: lazyBugEdge.Cursor,
+ Node: *snap,
+ }
+ }
+
+ return models.BugConnection{
+ Edges: edges,
+ PageInfo: info,
+ TotalCount: totalCount,
+ }, nil
+ }
+
+ return connections.StringCon(source, edger, conMaker, input)
}
func (repoResolver) Bug(ctx context.Context, obj *repoResolver, prefix string) (*bug.Snapshot, error) {