Gisle Aune
6 years ago
7 changed files with 151 additions and 1 deletions
-
33cmd/rpdata-server/main.go
-
4graph2/graph.go
-
11graph2/queries/changes.go
-
4graph2/queries/resolver.go
-
8graph2/schema/root.gql
-
5models/changes/submit.go
-
87models/changes/subscribe.go
@ -0,0 +1,87 @@ |
|||||
|
package changes |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"sync" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/models" |
||||
|
) |
||||
|
|
||||
|
var subMutex sync.Mutex |
||||
|
var subList []*subscription |
||||
|
|
||||
|
type subscription struct { |
||||
|
Keys map[string]bool |
||||
|
Channel chan<- models.Change |
||||
|
WildCard bool |
||||
|
} |
||||
|
|
||||
|
// Subscribe subscribes to all changes.
|
||||
|
func Subscribe(ctx context.Context, keys []models.ChangeKey, wildcard bool) <-chan models.Change { |
||||
|
channel := make(chan models.Change, 64) |
||||
|
sub := &subscription{ |
||||
|
Keys: make(map[string]bool, len(keys)), |
||||
|
Channel: channel, |
||||
|
WildCard: wildcard, |
||||
|
} |
||||
|
|
||||
|
for _, key := range keys { |
||||
|
sub.Keys[mapKey(key)] = true |
||||
|
} |
||||
|
|
||||
|
subMutex.Lock() |
||||
|
subList = append(subList, sub) |
||||
|
subMutex.Unlock() |
||||
|
|
||||
|
go func() { |
||||
|
<-ctx.Done() |
||||
|
|
||||
|
subMutex.Lock() |
||||
|
for i := range subList { |
||||
|
if subList[i] == sub { |
||||
|
subList = append(subList[:i], subList[i+1:]...) |
||||
|
} |
||||
|
} |
||||
|
subMutex.Unlock() |
||||
|
}() |
||||
|
|
||||
|
return channel |
||||
|
} |
||||
|
|
||||
|
func pushToSubscribers(change models.Change) { |
||||
|
keys := make([]string, len(change.Keys)) |
||||
|
for i := range change.Keys { |
||||
|
keys[i] = mapKey(change.Keys[i]) |
||||
|
} |
||||
|
|
||||
|
subMutex.Lock() |
||||
|
SubLoop: |
||||
|
for _, sub := range subList { |
||||
|
if sub.WildCard && change.Listed { |
||||
|
select { |
||||
|
case sub.Channel <- change: |
||||
|
default: |
||||
|
} |
||||
|
} else { |
||||
|
for _, key := range keys { |
||||
|
if sub.Keys[key] { |
||||
|
select { |
||||
|
case sub.Channel <- change: |
||||
|
default: |
||||
|
} |
||||
|
|
||||
|
continue SubLoop |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
subMutex.Unlock() |
||||
|
} |
||||
|
|
||||
|
func mapKey(ck models.ChangeKey) string { |
||||
|
return ck.Model.String() + "." + ck.ID |
||||
|
} |
||||
|
|
||||
|
func init() { |
||||
|
subList = make([]*subscription, 0, 16) |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue