5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 20:39:34 +08:00
wails/v2/internal/subsystem/call.go

149 lines
3.5 KiB
Go

package subsystem
import (
"encoding/json"
"fmt"
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/internal/messagedispatcher/message"
"github.com/wailsapp/wails/v2/internal/servicebus"
)
// Call is the Call subsystem. It manages all service bus messages
// starting with "call".
type Call struct {
quitChannel <-chan *servicebus.Message
callChannel <-chan *servicebus.Message
running bool
// bindings DB
DB *binding.DB
// ServiceBus
bus *servicebus.ServiceBus
// logger
logger logger.CustomLogger
}
// NewCall creates a new log subsystem
func NewCall(bus *servicebus.ServiceBus, logger *logger.Logger, DB *binding.DB) (*Call, error) {
// Register quit channel
quitChannel, err := bus.Subscribe("quit")
if err != nil {
return nil, err
}
// Subscribe to event messages
callChannel, err := bus.Subscribe("call:invoke")
if err != nil {
return nil, err
}
result := &Call{
quitChannel: quitChannel,
callChannel: callChannel,
logger: logger.CustomLogger("Call Subsystem"),
DB: DB,
bus: bus,
}
return result, nil
}
// Start the subsystem
func (c *Call) Start() error {
c.running = true
// Spin off a go routine
go func() {
for c.running {
select {
case <-c.quitChannel:
c.running = false
case callMessage := <-c.callChannel:
c.processCall(callMessage)
}
}
// Call shutdown
c.shutdown()
}()
return nil
}
func (c *Call) processCall(callMessage *servicebus.Message) {
c.logger.Trace("Got message: %+v", callMessage)
// Extract payload
payload := callMessage.Data().(*message.CallMessage)
// Lookup method
registeredMethod := c.DB.GetMethod(payload.Name)
// Check we have it
if registeredMethod == nil {
c.sendError(fmt.Errorf("Method not registered"), payload, callMessage.Target())
return
}
c.logger.Trace("Got registered method: %+v", registeredMethod)
result, err := registeredMethod.Call(payload.Args)
if err != nil {
c.sendError(err, payload, callMessage.Target())
return
}
c.logger.Trace("registeredMethod.Call: %+v, %+v", result, err)
// process result
c.sendResult(result, payload, callMessage.Target())
}
func (c *Call) sendResult(result interface{}, payload *message.CallMessage, clientID string) {
c.logger.Trace("Sending success result with CallbackID '%s' : %+v\n", payload.CallbackID, result)
message := &CallbackMessage{
Result: result,
CallbackID: payload.CallbackID,
}
messageData, err := json.Marshal(message)
c.logger.Trace("json message data: %+v\n", string(messageData))
if err != nil {
// what now?
c.logger.Fatal(err.Error())
}
c.bus.PublishForTarget("call:result", string(messageData), clientID)
}
func (c *Call) sendError(err error, payload *message.CallMessage, clientID string) {
c.logger.Trace("Sending error result with CallbackID '%s' : %+v\n", payload.CallbackID, err.Error())
message := &CallbackMessage{
Err: err.Error(),
CallbackID: payload.CallbackID,
}
messageData, err := json.Marshal(message)
c.logger.Trace("json message data: %+v\n", string(messageData))
if err != nil {
// what now?
c.logger.Fatal(err.Error())
}
c.bus.PublishForTarget("call:result", string(messageData), clientID)
}
func (c *Call) shutdown() {
c.logger.Trace("Shutdown")
}
// CallbackMessage defines a message that contains the result of a call
type CallbackMessage struct {
Result interface{} `json:"result"`
Err string `json:"error"`
CallbackID string `json:"callbackid"`
}