refactor(plugins): simplify websocket callback invocation by creating a generic helper function

Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Deluan
2026-02-02 08:59:40 +01:00
parent ebbc31f1ab
commit 7b709899a1
+17 -70
View File
@@ -324,105 +324,52 @@ func (s *webSocketServiceImpl) readLoop(ctx context.Context, connectionID string
}
}
func (s *webSocketServiceImpl) invokeOnTextMessage(ctx context.Context, connectionID, message string) {
// invokeWebSocketCallback is a generic helper that handles the common callback invocation pattern.
func invokeWebSocketCallback[I any](ctx context.Context, s *webSocketServiceImpl, funcName string, input I, callbackName string, connectionID string) {
instance := s.getPluginInstance()
if instance == nil {
return
}
input := capabilities.OnTextMessageRequest{
ConnectionID: connectionID,
Message: message,
}
// Create a timeout context for this callback invocation
callbackCtx, cancel := context.WithTimeout(ctx, webSocketCallbackTimeout)
defer cancel()
start := time.Now()
err := callPluginFunctionNoOutput(callbackCtx, instance, FuncWebSocketOnTextMessage, input)
err := callPluginFunctionNoOutput(callbackCtx, instance, funcName, input)
if err != nil {
// Don't log error if function simply doesn't exist (optional callback)
if !errors.Is(errFunctionNotFound, err) {
log.Error(ctx, "WebSocket text message callback failed", "plugin", s.pluginName, "connectionID", connectionID, "duration", time.Since(start), err)
log.Error(ctx, "WebSocket "+callbackName+" callback failed", "plugin", s.pluginName, "connectionID", connectionID, "duration", time.Since(start), err)
}
}
}
func (s *webSocketServiceImpl) invokeOnTextMessage(ctx context.Context, connectionID, message string) {
invokeWebSocketCallback(ctx, s, FuncWebSocketOnTextMessage, capabilities.OnTextMessageRequest{
ConnectionID: connectionID,
Message: message,
}, "text message", connectionID)
}
func (s *webSocketServiceImpl) invokeOnBinaryMessage(ctx context.Context, connectionID string, data []byte) {
instance := s.getPluginInstance()
if instance == nil {
return
}
input := capabilities.OnBinaryMessageRequest{
invokeWebSocketCallback(ctx, s, FuncWebSocketOnBinaryMessage, capabilities.OnBinaryMessageRequest{
ConnectionID: connectionID,
Data: base64.StdEncoding.EncodeToString(data),
}
// Create a timeout context for this callback invocation
callbackCtx, cancel := context.WithTimeout(ctx, webSocketCallbackTimeout)
defer cancel()
start := time.Now()
err := callPluginFunctionNoOutput(callbackCtx, instance, FuncWebSocketOnBinaryMessage, input)
if err != nil {
// Don't log error if function simply doesn't exist (optional callback)
if !errors.Is(errFunctionNotFound, err) {
log.Error(ctx, "WebSocket binary message callback failed", "plugin", s.pluginName, "connectionID", connectionID, "duration", time.Since(start), err)
}
}
}, "binary message", connectionID)
}
func (s *webSocketServiceImpl) invokeOnError(ctx context.Context, connectionID, errorMsg string) {
instance := s.getPluginInstance()
if instance == nil {
return
}
input := capabilities.OnErrorRequest{
invokeWebSocketCallback(ctx, s, FuncWebSocketOnError, capabilities.OnErrorRequest{
ConnectionID: connectionID,
Error: errorMsg,
}
// Create a timeout context for this callback invocation
callbackCtx, cancel := context.WithTimeout(ctx, webSocketCallbackTimeout)
defer cancel()
start := time.Now()
err := callPluginFunctionNoOutput(callbackCtx, instance, FuncWebSocketOnError, input)
if err != nil {
// Don't log error if function simply doesn't exist (optional callback)
if !errors.Is(errFunctionNotFound, err) {
log.Error(ctx, "WebSocket error callback failed", "plugin", s.pluginName, "connectionID", connectionID, "duration", time.Since(start), err)
}
}
}, "error", connectionID)
}
func (s *webSocketServiceImpl) invokeOnClose(ctx context.Context, connectionID string, code int32, reason string) {
instance := s.getPluginInstance()
if instance == nil {
return
}
input := capabilities.OnCloseRequest{
invokeWebSocketCallback(ctx, s, FuncWebSocketOnClose, capabilities.OnCloseRequest{
ConnectionID: connectionID,
Code: code,
Reason: reason,
}
// Create a timeout context for this callback invocation
callbackCtx, cancel := context.WithTimeout(ctx, webSocketCallbackTimeout)
defer cancel()
start := time.Now()
err := callPluginFunctionNoOutput(callbackCtx, instance, FuncWebSocketOnClose, input)
if err != nil {
// Don't log error if function simply doesn't exist (optional callback)
if !errors.Is(errFunctionNotFound, err) {
log.Error(ctx, "WebSocket close callback failed", "plugin", s.pluginName, "connectionID", connectionID, "duration", time.Since(start), err)
}
}
}, "close", connectionID)
}
func (s *webSocketServiceImpl) getPluginInstance() *plugin {