Skip to content

Commit 16c4398

Browse files
author
Jannis Pohlmann
committed
subscriptions: Add matching of subscriptions against entities
1 parent 448c050 commit 16c4398

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

ast.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package graphqlws
2+
3+
import (
4+
"github.com/graphql-go/graphql/language/ast"
5+
)
6+
7+
func operationDefinitionsWithOperation(
8+
doc *ast.Document,
9+
op string,
10+
) []*ast.OperationDefinition {
11+
defs := []*ast.OperationDefinition{}
12+
for _, node := range doc.Definitions {
13+
if node.GetKind() == "OperationDefinition" {
14+
if def, ok := node.(*ast.OperationDefinition); ok {
15+
defs = append(defs, def)
16+
}
17+
}
18+
}
19+
return defs
20+
}
21+
22+
func selectionSetsForOperationDefinitions(
23+
defs []*ast.OperationDefinition,
24+
) []*ast.SelectionSet {
25+
sets := []*ast.SelectionSet{}
26+
for _, def := range defs {
27+
if set := def.GetSelectionSet(); set != nil {
28+
sets = append(sets, set)
29+
}
30+
}
31+
return sets
32+
}
33+
34+
func nameForSelectionSet(set *ast.SelectionSet) (string, bool) {
35+
if len(set.Selections) >= 1 {
36+
if field, ok := set.Selections[0].(*ast.Field); ok {
37+
return field.Name.Value, true
38+
}
39+
}
40+
return "", false
41+
}
42+
43+
func namesForSelectionSets(sets []*ast.SelectionSet) []string {
44+
names := []string{}
45+
for _, set := range sets {
46+
if name, ok := nameForSelectionSet(set); ok {
47+
names = append(names, name)
48+
}
49+
}
50+
return names
51+
}
52+
53+
func subscriptionFieldNamesFromDocument(doc *ast.Document) []string {
54+
defs := operationDefinitionsWithOperation(doc, "subscription")
55+
sets := selectionSetsForOperationDefinitions(defs)
56+
return namesForSelectionSets(sets)
57+
}

subscriptions.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,27 @@ type Subscription struct {
3131
Query string
3232
Variables map[string]interface{}
3333
OperationName string
34-
SendData SubscriptionSendDataFunc
3534
Document *ast.Document
35+
Fields []string
36+
Connection Connection
37+
SendData SubscriptionSendDataFunc
38+
}
39+
40+
// MatchesField returns true if the subscription is for data that
41+
// belongs to the given field.
42+
func (s *Subscription) MatchesField(field string) bool {
43+
if s.Document == nil || len(s.Fields) == 0 {
44+
return false
45+
}
46+
47+
// The subscription matches the field if any of the queries have
48+
// the same name as the field
49+
for _, name := range s.Fields {
50+
if name == field {
51+
return true
52+
}
53+
}
54+
return false
3655
}
3756

3857
// ConnectionSubscriptions defines a map of all subscriptions of
@@ -113,6 +132,9 @@ func (m *subscriptionManager) AddSubscription(
113132
// Remember the query document for later
114133
subscription.Document = document
115134

135+
// Extract query names from the document (typically, there should only be one)
136+
subscription.Fields = subscriptionFieldNamesFromDocument(document)
137+
116138
// Allocate the connection's map of subscription IDs to
117139
// subscriptions on demand
118140
if m.subscriptions[conn] == nil {

0 commit comments

Comments
 (0)