package module import ( "context" "forge.cadoles.com/arcad/edge/pkg/app" "forge.cadoles.com/arcad/edge/pkg/bus" "github.com/dop251/goja" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/logger" ) type LifecycleModule struct { backend *app.Server bus bus.Bus } func (m *LifecycleModule) Name() string { return "lifecycle" } func (m *LifecycleModule) Export(export *goja.Object) { } func (m *LifecycleModule) OnInit() error { if _, err := m.backend.ExecFuncByName("onInit"); err != nil { if errors.Is(err, app.ErrFuncDoesNotExist) { logger.Warn(context.Background(), "could not find onInit() function", logger.E(errors.WithStack(err))) return errors.WithStack(err) } } return nil } func (m *LifecycleModule) handleMessages() { ctx := context.Background() logger.Debug( ctx, "subscribing to bus messages", ) userConnectedMessages, err := m.bus.Subscribe(ctx, MessageNamespaceUserConnected) if err != nil { panic(errors.WithStack(err)) } userDisconnectedMessages, err := m.bus.Subscribe(ctx, MessageNamespaceUserDisconnected) if err != nil { panic(errors.WithStack(err)) } frontendMessageMessages, err := m.bus.Subscribe(ctx, MessageNamespaceFrontend) if err != nil { panic(errors.WithStack(err)) } defer func() { logger.Debug( ctx, "unsubscribing from bus messages", ) m.bus.Unsubscribe(ctx, MessageNamespaceFrontend, frontendMessageMessages) m.bus.Unsubscribe(ctx, MessageNamespaceUserDisconnected, userDisconnectedMessages) m.bus.Unsubscribe(ctx, MessageNamespaceUserConnected, userConnectedMessages) }() for { logger.Debug( ctx, "waiting for next message", ) select { case <-ctx.Done(): logger.Debug( ctx, "context done", ) return case msg := <-userConnectedMessages: userConnected, ok := msg.(*UserConnectedMessage) if !ok { logger.Error( ctx, "unexpected message type", logger.F("message", msg), ) continue } logger.Debug( ctx, "received user connected message", logger.F("message", userConnected), ) if _, err := m.backend.ExecFuncByName("onUserConnect"); err != nil { if errors.Is(err, app.ErrFuncDoesNotExist) { continue } logger.Error( ctx, "on user connected error", logger.E(err), ) } case msg := <-userDisconnectedMessages: userDisconnected, ok := msg.(*UserDisconnectedMessage) if !ok { logger.Error( ctx, "unexpected message type", logger.F("message", msg), ) continue } logger.Debug( ctx, "received user disconnected message", logger.F("message", userDisconnected), ) if _, err := m.backend.ExecFuncByName("onUserDisconnect"); err != nil { if errors.Is(err, app.ErrFuncDoesNotExist) { continue } logger.Error( ctx, "on user disconnected error", logger.E(err), ) } case msg := <-frontendMessageMessages: frontendMessage, ok := msg.(*FrontendMessage) if !ok { logger.Error( ctx, "unexpected message type", logger.F("message", msg), ) continue } logger.Debug( ctx, "received frontend message", logger.F("message", frontendMessage), ) if _, err := m.backend.ExecFuncByName("onUserMessage", frontendMessage.Data); err != nil { if errors.Is(err, app.ErrFuncDoesNotExist) { continue } logger.Error( ctx, "on user message error", logger.E(err), ) } } } } func LifecycleModuleFactory(bus bus.Bus) app.ServerModuleFactory { return func(backend *app.Server) app.ServerModule { module := &LifecycleModule{ backend: backend, bus: bus, } go module.handleMessages() return module } } var _ app.InitializableModule = &LifecycleModule{}