160 lines
3.2 KiB
Go
160 lines
3.2 KiB
Go
package net
|
|
|
|
import (
|
|
"context"
|
|
|
|
"forge.cadoles.com/arcad/edge/pkg/app"
|
|
"forge.cadoles.com/arcad/edge/pkg/bus"
|
|
edgeHTTP "forge.cadoles.com/arcad/edge/pkg/http"
|
|
"forge.cadoles.com/arcad/edge/pkg/module"
|
|
"forge.cadoles.com/arcad/edge/pkg/module/util"
|
|
"github.com/dop251/goja"
|
|
"github.com/pkg/errors"
|
|
"gitlab.com/wpetit/goweb/logger"
|
|
)
|
|
|
|
type Module struct {
|
|
server *app.Server
|
|
bus bus.Bus
|
|
}
|
|
|
|
func (m *Module) Name() string {
|
|
return "net"
|
|
}
|
|
|
|
func (m *Module) Export(export *goja.Object) {
|
|
if err := export.Set("broadcast", m.broadcast); err != nil {
|
|
panic(errors.Wrap(err, "could not set 'broadcast' function"))
|
|
}
|
|
|
|
if err := export.Set("send", m.send); err != nil {
|
|
panic(errors.Wrap(err, "could not set 'send' function"))
|
|
}
|
|
}
|
|
|
|
func (m *Module) broadcast(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
|
|
if len(call.Arguments) < 1 {
|
|
panic(rt.ToValue(errors.New("invalid number of argument")))
|
|
}
|
|
|
|
data := call.Argument(0).Export()
|
|
ctx := context.Background()
|
|
|
|
msg := module.NewServerMessage(ctx, data)
|
|
if err := m.bus.Publish(ctx, msg); err != nil {
|
|
panic(rt.ToValue(errors.WithStack(err)))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *Module) send(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
|
|
if len(call.Arguments) < 2 {
|
|
panic(rt.ToValue(errors.New("invalid number of argument")))
|
|
}
|
|
|
|
var ctx context.Context
|
|
|
|
firstArg := call.Argument(0)
|
|
|
|
sessionID, ok := firstArg.Export().(string)
|
|
if ok {
|
|
ctx = module.WithContext(context.Background(), map[module.ContextKey]any{
|
|
edgeHTTP.ContextKeySessionID: sessionID,
|
|
})
|
|
} else {
|
|
ctx = util.AssertContext(firstArg, rt)
|
|
}
|
|
|
|
data := call.Argument(1).Export()
|
|
|
|
msg := module.NewServerMessage(ctx, data)
|
|
if err := m.bus.Publish(ctx, msg); err != nil {
|
|
panic(rt.ToValue(errors.WithStack(err)))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *Module) handleClientMessages() {
|
|
ctx := context.Background()
|
|
|
|
logger.Debug(
|
|
ctx,
|
|
"subscribing to bus messages",
|
|
)
|
|
|
|
clientMessages, err := m.bus.Subscribe(ctx, module.MessageNamespaceClient)
|
|
if err != nil {
|
|
panic(errors.WithStack(err))
|
|
}
|
|
|
|
defer func() {
|
|
logger.Debug(
|
|
ctx,
|
|
"unsubscribing from bus messages",
|
|
)
|
|
|
|
m.bus.Unsubscribe(ctx, module.MessageNamespaceClient, clientMessages)
|
|
}()
|
|
|
|
for {
|
|
logger.Debug(
|
|
ctx,
|
|
"waiting for next message",
|
|
)
|
|
select {
|
|
case <-ctx.Done():
|
|
logger.Debug(
|
|
ctx,
|
|
"context done",
|
|
)
|
|
|
|
return
|
|
|
|
case msg := <-clientMessages:
|
|
clientMessage, ok := msg.(*module.ClientMessage)
|
|
if !ok {
|
|
logger.Error(
|
|
ctx,
|
|
"unexpected message type",
|
|
logger.F("message", msg),
|
|
)
|
|
|
|
continue
|
|
}
|
|
|
|
logger.Debug(
|
|
ctx,
|
|
"received client message",
|
|
logger.F("message", clientMessage),
|
|
)
|
|
|
|
if _, err := m.server.ExecFuncByName(clientMessage.Context, "onClientMessage", clientMessage.Context, clientMessage.Data); err != nil {
|
|
if errors.Is(err, app.ErrFuncDoesNotExist) {
|
|
continue
|
|
}
|
|
|
|
logger.Error(
|
|
ctx,
|
|
"on client message error",
|
|
logger.E(err),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func ModuleFactory(bus bus.Bus) app.ServerModuleFactory {
|
|
return func(server *app.Server) app.ServerModule {
|
|
module := &Module{
|
|
server: server,
|
|
bus: bus,
|
|
}
|
|
|
|
go module.handleClientMessages()
|
|
|
|
return module
|
|
}
|
|
}
|