github.com/jepp2078/gqlgen@v0.7.2/example/chat/resolvers.go (about) 1 //go:generate gorunpkg github.com/99designs/gqlgen 2 3 package chat 4 5 import ( 6 context "context" 7 "math/rand" 8 "sync" 9 "time" 10 ) 11 12 type resolver struct { 13 Rooms map[string]*Chatroom 14 mu sync.Mutex // nolint: structcheck 15 } 16 17 func (r *resolver) Mutation() MutationResolver { 18 return &mutationResolver{r} 19 } 20 21 func (r *resolver) Query() QueryResolver { 22 return &queryResolver{r} 23 } 24 25 func (r *resolver) Subscription() SubscriptionResolver { 26 return &subscriptionResolver{r} 27 } 28 29 func New() Config { 30 return Config{ 31 Resolvers: &resolver{ 32 Rooms: map[string]*Chatroom{}, 33 }, 34 } 35 } 36 37 type Chatroom struct { 38 Name string 39 Messages []Message 40 Observers map[string]chan Message 41 } 42 43 type mutationResolver struct{ *resolver } 44 45 func (r *mutationResolver) Post(ctx context.Context, text string, username string, roomName string) (Message, error) { 46 r.mu.Lock() 47 room := r.Rooms[roomName] 48 if room == nil { 49 room = &Chatroom{Name: roomName, Observers: map[string]chan Message{}} 50 r.Rooms[roomName] = room 51 } 52 r.mu.Unlock() 53 54 message := Message{ 55 ID: randString(8), 56 CreatedAt: time.Now(), 57 Text: text, 58 CreatedBy: username, 59 } 60 61 room.Messages = append(room.Messages, message) 62 r.mu.Lock() 63 for _, observer := range room.Observers { 64 observer <- message 65 } 66 r.mu.Unlock() 67 return message, nil 68 } 69 70 type queryResolver struct{ *resolver } 71 72 func (r *queryResolver) Room(ctx context.Context, name string) (*Chatroom, error) { 73 r.mu.Lock() 74 room := r.Rooms[name] 75 if room == nil { 76 room = &Chatroom{Name: name, Observers: map[string]chan Message{}} 77 r.Rooms[name] = room 78 } 79 r.mu.Unlock() 80 81 return room, nil 82 } 83 84 type subscriptionResolver struct{ *resolver } 85 86 func (r *subscriptionResolver) MessageAdded(ctx context.Context, roomName string) (<-chan Message, error) { 87 r.mu.Lock() 88 room := r.Rooms[roomName] 89 if room == nil { 90 room = &Chatroom{Name: roomName, Observers: map[string]chan Message{}} 91 r.Rooms[roomName] = room 92 } 93 r.mu.Unlock() 94 95 id := randString(8) 96 events := make(chan Message, 1) 97 98 go func() { 99 <-ctx.Done() 100 r.mu.Lock() 101 delete(room.Observers, id) 102 r.mu.Unlock() 103 }() 104 105 r.mu.Lock() 106 room.Observers[id] = events 107 r.mu.Unlock() 108 109 return events, nil 110 } 111 112 var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 113 114 func randString(n int) string { 115 b := make([]rune, n) 116 for i := range b { 117 b[i] = letterRunes[rand.Intn(len(letterRunes))] 118 } 119 return string(b) 120 }