124 lines
3.6 KiB
Go
124 lines
3.6 KiB
Go
package localserver
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type ChatRequestScheduler struct {
|
|
handlersPublishers []chan<- *ChatRequest
|
|
handlersDataChannelDispatchCallbacks []DispatchDataChannelCallBack
|
|
}
|
|
|
|
type ChatRequest struct {
|
|
ReqType string `json:"reqType"`
|
|
Payload map[string]any
|
|
From string
|
|
}
|
|
|
|
type ChatResponse struct {
|
|
Type string `json:"type"`
|
|
To string `json:"to"`
|
|
From string `json:"from"`
|
|
Payload map[string]any `json:"payload"`
|
|
}
|
|
|
|
type ChatRequestHandler interface {
|
|
Init(ctx context.Context, initiator, target, initiatorNodeID, targetNodeID string) (err error)
|
|
Subscribe(ctx context.Context, publisher <-chan *ChatRequest) (reqChan chan *ChatRequest, done chan struct{}, errCh chan error)
|
|
handleChatRequest(ctx context.Context, req *ChatRequest) (err error)
|
|
handleDataChannel(ctx context.Context, dc *DataChannel) (catched bool)
|
|
}
|
|
|
|
func NewChatRequestScheduler(initiator, target, initiatorNodeID, targetNodeID string, handlers ...ChatRequestHandler) (chatRequestScheduler *ChatRequestScheduler, handlerErrCh chan error) {
|
|
chatRequestScheduler = new(ChatRequestScheduler)
|
|
chatRequestScheduler.handlersPublishers = make([]chan<- *ChatRequest, 0)
|
|
chatRequestScheduler.handlersDataChannelDispatchCallbacks = make([]DispatchDataChannelCallBack, 0)
|
|
handlerErrCh = make(chan error)
|
|
reqChans := []chan *ChatRequest{}
|
|
for _, handler := range handlers {
|
|
publisher := make(chan *ChatRequest, 100)
|
|
chatRequestScheduler.handlersPublishers = append(chatRequestScheduler.handlersPublishers, publisher)
|
|
chatRequestScheduler.handlersDataChannelDispatchCallbacks = append(chatRequestScheduler.handlersDataChannelDispatchCallbacks, handler.handleDataChannel)
|
|
fmt.Println("this is the fking handler")
|
|
fmt.Println(handler)
|
|
reqChan, done, errCh := handler.Subscribe(context.Background(), publisher)
|
|
go func(done <-chan struct{}, errCh <-chan error) {
|
|
for {
|
|
select {
|
|
case <-done:
|
|
return
|
|
case handlerErrCh <- <-errCh:
|
|
}
|
|
}
|
|
}(done, errCh)
|
|
reqChans = append(reqChans, reqChan)
|
|
}
|
|
for _, reqChan := range reqChans {
|
|
go func(reqChan <-chan *ChatRequest) {
|
|
done, errCh := chatRequestScheduler.Schedule(reqChan)
|
|
for {
|
|
select {
|
|
case <-done:
|
|
return
|
|
case <-errCh:
|
|
// logger.Println(e)
|
|
}
|
|
}
|
|
}(reqChan)
|
|
}
|
|
for _, handler := range handlers {
|
|
if ierr := handler.Init(context.Background(), initiator, target, initiatorNodeID, targetNodeID); ierr != nil {
|
|
// logger.Println(ierr)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (crs *ChatRequestScheduler) Schedule(reqChan <-chan *ChatRequest) (done chan struct{}, errCh chan error) {
|
|
done, errCh = make(chan struct{}), make(chan error)
|
|
go func() {
|
|
for req := range reqChan {
|
|
go func(r *ChatRequest) {
|
|
for _, publisher := range crs.handlersPublishers {
|
|
publisher <- r
|
|
}
|
|
}(req)
|
|
}
|
|
done <- struct{}{}
|
|
}()
|
|
return
|
|
}
|
|
|
|
func (crs *ChatRequestScheduler) DispatchDataChannel(ctx context.Context, dc *DataChannel) (catched bool) {
|
|
wg, lock := sync.WaitGroup{}, &sync.Mutex{}
|
|
timeoutCtx, cancel := context.WithTimeout(ctx, 15*time.Second)
|
|
defer cancel()
|
|
done := make(chan struct{})
|
|
for _, dispatchCallback := range crs.handlersDataChannelDispatchCallbacks {
|
|
wg.Add(1)
|
|
go func(w *sync.WaitGroup, dispatchCallback DispatchDataChannelCallBack) {
|
|
defer w.Done()
|
|
val := dispatchCallback(timeoutCtx, dc)
|
|
if val {
|
|
lock.Lock()
|
|
catched = true
|
|
lock.Unlock()
|
|
return
|
|
}
|
|
}(&wg, dispatchCallback)
|
|
}
|
|
go func() {
|
|
wg.Wait()
|
|
done <- struct{}{}
|
|
}()
|
|
select {
|
|
case <-done:
|
|
return
|
|
case <-timeoutCtx.Done():
|
|
return false
|
|
}
|
|
}
|