added long pooling

This commit is contained in:
Sergey Chubaryan 2024-08-16 00:37:15 +03:00
parent 19297b331e
commit 17b0970364
5 changed files with 116 additions and 0 deletions

View File

@ -2,6 +2,7 @@ package main
import (
"backend/src/args_parser"
"backend/src/client_notifier"
"backend/src/config"
"backend/src/core/models"
"backend/src/core/repos"
@ -80,6 +81,8 @@ func main() {
emailRepo := repos.NewEmailRepo()
actionTokenRepo := repos.NewActionTokenRepo(sqlDb)
clientNotifier := client_notifier.NewBasicNotifier()
userService := services.NewUserService(
services.UserServiceDeps{
Jwt: jwtUtil,
@ -116,6 +119,9 @@ func main() {
dummyGroup.Use(middleware.NewAuthMiddleware(userService))
dummyGroup.GET("/", handlers.NewDummyHandler())
lpGroup := r.Group("/pooling")
lpGroup.GET("/", handlers.NewLongPoolingHandler(clientNotifier))
listenAddr := fmt.Sprintf(":%d", conf.GetPort())
logger.Log().Msgf("server listening on %s", listenAddr)

View File

@ -0,0 +1,12 @@
package client_notifier
type Event struct {
Type EventType
Data []byte
}
type EventType string
const (
EventTypeEmailConfirmed EventType = "event_email_confirmed"
)

View File

@ -0,0 +1,57 @@
package client_notifier
import "sync"
type ClientNotifier interface {
RegisterClient(id string) <-chan Event
UnregisterClient(id string)
NotifyClient(id string, e Event)
}
type client struct {
id string
eventChan chan Event
}
func NewBasicNotifier() ClientNotifier {
return &basicNotifier{
m: &sync.RWMutex{},
clients: map[string]client{},
}
}
type basicNotifier struct {
m *sync.RWMutex
clients map[string]client
}
func (p *basicNotifier) RegisterClient(id string) <-chan Event {
p.m.Lock()
defer p.m.Unlock()
eventChan := make(chan Event)
p.clients[id] = client{
id: id,
eventChan: eventChan,
}
return eventChan
}
func (p *basicNotifier) UnregisterClient(id string) {
p.m.Lock()
defer p.m.Unlock()
delete(p.clients, id)
}
func (p *basicNotifier) NotifyClient(id string, e Event) {
p.m.RLock()
defer p.m.RUnlock()
client, ok := p.clients[id]
if !ok {
return
}
client.eventChan <- e
}

View File

@ -0,0 +1,27 @@
package handlers
import (
"backend/src/client_notifier"
"backend/src/server/utils"
"github.com/gin-gonic/gin"
)
func NewLongPoolingHandler(notifier client_notifier.ClientNotifier) gin.HandlerFunc {
return func(c *gin.Context) {
user := utils.GetUserFromRequest(c)
if user == nil {
c.Data(403, "plain/text", []byte("Unauthorized"))
return
}
eventChan := notifier.RegisterClient(user.Id)
select {
case <-c.Done():
notifier.UnregisterClient(user.Id)
case event := <-eventChan:
c.Data(200, "application/json", event.Data)
}
}
}

14
src/server/utils/user.go Normal file
View File

@ -0,0 +1,14 @@
package utils
import (
"backend/src/core/models"
"github.com/gin-gonic/gin"
)
func GetUserFromRequest(c *gin.Context) *models.UserDTO {
if user, ok := c.Get("user"); ok {
return user.(*models.UserDTO)
}
return nil
}