From 3da1990543a75e63dcb161491503e1517654132b Mon Sep 17 00:00:00 2001 From: Jono Wenger <jono@elixxir.io> Date: Fri, 6 Jan 2023 10:37:44 -0800 Subject: [PATCH] Improve logging --- indexedDb/channels/handlers.go | 158 ++++++++++------------ indexedDb/channels/implementation_test.go | 14 +- indexedDb/channels/init.go | 4 +- indexedDb/channels/main.go | 2 +- indexedDb/dm/handlers.go | 110 +++++++-------- indexedDb/dm/init.go | 4 +- indexedDb/dm/main.go | 2 +- indexedDb/messageHandler.go | 59 +++++--- indexedDbWorker/channels/init.go | 7 +- indexedDbWorker/dm/init.go | 6 +- indexedDbWorker/worker.go | 81 ++++++----- 11 files changed, 223 insertions(+), 224 deletions(-) diff --git a/indexedDb/channels/handlers.go b/indexedDb/channels/handlers.go index 5fefb65e..9a1ee663 100644 --- a/indexedDb/channels/handlers.go +++ b/indexedDb/channels/handlers.go @@ -20,7 +20,7 @@ import ( "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/crypto/message" "gitlab.com/elixxir/xxdk-wasm/indexedDb" - "gitlab.com/elixxir/xxdk-wasm/indexedDbWorker" + worker "gitlab.com/elixxir/xxdk-wasm/indexedDbWorker" mChannels "gitlab.com/elixxir/xxdk-wasm/indexedDbWorker/channels" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/primitives/id" @@ -37,28 +37,26 @@ type manager struct { // RegisterHandlers registers all the reception handlers to manage messages from // the main thread for the channels.EventModel. func (m *manager) RegisterHandlers() { - - m.mh.RegisterHandler(indexedDbWorker.NewWASMEventModelTag, m.newWASMEventModelHandler) - m.mh.RegisterHandler(indexedDbWorker.JoinChannelTag, m.joinChannelHandler) - m.mh.RegisterHandler(indexedDbWorker.LeaveChannelTag, m.leaveChannelHandler) - m.mh.RegisterHandler(indexedDbWorker.ReceiveMessageTag, m.receiveMessageHandler) - m.mh.RegisterHandler(indexedDbWorker.ReceiveReplyTag, m.receiveReplyHandler) - m.mh.RegisterHandler(indexedDbWorker.ReceiveReactionTag, m.receiveReactionHandler) - m.mh.RegisterHandler(indexedDbWorker.UpdateFromUUIDTag, m.updateFromUUIDHandler) - m.mh.RegisterHandler(indexedDbWorker.UpdateFromMessageIDTag, m.updateFromMessageIDHandler) - m.mh.RegisterHandler(indexedDbWorker.GetMessageTag, m.getMessageHandler) - m.mh.RegisterHandler(indexedDbWorker.DeleteMessageTag, m.deleteMessageHandler) + m.mh.RegisterHandler(worker.NewWASMEventModelTag, m.newWASMEventModelHandler) + m.mh.RegisterHandler(worker.JoinChannelTag, m.joinChannelHandler) + m.mh.RegisterHandler(worker.LeaveChannelTag, m.leaveChannelHandler) + m.mh.RegisterHandler(worker.ReceiveMessageTag, m.receiveMessageHandler) + m.mh.RegisterHandler(worker.ReceiveReplyTag, m.receiveReplyHandler) + m.mh.RegisterHandler(worker.ReceiveReactionTag, m.receiveReactionHandler) + m.mh.RegisterHandler(worker.UpdateFromUUIDTag, m.updateFromUUIDHandler) + m.mh.RegisterHandler(worker.UpdateFromMessageIDTag, m.updateFromMessageIDHandler) + m.mh.RegisterHandler(worker.GetMessageTag, m.getMessageHandler) + m.mh.RegisterHandler(worker.DeleteMessageTag, m.deleteMessageHandler) } // newWASMEventModelHandler is the handler for NewWASMEventModel. Returns nil on // success or an error message on failure. -func (m *manager) newWASMEventModelHandler(data []byte) []byte { +func (m *manager) newWASMEventModelHandler(data []byte) ([]byte, error) { var msg mChannels.NewWASMEventModelMessage err := json.Unmarshal(data, &msg) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal "+ - "NewWASMEventModelMessage from main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) } // Create new encryption cipher @@ -66,17 +64,16 @@ func (m *manager) newWASMEventModelHandler(data []byte) []byte { encryption, err := cryptoChannel.NewCipherFromJSON( []byte(msg.EncryptionJSON), rng.GetStream()) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal channel cipher from "+ - "main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal Cipher from main thread: %+v", err) } m.model, err = NewWASMEventModel(msg.Path, encryption, m.messageReceivedCallback, m.storeEncryptionStatus) if err != nil { - return []byte(err.Error()) + return []byte(err.Error()), nil } - return nil + return nil, nil } // messageReceivedCallback sends calls to the MessageReceivedCallback in the @@ -100,7 +97,7 @@ func (m *manager) messageReceivedCallback( // Send it to the main thread m.mh.SendResponse( - indexedDbWorker.GetMessageTag, indexedDbWorker.InitID, data) + worker.GetMessageTag, worker.InitID, data) } // storeEncryptionStatus augments the functionality of @@ -122,15 +119,15 @@ func (m *manager) storeEncryptionStatus( // Register response handler with channel that will wait for the response responseChan := make(chan []byte) - m.mh.RegisterHandler(indexedDbWorker.EncryptionStatusTag, - func(data []byte) []byte { + m.mh.RegisterHandler(worker.EncryptionStatusTag, + func(data []byte) ([]byte, error) { responseChan <- data - return nil + return nil, nil }) // Send encryption status to main thread m.mh.SendResponse( - indexedDbWorker.EncryptionStatusTag, indexedDbWorker.InitID, data) + worker.EncryptionStatusTag, worker.InitID, data) // Wait for response var response mChannels.EncryptionStatusReply @@ -139,10 +136,10 @@ func (m *manager) storeEncryptionStatus( if err = json.Unmarshal(responseData, &response); err != nil { return false, err } - case <-time.After(indexedDbWorker.ResponseTimeout): + case <-time.After(worker.ResponseTimeout): return false, errors.Errorf("timed out after %s waiting for "+ "response about the database encryption status from local "+ - "storage in the main thread", indexedDbWorker.ResponseTimeout) + "storage in the main thread", worker.ResponseTimeout) } // If the response contain an error, return it @@ -156,42 +153,39 @@ func (m *manager) storeEncryptionStatus( // joinChannelHandler is the handler for wasmModel.JoinChannel. Always returns // nil; meaning, no response is supplied (or expected). -func (m *manager) joinChannelHandler(data []byte) []byte { +func (m *manager) joinChannelHandler(data []byte) ([]byte, error) { var channel cryptoBroadcast.Channel err := json.Unmarshal(data, &channel) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal broadcast.Channel from "+ - "main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", channel, err) } m.model.JoinChannel(&channel) - return nil + return nil, nil } // leaveChannelHandler is the handler for wasmModel.LeaveChannel. Always returns // nil; meaning, no response is supplied (or expected). -func (m *manager) leaveChannelHandler(data []byte) []byte { +func (m *manager) leaveChannelHandler(data []byte) ([]byte, error) { channelID, err := id.Unmarshal(data) if err != nil { - jww.ERROR.Printf( - "Could not unmarshal channel ID from main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", channelID, err) } m.model.LeaveChannel(channelID) - return nil + return nil, nil } // receiveMessageHandler is the handler for wasmModel.ReceiveMessage. Returns // nil on error or the JSON marshalled UUID (uint64) on success. -func (m *manager) receiveMessageHandler(data []byte) []byte { +func (m *manager) receiveMessageHandler(data []byte) ([]byte, error) { var msg channels.ModelMessage err := json.Unmarshal(data, &msg) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal channels.ModelMessage "+ - "from main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) } uuid := m.model.ReceiveMessage(msg.ChannelID, msg.MessageID, msg.Nickname, @@ -201,22 +195,19 @@ func (m *manager) receiveMessageHandler(data []byte) []byte { uuidData, err := json.Marshal(uuid) if err != nil { - jww.ERROR.Printf( - "Could not JSON marshal UUID from ReceiveMessage: %+v", err) - return nil + return nil, errors.Errorf("failed to JSON marshal UUID : %+v", err) } - return uuidData + return uuidData, nil } // receiveReplyHandler is the handler for wasmModel.ReceiveReply. Returns // nil on error or the JSON marshalled UUID (uint64) on success. -func (m *manager) receiveReplyHandler(data []byte) []byte { +func (m *manager) receiveReplyHandler(data []byte) ([]byte, error) { var msg mChannels.ReceiveReplyMessage err := json.Unmarshal(data, &msg) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal ReceiveReplyMessage "+ - "from main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) } uuid := m.model.ReceiveReply(msg.ChannelID, msg.MessageID, msg.ReactionTo, @@ -226,22 +217,19 @@ func (m *manager) receiveReplyHandler(data []byte) []byte { uuidData, err := json.Marshal(uuid) if err != nil { - jww.ERROR.Printf( - "Could not JSON marshal UUID from ReceiveReply: %+v", err) - return nil + return nil, errors.Errorf("failed to JSON marshal UUID : %+v", err) } - return uuidData + return uuidData, nil } // receiveReactionHandler is the handler for wasmModel.ReceiveReaction. Returns // nil on error or the JSON marshalled UUID (uint64) on success. -func (m *manager) receiveReactionHandler(data []byte) []byte { +func (m *manager) receiveReactionHandler(data []byte) ([]byte, error) { var msg mChannels.ReceiveReplyMessage err := json.Unmarshal(data, &msg) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal ReceiveReplyMessage "+ - "from main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) } uuid := m.model.ReceiveReaction(msg.ChannelID, msg.MessageID, @@ -251,22 +239,19 @@ func (m *manager) receiveReactionHandler(data []byte) []byte { uuidData, err := json.Marshal(uuid) if err != nil { - jww.ERROR.Printf( - "Could not JSON marshal UUID from ReceiveReaction: %+v", err) - return nil + return nil, errors.Errorf("failed to JSON marshal UUID : %+v", err) } - return uuidData + return uuidData, nil } // updateFromUUIDHandler is the handler for wasmModel.UpdateFromUUID. Always // returns nil; meaning, no response is supplied (or expected). -func (m *manager) updateFromUUIDHandler(data []byte) []byte { +func (m *manager) updateFromUUIDHandler(data []byte) ([]byte, error) { var msg mChannels.MessageUpdateInfo err := json.Unmarshal(data, &msg) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal MessageUpdateInfo "+ - "from main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) } var messageID *message.ID var timestamp *time.Time @@ -294,18 +279,17 @@ func (m *manager) updateFromUUIDHandler(data []byte) []byte { m.model.UpdateFromUUID( msg.UUID, messageID, timestamp, round, pinned, hidden, status) - return nil + return nil, nil } // updateFromMessageIDHandler is the handler for wasmModel.UpdateFromMessageID. // Always returns nil; meaning, no response is supplied (or expected). -func (m *manager) updateFromMessageIDHandler(data []byte) []byte { +func (m *manager) updateFromMessageIDHandler(data []byte) ([]byte, error) { var msg mChannels.MessageUpdateInfo err := json.Unmarshal(data, &msg) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal MessageUpdateInfo "+ - "from main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) } var timestamp *time.Time var round *rounds.Round @@ -332,23 +316,21 @@ func (m *manager) updateFromMessageIDHandler(data []byte) []byte { uuidData, err := json.Marshal(uuid) if err != nil { - jww.ERROR.Printf( - "Could not JSON marshal UUID from UpdateFromMessageID: %+v", err) - return nil + return nil, errors.Errorf("failed to JSON marshal UUID : %+v", err) } - return uuidData + + return uuidData, nil } // getMessageHandler is the handler for wasmModel.GetMessage. Returns JSON // marshalled channels.GetMessageMessage. If an error occurs, then Error will // be set with the error message. Otherwise, Message will be set. Only one field // will be set. -func (m *manager) getMessageHandler(data []byte) []byte { +func (m *manager) getMessageHandler(data []byte) ([]byte, error) { messageID, err := message.UnmarshalID(data) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal message ID from main "+ - "thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", messageID, err) } reply := mChannels.GetMessageMessage{} @@ -362,27 +344,25 @@ func (m *manager) getMessageHandler(data []byte) []byte { messageData, err := json.Marshal(reply) if err != nil { - jww.ERROR.Printf("Could not JSON marshal GetMessageMessage for "+ - "GetMessage reply: %+v", err) - return nil + return nil, errors.Errorf("failed to JSON marshal %T from main thread "+ + "for GetMessage reply: %+v", reply, err) } - return messageData + return messageData, nil } // deleteMessageHandler is the handler for wasmModel.DeleteMessage. Always // returns nil; meaning, no response is supplied (or expected). -func (m *manager) deleteMessageHandler(data []byte) []byte { +func (m *manager) deleteMessageHandler(data []byte) ([]byte, error) { messageID, err := message.UnmarshalID(data) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal message ID from main "+ - "thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", messageID, err) } err = m.model.DeleteMessage(messageID) if err != nil { - return []byte(err.Error()) + return []byte(err.Error()), nil } - return nil + return nil, nil } diff --git a/indexedDb/channels/implementation_test.go b/indexedDb/channels/implementation_test.go index 39b49a4a..c11c014f 100644 --- a/indexedDb/channels/implementation_test.go +++ b/indexedDb/channels/implementation_test.go @@ -46,7 +46,7 @@ func dummyStoreEncryptionStatus(_ string, encryptionStatus bool) (bool, error) { // Happy path, insert message and look it up func TestWasmModel_msgIDLookup(t *testing.T) { cipher, err := cryptoChannel.NewCipher( - []byte("testpass"), []byte("testsalt"), 128, csprng.NewSystemRNG()) + []byte("testPass"), []byte("testSalt"), 128, csprng.NewSystemRNG()) if err != nil { t.Fatalf("Failed to create cipher") } @@ -134,7 +134,7 @@ func TestWasmModel_DeleteMessage(t *testing.T) { // Test wasmModel.UpdateSentStatus happy path and ensure fields don't change. func Test_wasmModel_UpdateSentStatus(t *testing.T) { cipher, err := cryptoChannel.NewCipher( - []byte("testpass"), []byte("testsalt"), 128, csprng.NewSystemRNG()) + []byte("testPass"), []byte("testSalt"), 128, csprng.NewSystemRNG()) if err != nil { t.Fatalf("Failed to create cipher") } @@ -205,7 +205,7 @@ func Test_wasmModel_UpdateSentStatus(t *testing.T) { // Smoke test wasmModel.JoinChannel/wasmModel.LeaveChannel happy paths. func Test_wasmModel_JoinChannel_LeaveChannel(t *testing.T) { cipher, err := cryptoChannel.NewCipher( - []byte("testpass"), []byte("testsalt"), 128, csprng.NewSystemRNG()) + []byte("testPass"), []byte("testSalt"), 128, csprng.NewSystemRNG()) if err != nil { t.Fatalf("Failed to create cipher") } @@ -258,7 +258,7 @@ func Test_wasmModel_JoinChannel_LeaveChannel(t *testing.T) { // Test UUID gets returned when different messages are added. func Test_wasmModel_UUIDTest(t *testing.T) { cipher, err := cryptoChannel.NewCipher( - []byte("testpass"), []byte("testsalt"), 128, csprng.NewSystemRNG()) + []byte("testPass"), []byte("testSalt"), 128, csprng.NewSystemRNG()) if err != nil { t.Fatalf("Failed to create cipher") } @@ -305,7 +305,7 @@ func Test_wasmModel_UUIDTest(t *testing.T) { // Tests if the same message ID being sent always returns the same UUID. func Test_wasmModel_DuplicateReceives(t *testing.T) { cipher, err := cryptoChannel.NewCipher( - []byte("testpass"), []byte("testsalt"), 128, csprng.NewSystemRNG()) + []byte("testPass"), []byte("testSalt"), 128, csprng.NewSystemRNG()) if err != nil { t.Fatalf("Failed to create cipher") } @@ -353,7 +353,7 @@ func Test_wasmModel_DuplicateReceives(t *testing.T) { // result is as expected. func Test_wasmModel_deleteMsgByChannel(t *testing.T) { cipher, err := cryptoChannel.NewCipher( - []byte("testpass"), []byte("testsalt"), 128, csprng.NewSystemRNG()) + []byte("testPass"), []byte("testSalt"), 128, csprng.NewSystemRNG()) if err != nil { t.Fatalf("Failed to create cipher") } @@ -426,7 +426,7 @@ func Test_wasmModel_deleteMsgByChannel(t *testing.T) { // Inserts will not fail, they simply will not happen. func TestWasmModel_receiveHelper_UniqueIndex(t *testing.T) { cipher, err := cryptoChannel.NewCipher( - []byte("testpass"), []byte("testsalt"), 128, csprng.NewSystemRNG()) + []byte("testPass"), []byte("testSalt"), 128, csprng.NewSystemRNG()) if err != nil { t.Fatalf("Failed to create cipher") } diff --git a/indexedDb/channels/init.go b/indexedDb/channels/init.go index c3366883..801d8613 100644 --- a/indexedDb/channels/init.go +++ b/indexedDb/channels/init.go @@ -192,9 +192,9 @@ func RegisterDatabaseNameStore(m *manager) { storeDatabaseNameResponseChan := make(chan []byte) // Register handler m.mh.RegisterHandler(indexedDbWorker.StoreDatabaseNameTag, - func(data []byte) []byte { + func(data []byte) ([]byte, error) { storeDatabaseNameResponseChan <- data - return nil + return nil, nil }) storeDatabaseName = func(databaseName string) error { diff --git a/indexedDb/channels/main.go b/indexedDb/channels/main.go index 2252d7eb..2f19a648 100644 --- a/indexedDb/channels/main.go +++ b/indexedDb/channels/main.go @@ -17,7 +17,7 @@ import ( func main() { fmt.Println("Starting xxDK WebAssembly Channels Database Worker.") - m := &manager{mh: indexedDb.NewMessageHandler()} + m := &manager{mh: indexedDb.NewMessageHandler("ChannelsIndexedDbWorker")} RegisterDatabaseNameStore(m) m.RegisterHandlers() m.mh.SignalReady() diff --git a/indexedDb/dm/handlers.go b/indexedDb/dm/handlers.go index b2a580ba..95ed73ed 100644 --- a/indexedDb/dm/handlers.go +++ b/indexedDb/dm/handlers.go @@ -18,7 +18,7 @@ import ( cryptoChannel "gitlab.com/elixxir/crypto/channel" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/xxdk-wasm/indexedDb" - "gitlab.com/elixxir/xxdk-wasm/indexedDbWorker" + worker "gitlab.com/elixxir/xxdk-wasm/indexedDbWorker" mChannels "gitlab.com/elixxir/xxdk-wasm/indexedDbWorker/channels" mDm "gitlab.com/elixxir/xxdk-wasm/indexedDbWorker/dm" "gitlab.com/xx_network/crypto/csprng" @@ -35,24 +35,22 @@ type manager struct { // RegisterHandlers registers all the reception handlers to manage messages from // the main thread for the channels.EventModel. func (m *manager) RegisterHandlers() { - - m.mh.RegisterHandler(indexedDbWorker.NewWASMEventModelTag, m.newWASMEventModelHandler) - m.mh.RegisterHandler(indexedDbWorker.ReceiveTag, m.receiveHandler) - m.mh.RegisterHandler(indexedDbWorker.ReceiveTextTag, m.receiveTextHandler) - m.mh.RegisterHandler(indexedDbWorker.ReceiveReplyTag, m.receiveReplyHandler) - m.mh.RegisterHandler(indexedDbWorker.ReceiveReactionTag, m.receiveReactionHandler) - m.mh.RegisterHandler(indexedDbWorker.UpdateSentStatusTag, m.updateSentStatusHandler) + m.mh.RegisterHandler(worker.NewWASMEventModelTag, m.newWASMEventModelHandler) + m.mh.RegisterHandler(worker.ReceiveTag, m.receiveHandler) + m.mh.RegisterHandler(worker.ReceiveTextTag, m.receiveTextHandler) + m.mh.RegisterHandler(worker.ReceiveReplyTag, m.receiveReplyHandler) + m.mh.RegisterHandler(worker.ReceiveReactionTag, m.receiveReactionHandler) + m.mh.RegisterHandler(worker.UpdateSentStatusTag, m.updateSentStatusHandler) } // newWASMEventModelHandler is the handler for NewWASMEventModel. Returns nil on // success or an error message on failure. -func (m *manager) newWASMEventModelHandler(data []byte) []byte { +func (m *manager) newWASMEventModelHandler(data []byte) ([]byte, error) { var msg mChannels.NewWASMEventModelMessage err := json.Unmarshal(data, &msg) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal NewWASMEventModelMessage "+ - "from NewWASMEventModel in main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) } // Create new encryption cipher @@ -60,17 +58,16 @@ func (m *manager) newWASMEventModelHandler(data []byte) []byte { encryption, err := cryptoChannel.NewCipherFromJSON( []byte(msg.EncryptionJSON), rng.GetStream()) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal channel cipher from "+ - "main thread: %+v", err) - return nil + return nil, errors.Errorf("failed to JSON unmarshal channel cipher "+ + "from main thread: %+v", err) } m.model, err = NewWASMEventModel(msg.Path, encryption, m.messageReceivedCallback, m.storeEncryptionStatus) if err != nil { - return []byte(err.Error()) + return []byte(err.Error()), nil } - return nil + return nil, nil } // messageReceivedCallback sends calls to the MessageReceivedCallback in the @@ -94,7 +91,7 @@ func (m *manager) messageReceivedCallback( // Send it to the main thread m.mh.SendResponse( - indexedDbWorker.GetMessageTag, indexedDbWorker.InitID, data) + worker.GetMessageTag, worker.InitID, data) } // storeEncryptionStatus augments the functionality of @@ -116,15 +113,15 @@ func (m *manager) storeEncryptionStatus( // Register response handler with channel that will wait for the response responseChan := make(chan []byte) - m.mh.RegisterHandler(indexedDbWorker.EncryptionStatusTag, - func(data []byte) []byte { + m.mh.RegisterHandler(worker.EncryptionStatusTag, + func(data []byte) ([]byte, error) { responseChan <- data - return nil + return nil, nil }) // Send encryption status to main thread m.mh.SendResponse( - indexedDbWorker.EncryptionStatusTag, indexedDbWorker.InitID, data) + worker.EncryptionStatusTag, worker.InitID, data) // Wait for response var response mChannels.EncryptionStatusReply @@ -133,10 +130,10 @@ func (m *manager) storeEncryptionStatus( if err = json.Unmarshal(responseData, &response); err != nil { return false, err } - case <-time.After(indexedDbWorker.ResponseTimeout): + case <-time.After(worker.ResponseTimeout): return false, errors.Errorf("timed out after %s waiting for "+ "response about the database encryption status from local "+ - "storage in the main thread", indexedDbWorker.ResponseTimeout) + "storage in the main thread", worker.ResponseTimeout) } // If the response contain an error, return it @@ -150,13 +147,12 @@ func (m *manager) storeEncryptionStatus( // receiveHandler is the handler for wasmModel.Receive. Returns nil on error or // the JSON marshalled UUID (uint64) on success. -func (m *manager) receiveHandler(data []byte) []byte { +func (m *manager) receiveHandler(data []byte) ([]byte, error) { var msg mDm.TransferMessage err := json.Unmarshal(data, &msg) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal dm.TransferMessage from "+ - "Receive in main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) } uuid := m.model.Receive( @@ -165,22 +161,19 @@ func (m *manager) receiveHandler(data []byte) []byte { uuidData, err := json.Marshal(uuid) if err != nil { - jww.ERROR.Printf( - "Could not JSON marshal UUID from Receive: %+v", err) - return nil + return nil, errors.Errorf("failed to JSON marshal UUID : %+v", err) } - return uuidData + return uuidData, nil } // receiveTextHandler is the handler for wasmModel.ReceiveText. Returns nil on // error or the JSON marshalled UUID (uint64) on success. -func (m *manager) receiveTextHandler(data []byte) []byte { +func (m *manager) receiveTextHandler(data []byte) ([]byte, error) { var msg mDm.TransferMessage err := json.Unmarshal(data, &msg) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal dm.TransferMessage from "+ - "ReceiveText in main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) } uuid := m.model.ReceiveText( @@ -189,22 +182,20 @@ func (m *manager) receiveTextHandler(data []byte) []byte { uuidData, err := json.Marshal(uuid) if err != nil { - jww.ERROR.Printf( - "Could not JSON marshal UUID from ReceiveText: %+v", err) - return nil + return nil, errors.Errorf("failed to JSON marshal UUID : %+v", err) } - return uuidData + + return uuidData, nil } // receiveReplyHandler is the handler for wasmModel.ReceiveReply. Returns nil on // error or the JSON marshalled UUID (uint64) on success. -func (m *manager) receiveReplyHandler(data []byte) []byte { +func (m *manager) receiveReplyHandler(data []byte) ([]byte, error) { var msg mDm.TransferMessage err := json.Unmarshal(data, &msg) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal dm.TransferMessage from "+ - "ReceiveReply in main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) } uuid := m.model.ReceiveReply(msg.MessageID, msg.ReactionTo, msg.Nickname, @@ -213,22 +204,20 @@ func (m *manager) receiveReplyHandler(data []byte) []byte { uuidData, err := json.Marshal(uuid) if err != nil { - jww.ERROR.Printf( - "Could not JSON marshal UUID from ReceiveReply: %+v", err) - return nil + return nil, errors.Errorf("failed to JSON marshal UUID : %+v", err) } - return uuidData + + return uuidData, nil } // receiveReactionHandler is the handler for wasmModel.ReceiveReaction. Returns // nil on error or the JSON marshalled UUID (uint64) on success. -func (m *manager) receiveReactionHandler(data []byte) []byte { +func (m *manager) receiveReactionHandler(data []byte) ([]byte, error) { var msg mDm.TransferMessage err := json.Unmarshal(data, &msg) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal dm.TransferMessage from "+ - "ReceiveReaction in main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) } uuid := m.model.ReceiveReaction(msg.MessageID, msg.ReactionTo, msg.Nickname, @@ -237,25 +226,24 @@ func (m *manager) receiveReactionHandler(data []byte) []byte { uuidData, err := json.Marshal(uuid) if err != nil { - jww.ERROR.Printf( - "Could not JSON marshal UUID from ReceiveReaction: %+v", err) - return nil + return nil, errors.Errorf("failed to JSON marshal UUID : %+v", err) } - return uuidData + + return uuidData, nil } // updateSentStatusHandler is the handler for wasmModel.UpdateSentStatus. Always // returns nil; meaning, no response is supplied (or expected). -func (m *manager) updateSentStatusHandler(data []byte) []byte { +func (m *manager) updateSentStatusHandler(data []byte) ([]byte, error) { var msg mDm.TransferMessage err := json.Unmarshal(data, &msg) if err != nil { - jww.ERROR.Printf("Could not JSON unmarshal dm.TransferMessage from "+ - "UpdateSentStatus in main thread: %+v", err) - return nil + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) } m.model.UpdateSentStatus( msg.UUID, msg.MessageID, msg.Timestamp, msg.Round, msg.Status) - return nil + + return nil, nil } diff --git a/indexedDb/dm/init.go b/indexedDb/dm/init.go index ceeb884e..c709b19b 100644 --- a/indexedDb/dm/init.go +++ b/indexedDb/dm/init.go @@ -193,9 +193,9 @@ func RegisterDatabaseNameStore(m *manager) { storeDatabaseNameResponseChan := make(chan []byte) // Register handler m.mh.RegisterHandler(indexedDbWorker.StoreDatabaseNameTag, - func(data []byte) []byte { + func(data []byte) ([]byte, error) { storeDatabaseNameResponseChan <- data - return nil + return nil, nil }) storeDatabaseName = func(databaseName string) error { diff --git a/indexedDb/dm/main.go b/indexedDb/dm/main.go index 30cd9514..71494d8f 100644 --- a/indexedDb/dm/main.go +++ b/indexedDb/dm/main.go @@ -17,7 +17,7 @@ import ( func main() { fmt.Println("Starting xxDK WebAssembly DM Database Worker.") - m := &manager{mh: indexedDb.NewMessageHandler()} + m := &manager{mh: indexedDb.NewMessageHandler("DmIndexedDbWorker")} m.RegisterHandlers() RegisterDatabaseNameStore(m) m.mh.SignalReady() diff --git a/indexedDb/messageHandler.go b/indexedDb/messageHandler.go index aa515ef2..1e200616 100644 --- a/indexedDb/messageHandler.go +++ b/indexedDb/messageHandler.go @@ -20,7 +20,7 @@ import ( ) // HandlerFn is the function that handles incoming data from the main thread. -type HandlerFn func(data []byte) []byte +type HandlerFn func(data []byte) ([]byte, error) // MessageHandler queues incoming messages from the main thread and handles them // based on their tag. @@ -32,14 +32,18 @@ type MessageHandler struct { // main thread keyed on the handler tag. handlers map[indexedDbWorker.Tag]HandlerFn + // name describes the worker. It is used for debugging and logging purposes. + name string + mux sync.Mutex } // NewMessageHandler initialises a new MessageHandler. -func NewMessageHandler() *MessageHandler { +func NewMessageHandler(name string) *MessageHandler { mh := &MessageHandler{ messages: make(chan js.Value, 100), handlers: make(map[indexedDbWorker.Tag]HandlerFn), + name: name, } mh.addEventListeners() @@ -57,43 +61,51 @@ func (mh *MessageHandler) SignalReady() { // SendResponse sends a reply to the main thread with the given tag and ID, func (mh *MessageHandler) SendResponse( tag indexedDbWorker.Tag, id uint64, data []byte) { - message := indexedDbWorker.WorkerMessage{ + msg := indexedDbWorker.WorkerMessage{ Tag: tag, ID: id, Data: data, } + jww.DEBUG.Printf("[WW] [%s] Worker sending message for %q and ID %d with "+ + "data: %s", mh.name, tag, id, data) - payload, err := json.Marshal(message) + payload, err := json.Marshal(msg) if err != nil { - jww.FATAL.Panicf("Failed to marshal payload with tag %q and ID %d "+ - "going to main thread: %+v", tag, id, err) + jww.FATAL.Panicf("[WW] [%s] Worker failed to marshal %T for %q and ID "+ + "%d going to main: %+v", mh.name, msg, tag, id, err) } - go postMessage(string(payload)) + go mh.postMessage(string(payload)) } // receiveMessage is registered with the Javascript event listener and is called // everytime a message from the main thread is received. If the registered // handler returns a response, it is sent to the main thread. func (mh *MessageHandler) receiveMessage(data []byte) error { - var message indexedDbWorker.WorkerMessage - err := json.Unmarshal(data, &message) + var msg indexedDbWorker.WorkerMessage + err := json.Unmarshal(data, &msg) if err != nil { return err } + jww.DEBUG.Printf("[WW] [%s] Worker received message for %q and ID %d with "+ + "data: %s", mh.name, msg.Tag, msg.ID, msg.Data) mh.mux.Lock() - handler, exists := mh.handlers[message.Tag] + handler, exists := mh.handlers[msg.Tag] mh.mux.Unlock() if !exists { - return errors.Errorf("no handler found for tag %q", message.Tag) + return errors.Errorf("no handler found for tag %q", msg.Tag) } // Call handler and register response with its return go func() { - response := handler(message.Data) + response, err2 := handler(msg.Data) + if err2 != nil { + jww.FATAL.Panicf("[WW] [%s] Handler for for %q and ID %d returned "+ + "an error: %+v", mh.name, msg.Tag, msg.ID, err) + } if response != nil { - mh.SendResponse(message.Tag, message.ID, response) + mh.SendResponse(msg.Tag, msg.ID, response) } }() @@ -105,6 +117,8 @@ func (mh *MessageHandler) receiveMessage(data []byte) error { // // If the handler returns anything but nil, it will be returned as a response. func (mh *MessageHandler) RegisterHandler(tag indexedDbWorker.Tag, handler HandlerFn) { + jww.DEBUG.Printf( + "[WW] [%s] Worker registering handler for tag %q", mh.name, tag) mh.mux.Lock() mh.handlers[tag] = handler mh.mux.Unlock() @@ -117,24 +131,27 @@ func (mh *MessageHandler) addEventListeners() { // Create a listener for when the message event is fire on the worker. This // occurs when a message is received from the main thread. // Doc: https://developer.mozilla.org/en-US/docs/Web/API/Worker/message_event - messageEvent := js.FuncOf(func(this js.Value, args []js.Value) any { + messageEvent := js.FuncOf(func(_ js.Value, args []js.Value) any { err := mh.receiveMessage([]byte(args[0].Get("data").String())) if err != nil { - jww.ERROR.Printf("Failed to receive message from main thread: %+v", err) + jww.ERROR.Printf("[WW] [%s] Failed to receive message from "+ + "main thread: %+v", mh.name, err) } return nil }) // Create listener for when a messageerror event is fired on the worker. - // This occurs when it receives a message that can't be deserialized. + // This occurs when it receives a message that cannot be deserialized. // Doc: https://developer.mozilla.org/en-US/docs/Web/API/Worker/messageerror_event - messageError := js.FuncOf(func(this js.Value, args []js.Value) any { + messageError := js.FuncOf(func(_ js.Value, args []js.Value) any { event := args[0] - jww.ERROR.Printf( - "Error receiving message from main thread: %s", utils.JsToJson(event)) + jww.ERROR.Printf("[WW] [%s] Worker received error message from main "+ + "thread: %s", mh.name, utils.JsToJson(event)) return nil }) + // Register each event listener on the worker using addEventListener + // Doc: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener js.Global().Call("addEventListener", "message", messageEvent) js.Global().Call("addEventListener", "messageerror", messageError) } @@ -146,7 +163,7 @@ func (mh *MessageHandler) addEventListeners() { // handled by the structured clone algorithm". See the doc for more information. // // Doc: https://developer.mozilla.org/docs/Web/API/DedicatedWorkerGlobalScope/postMessage -func postMessage(aMessage any) { +func (mh *MessageHandler) postMessage(aMessage any) { js.Global().Call("postMessage", aMessage) } @@ -160,6 +177,6 @@ func postMessage(aMessage any) { // transferList // // Doc: https://developer.mozilla.org/en-US/docs/Web/API/DedicatedWorkerGlobalScope/postMessage -func postMessageTransferList(aMessage, transferList any) { +func (mh *MessageHandler) postMessageTransferList(aMessage, transferList any) { js.Global().Call("postMessage", aMessage, transferList) } diff --git a/indexedDbWorker/channels/init.go b/indexedDbWorker/channels/init.go index ccc875c4..586ed8aa 100644 --- a/indexedDbWorker/channels/init.go +++ b/indexedDbWorker/channels/init.go @@ -23,7 +23,7 @@ import ( // WorkerJavascriptFileURL is the URL of the script the worker will execute to // launch the worker WASM binary. It must obey the same-origin policy. -const WorkerJavascriptFileURL = "/integrations/assets/dmIndexedDbWorker.js" +const WorkerJavascriptFileURL = "/integrations/assets/channelsIndexedDbWorker.js" // MessageReceivedCallback is called any time a message is received or updated. // @@ -77,12 +77,12 @@ func NewWASMEventModel(path string, encryption cryptoChannel.Cipher, return nil, err } - message := NewWASMEventModelMessage{ + msg := NewWASMEventModelMessage{ Path: path, EncryptionJSON: string(encryptionJSON), } - payload, err := json.Marshal(message) + payload, err := json.Marshal(msg) if err != nil { return nil, err } @@ -185,7 +185,6 @@ func storeDatabaseNameHandler( var returnData []byte // Get the database name and save it to storage - jww.ERROR.Printf("*** Storing database name: %s", string(data)) if err := storage.StoreIndexedDb(string(data)); err != nil { returnData = []byte(err.Error()) } diff --git a/indexedDbWorker/dm/init.go b/indexedDbWorker/dm/init.go index f38a036d..5e4044e9 100644 --- a/indexedDbWorker/dm/init.go +++ b/indexedDbWorker/dm/init.go @@ -24,7 +24,7 @@ import ( // WorkerJavascriptFileURL is the URL of the script the worker will execute to // launch the worker WASM binary. It must obey the same-origin policy. -const WorkerJavascriptFileURL = "/integrations/assets/indexedDbWorker.js" +const WorkerJavascriptFileURL = "/integrations/assets/dmIndexedDbWorker.js" // MessageReceivedCallback is called any time a message is received or updated. // @@ -68,12 +68,12 @@ func NewWASMEventModel(path string, encryption cryptoChannel.Cipher, return nil, err } - message := NewWASMEventModelMessage{ + msg := NewWASMEventModelMessage{ Path: path, EncryptionJSON: string(encryptionJSON), } - payload, err := json.Marshal(message) + payload, err := json.Marshal(msg) if err != nil { return nil, err } diff --git a/indexedDbWorker/worker.go b/indexedDbWorker/worker.go index 5f161856..98bcf656 100644 --- a/indexedDbWorker/worker.go +++ b/indexedDbWorker/worker.go @@ -58,6 +58,9 @@ type WorkerHandler struct { // idCount tracks the newest ID to assign to new handlers. idCount uint64 + // name describes the worker. It is used for debugging and logging purposes. + name string + mux sync.Mutex } @@ -79,6 +82,7 @@ func NewWorkerHandler(aURL, name string) (*WorkerHandler, error) { worker: js.Global().Get("Worker").New(aURL, opts), handlers: make(map[Tag]map[uint64]HandlerFn), idCount: InitID, + name: name, } // Register listeners on the Javascript worker object that receive messages @@ -112,20 +116,44 @@ func (wh *WorkerHandler) SendMessage( id = wh.RegisterHandler(tag, 0, true, receptionHandler) } - message := WorkerMessage{ + jww.DEBUG.Printf("[WW] [%s] Main sending message for %q and ID %d with "+ + "data: %s", wh.name, tag, id, data) + + msg := WorkerMessage{ Tag: tag, ID: id, Data: data, } - payload, err := json.Marshal(message) + payload, err := json.Marshal(msg) if err != nil { - jww.FATAL.Panicf( - "Failed to marshal payload for %q going to worker: %+v", tag, err) + jww.FATAL.Panicf("[WW] [%s] Main failed to marshal %T for %q and "+ + "ID %d going to worker: %+v", wh.name, msg, tag, id, err) } go wh.postMessage(string(payload)) } +// receiveMessage is registered with the Javascript event listener and is called +// every time a new message from the worker is received. +func (wh *WorkerHandler) receiveMessage(data []byte) error { + var msg WorkerMessage + err := json.Unmarshal(data, &msg) + if err != nil { + return err + } + jww.DEBUG.Printf("[WW] [%s] Main received message for %q and ID %d with "+ + "data: %s", wh.name, msg.Tag, msg.ID, msg.Data) + + handler, err := wh.getHandler(msg.Tag, msg.ID) + if err != nil { + return err + } + + go handler(msg.Data) + + return nil +} + // RegisterHandler registers the handler for the given tag and ID unless autoID // is true, in which case a unique ID is used. Returns the ID that was // registered. If a previous handler was registered, it is overwritten. @@ -141,6 +169,9 @@ func (wh *WorkerHandler) RegisterHandler( id = wh.getNextID() } + jww.DEBUG.Printf("[WW] [%s] Main registering handler for tag %q and ID %d "+ + "(autoID: %t)", wh.name, tag, id, autoID) + if _, exists := wh.handlers[tag]; !exists { wh.handlers[tag] = make(map[uint64]HandlerFn) } @@ -163,47 +194,31 @@ func (wh *WorkerHandler) addEventListeners() { // Create a listener for when the message event is fired on the worker. This // occurs when a message is received from the worker. // Doc: https://developer.mozilla.org/en-US/docs/Web/API/Worker/message_event - messageEvent := js.FuncOf(func(this js.Value, args []js.Value) any { + messageEvent := js.FuncOf(func(_ js.Value, args []js.Value) any { err := wh.receiveMessage([]byte(args[0].Get("data").String())) if err != nil { - jww.ERROR.Printf("Failed to receive message from worker: %+v", err) + jww.ERROR.Printf("[WW] [%s] Failed to receive message from "+ + "worker: %+v", wh.name, err) } return nil }) // Create listener for when a messageerror event is fired on the worker. - // This occurs when it receives a message that can't be deserialized. + // This occurs when it receives a message that cannot be deserialized. // Doc: https://developer.mozilla.org/en-US/docs/Web/API/Worker/messageerror_event - messageError := js.FuncOf(func(this js.Value, args []js.Value) any { + messageError := js.FuncOf(func(_ js.Value, args []js.Value) any { event := args[0] - jww.ERROR.Printf( - "Error receiving message from worker: %s", utils.JsToJson(event)) + jww.ERROR.Printf("[WW] [%s] Main received error message from worker: %s", + wh.name, utils.JsToJson(event)) return nil }) + // Register each event listener on the worker using addEventListener + // Doc: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener wh.worker.Call("addEventListener", "message", messageEvent) wh.worker.Call("addEventListener", "messageerror", messageError) } -// receiveMessage is registered with the Javascript event listener and is called -// every time a new message from the worker is received. -func (wh *WorkerHandler) receiveMessage(data []byte) error { - var message WorkerMessage - err := json.Unmarshal(data, &message) - if err != nil { - return err - } - - handler, err := wh.getHandler(message.Tag, message.ID) - if err != nil { - return err - } - - go handler(message.Data) - - return nil -} - // getHandler returns the handler with the given ID or returns an error if no // handler is found. The handler is deleted from the map if specified in // deleteAfterReceiving. This function is thread safe. @@ -244,8 +259,8 @@ func (wh *WorkerHandler) getHandler(tag Tag, id uint64) (HandlerFn, error) { // js.Undefined can be passed explicitly. // // Doc: https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage -func (wh *WorkerHandler) postMessage(message any) { - wh.worker.Call("postMessage", message) +func (wh *WorkerHandler) postMessage(msg any) { + wh.worker.Call("postMessage", msg) } // postMessageTransferList sends an array of Transferable objects to transfer to @@ -258,8 +273,8 @@ func (wh *WorkerHandler) postMessage(message any) { // transferList // // Doc: https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage#transfer -func (wh *WorkerHandler) postMessageTransferList(message, transferList any) { - wh.worker.Call("postMessage", message, transferList) +func (wh *WorkerHandler) postMessageTransferList(msg, transferList any) { + wh.worker.Call("postMessage", msg, transferList) } // newWorkerOptions creates a new Javascript object containing optional -- GitLab