Skip to content

Commit

Permalink
Add match creation sub + sub on points scored for a match only
Browse files Browse the repository at this point in the history
  • Loading branch information
tsauvajon committed Jun 14, 2018
1 parent 0530d26 commit 335980f
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 48 deletions.
18 changes: 13 additions & 5 deletions resolvers/events.go
Expand Up @@ -6,9 +6,13 @@ import (

// PointScoredEvent : dispatched when a point is scored
type PointScoredEvent struct {
team bool
match *tennis.Match
tennis *tennis.Client
team bool
match *tennis.Match
}

// MatchCreatedEvent : a match was created
type MatchCreatedEvent struct {
match *tennis.Match
}

// Team : resolves the team that scored the point
Expand All @@ -18,6 +22,10 @@ func (r *PointScoredEvent) Team() bool {

// Match : resolves the match where the point was score
func (r *PointScoredEvent) Match() (*MatchResolver, error) {
match, err := r.tennis.GetMatchByID(r.match.ID)
return &MatchResolver{match: match}, err
return &MatchResolver{match: r.match}, nil
}

// Match : resolves the match where the point was score
func (r *MatchCreatedEvent) Match() (*MatchResolver, error) {
return &MatchResolver{match: r.match}, nil
}
37 changes: 37 additions & 0 deletions resolvers/mutation.go
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"time"

graphql "github.com/poudre-aux-yeux/graphql-go"
"github.com/poudre-aux-yeux/rapiquette/tennis"
Expand Down Expand Up @@ -56,6 +57,11 @@ type updateStadiumArgs struct {
Stadium tennis.Stadium
}

type scorePointArgs struct {
MatchID graphql.ID
Team bool
}

// CreateMatch : mutation to create a match
func (r *RootResolver) CreateMatch(ctx context.Context, args *createMatchArgs) (*MatchResolver, error) {
if args.Match.RefLink == "" {
Expand Down Expand Up @@ -114,6 +120,15 @@ func (r *RootResolver) CreateMatch(ctx context.Context, args *createMatchArgs) (

match, err := r.tennis.CreateMatch(args.Match)

// Dispatch the event
e := &MatchCreatedEvent{match: match}
go func() {
select {
case r.matchCreatedEvents <- e:
case <-time.After(1 * time.Second):
}
}()

return &MatchResolver{match: match, tennis: r.tennis}, err
}

Expand Down Expand Up @@ -283,6 +298,28 @@ func (r *RootResolver) UpdateStadium(ctx context.Context, args *updateStadiumArg
return &StadiumResolver{stadium: stadium}, err
}

// ScorePoint : score a point for a team in a match
func (r *RootResolver) ScorePoint(args struct{ Point struct{ scorePointArgs } }) (*PointScoredEvent, error) {
m, err := r.tennis.GetMatchByID(args.Point.MatchID)

if err != nil {
return nil, fmt.Errorf("couldn't get the match %s: %v", args.Point.MatchID, err)
}

e := &PointScoredEvent{match: m, team: args.Point.Team}
go func() {
select {
case r.pointScoredEvents <- e:
case <-time.After(1 * time.Second):
}
}()

// TODO: save the event in the message broker
// or somewhere else

return e, nil
}

func (r *RootResolver) existsInSet(set string, key graphql.ID) error {
if ex, err := r.tennis.KeyExistsInSet(set, string(key)); err != nil {
return err
Expand Down
21 changes: 13 additions & 8 deletions resolvers/root.go
Expand Up @@ -22,21 +22,26 @@ func NewRoot(tennis *tennis.Client, raquette *raquette.Client) (*RootResolver, e
return nil, ErrUnableToResolve
}
r := &RootResolver{
tennis: tennis,
raquette: raquette,
pointScoredEvents: make(chan *PointScoredEvent),
pointScoredSubscriber: make(chan *PointScoredSubscriber),
tennis: tennis,
raquette: raquette,
pointScoredEvents: make(chan *PointScoredEvent),
pointScoredSubscriber: make(chan *PointScoredSubscriber),
matchCreatedEvents: make(chan *MatchCreatedEvent),
matchCreatedSubscriber: make(chan *MatchCreatedSubscriber),
}

go r.broadcastPointScored()
go r.broadcastMatchCreated()

return r, nil
}

// RootResolver : default resolver
type RootResolver struct {
tennis *tennis.Client
raquette *raquette.Client
pointScoredEvents chan *PointScoredEvent
pointScoredSubscriber chan *PointScoredSubscriber
tennis *tennis.Client
raquette *raquette.Client
pointScoredEvents chan *PointScoredEvent
pointScoredSubscriber chan *PointScoredSubscriber
matchCreatedEvents chan *MatchCreatedEvent
matchCreatedSubscriber chan *MatchCreatedSubscriber
}
13 changes: 11 additions & 2 deletions resolvers/subscribers.go
@@ -1,7 +1,16 @@
package resolvers

// PointScoredSubscriber : ??
import graphql "github.com/poudre-aux-yeux/graphql-go"

// PointScoredSubscriber : subscribers to pointScored
type PointScoredSubscriber struct {
stop <-chan struct{}
events chan<- *PointScoredEvent
matchID graphql.ID
}

// MatchCreatedSubscriber : subscribers to matchCreated
type MatchCreatedSubscriber struct {
stop <-chan struct{}
events chan<- *PointScoredEvent
events chan<- *MatchCreatedEvent
}
75 changes: 44 additions & 31 deletions resolvers/subscriptions.go
Expand Up @@ -2,50 +2,29 @@ package resolvers

import (
"context"
"fmt"
"math/rand"
"time"

graphql "github.com/poudre-aux-yeux/graphql-go"
)

type scorePointArgs struct {
MatchID graphql.ID
Team bool
}

// ScorePoint : score a point for a team in a match
func (r *RootResolver) ScorePoint(args struct{ Point struct{ scorePointArgs } }) (*PointScoredEvent, error) {
m, err := r.tennis.GetMatchByID(args.Point.MatchID)

if err != nil {
return nil, fmt.Errorf("couldn't get the match %s: %v", args.Point.MatchID, err)
}

e := &PointScoredEvent{match: m, team: args.Point.Team, tennis: r.tennis}
go func() {
select {
case r.pointScoredEvents <- e:
case <-time.After(1 * time.Second):
}
}()
return e, nil
}

// PointScored : A new point was scored in a match
func (r *RootResolver) PointScored(ctx context.Context) <-chan *PointScoredEvent {
// PointScored : subscribe to scored points for every match
func (r *RootResolver) PointScored(ctx context.Context, args struct{ MatchID graphql.ID }) <-chan *PointScoredEvent {
c := make(chan *PointScoredEvent)
// NOTE: this could take a while
r.pointScoredSubscriber <- &PointScoredSubscriber{events: c, stop: ctx.Done()}
r.pointScoredSubscriber <- &PointScoredSubscriber{events: c, stop: ctx.Done(), matchID: args.MatchID}
return c
}

// MatchCreated : subscribe to match creations
func (r *RootResolver) MatchCreated(ctx context.Context) <-chan *MatchCreatedEvent {
c := make(chan *MatchCreatedEvent)
r.matchCreatedSubscriber <- &MatchCreatedSubscriber{events: c, stop: ctx.Done()}
return c
}

func (r *RootResolver) broadcastPointScored() {
subscribers := map[string]*PointScoredSubscriber{}
unsubscribe := make(chan string)

// NOTE: subscribing and sending events are at odds.
for {
select {
case id := <-unsubscribe:
Expand All @@ -54,6 +33,9 @@ func (r *RootResolver) broadcastPointScored() {
subscribers[randomID()] = s
case e := <-r.pointScoredEvents:
for id, s := range subscribers {
if s.matchID != e.match.ID {
continue
}
go func(id string, s *PointScoredSubscriber) {
select {
case <-s.stop:
Expand All @@ -66,7 +48,38 @@ func (r *RootResolver) broadcastPointScored() {
case <-s.stop:
unsubscribe <- id
case s.events <- e:
case <-time.After(time.Second):
case <-time.After(1 * time.Second):
}
}(id, s)
}
}
}
}

func (r *RootResolver) broadcastMatchCreated() {
subscribers := map[string]*MatchCreatedSubscriber{}
unsubscribe := make(chan string)
for {
select {
case id := <-unsubscribe:
delete(subscribers, id)
case s := <-r.matchCreatedSubscriber:
subscribers[randomID()] = s
case e := <-r.matchCreatedEvents:
for id, s := range subscribers {
go func(id string, s *MatchCreatedSubscriber) {
select {
case <-s.stop:
unsubscribe <- id
return
default:
}

select {
case <-s.stop:
unsubscribe <- id
case s.events <- e:
case <-time.After(1 * time.Second):
}
}(id, s)
}
Expand Down
8 changes: 7 additions & 1 deletion schema/events.graphql
@@ -1,7 +1,13 @@
# Dispatched when a point is scored
# A point was scored
type PointScoredEvent {
# The match where the point was scored
match: Match!
# The team that scored the point. True = home, false = away
team: Boolean!
}

# A match was created
type MatchCreatedEvent {
# The created match
match: Match!
}
3 changes: 2 additions & 1 deletion schema/subscriptions.graphql
@@ -1,3 +1,4 @@
type Subscription {
pointScored(): PointScoredEvent!
pointScored(matchId: ID!): PointScoredEvent!
matchCreated(): MatchCreatedEvent!
}

0 comments on commit 335980f

Please sign in to comment.