From 4ad84bdcf974a4497ac208a0298f82400302416f Mon Sep 17 00:00:00 2001 From: "Richard T. Carback III" <rick.carback@gmail.com> Date: Wed, 28 Sep 2022 17:13:40 +0000 Subject: [PATCH] Callback interface implementation, fix to UpdateSentStatus race condition, Wasm -> WASM, and update client dependency --- go.mod | 2 +- go.sum | 2 ++ indexedDb/implementation.go | 17 +++++++++++++- indexedDb/implementation_test.go | 8 ++++--- indexedDb/init.go | 40 +++++++++++++++++++++++--------- 5 files changed, 53 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 1ebdbb75..8476dd2d 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hack-pad/go-indexeddb v0.2.0 github.com/pkg/errors v0.9.1 github.com/spf13/jwalterweatherman v1.1.0 - gitlab.com/elixxir/client v1.5.1-0.20220925005456-24eb354b1d6f + gitlab.com/elixxir/client v1.5.1-0.20220928170652-fe87f3ae67b4 gitlab.com/elixxir/crypto v0.0.7-0.20220923233816-0364f1b203c6 gitlab.com/elixxir/primitives v0.0.3-0.20220901220638-1acc75fabdc6 gitlab.com/xx_network/primitives v0.0.4-0.20220809193445-9fc0a5209548 diff --git a/go.sum b/go.sum index ec84476e..debddfda 100644 --- a/go.sum +++ b/go.sum @@ -634,6 +634,8 @@ gitlab.com/elixxir/client v1.5.1-0.20220925004736-f9acd4f64d77 h1:wjyV+vXxAAapD8 gitlab.com/elixxir/client v1.5.1-0.20220925004736-f9acd4f64d77/go.mod h1:z1Bdlja75CF3UrzifMC0LQwjlEdOcJCfXEX5k9AKQTQ= gitlab.com/elixxir/client v1.5.1-0.20220925005456-24eb354b1d6f h1:m0jwFnBatQH/3uIhSwO0le06ky80LLuzqKD+Xd4nwXk= gitlab.com/elixxir/client v1.5.1-0.20220925005456-24eb354b1d6f/go.mod h1:z1Bdlja75CF3UrzifMC0LQwjlEdOcJCfXEX5k9AKQTQ= +gitlab.com/elixxir/client v1.5.1-0.20220928170652-fe87f3ae67b4 h1:WgpR5CjPDXSRF5lpRhyyexmNsMQq9xiwMJd3HeDOb68= +gitlab.com/elixxir/client v1.5.1-0.20220928170652-fe87f3ae67b4/go.mod h1:z1Bdlja75CF3UrzifMC0LQwjlEdOcJCfXEX5k9AKQTQ= gitlab.com/elixxir/comms v0.0.4-0.20220916185715-f1e9a5eda939 h1:+VRx2ULHKs040bBhDAOKNCZnbcXxUk3jD9JoKQzQpLk= gitlab.com/elixxir/comms v0.0.4-0.20220916185715-f1e9a5eda939/go.mod h1:AO6XkMhaHJW8eXlgL5m3UUcJqsSP8F5Wm1GX+wyq/rw= gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c= diff --git a/indexedDb/implementation.go b/indexedDb/implementation.go index 2614d6c3..d6e10517 100644 --- a/indexedDb/implementation.go +++ b/indexedDb/implementation.go @@ -12,6 +12,7 @@ package indexedDb import ( "context" "encoding/json" + "sync" "syscall/js" "time" @@ -35,7 +36,9 @@ const dbTimeout = time.Second // system passed an object that adheres to in order to get events on the // channel. type wasmModel struct { - db *idb.Database + db *idb.Database + receivedMessageCB MessageReceivedCallback + updateMux sync.Mutex } // newContext builds a context for database operations. @@ -157,6 +160,7 @@ func (w *wasmModel) ReceiveMessage(channelID *id.ID, if err != nil { jww.ERROR.Printf("%+v", errors.Wrap(parentErr, err.Error())) } + go w.receivedMessageCB(uuid, channelID) return uuid } @@ -179,6 +183,7 @@ func (w *wasmModel) ReceiveReply(channelID *id.ID, if err != nil { jww.ERROR.Printf("%+v", errors.Wrap(parentErr, err.Error())) } + go w.receivedMessageCB(uuid, channelID) return uuid } @@ -200,6 +205,7 @@ func (w *wasmModel) ReceiveReaction(channelID *id.ID, messageID cryptoChannel.Me if err != nil { jww.ERROR.Printf("%+v", errors.Wrap(parentErr, err.Error())) } + go w.receivedMessageCB(uuid, channelID) return uuid } @@ -210,6 +216,12 @@ func (w *wasmModel) UpdateSentStatus(uuid uint64, messageID cryptoChannel.Messag timestamp time.Time, round rounds.Round, status channels.SentStatus) { parentErr := errors.New("failed to UpdateSentStatus") + // FIXME: this is a bit of race condition without the mux. + // This should be done via the transactions (i.e., make a + // special version of receiveHelper) + w.updateMux.Lock() + defer w.updateMux.Unlock() + // Convert messageID to the key generated by json.Marshal key := js.ValueOf(uuid) @@ -232,6 +244,9 @@ func (w *wasmModel) UpdateSentStatus(uuid uint64, messageID cryptoChannel.Messag if err != nil { jww.ERROR.Printf("%+v", errors.Wrap(parentErr, err.Error())) } + channelID := &id.ID{} + copy(channelID[:], newMessage.ChannelID) + go w.receivedMessageCB(uuid, channelID) } // buildMessage is a private helper that converts typical [channels.EventModel] diff --git a/indexedDb/implementation_test.go b/indexedDb/implementation_test.go index e6479da1..5b47174f 100644 --- a/indexedDb/implementation_test.go +++ b/indexedDb/implementation_test.go @@ -29,11 +29,13 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) } +func dummyCallback(uuid uint64, channelID *id.ID) {} + // Test wasmModel.UpdateSentStatus happy path and ensure fields don't change. func TestWasmModel_UpdateSentStatus(t *testing.T) { testString := "test" testMsgId := channel.MakeMessageID([]byte(testString)) - eventModel, err := newWasmModel(testString) + eventModel, err := newWASMModel(testString, dummyCallback) if err != nil { t.Fatalf("%+v", err) } @@ -88,7 +90,7 @@ func TestWasmModel_UpdateSentStatus(t *testing.T) { // Smoke test wasmModel.JoinChannel/wasmModel.LeaveChannel happy paths. func TestWasmModel_JoinChannel_LeaveChannel(t *testing.T) { - eventModel, err := newWasmModel("test") + eventModel, err := newWASMModel("test", dummyCallback) if err != nil { t.Fatalf("%+v", err) } @@ -128,7 +130,7 @@ func TestWasmModel_JoinChannel_LeaveChannel(t *testing.T) { func TestWasmModel_UUIDTest(t *testing.T) { testString := "testHello" testMsgId := channel.MakeMessageID([]byte(testString)) - eventModel, err := newWasmModel(testString) + eventModel, err := newWASMModel(testString, dummyCallback) if err != nil { t.Fatalf("%+v", err) } diff --git a/indexedDb/init.go b/indexedDb/init.go index 20c8313c..af98dec2 100644 --- a/indexedDb/init.go +++ b/indexedDb/init.go @@ -17,26 +17,44 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/channels" + "gitlab.com/xx_network/primitives/id" ) const ( - // databaseSuffix is the suffix to be appended to the name of the database. - databaseSuffix = "_messenger" + // databaseSuffix is the suffix to be appended to the name of + // the database. + databaseSuffix = "_speakeasy" - // currentVersion is the current version of the IndexDb runtime. Used for - // migration purposes. + // currentVersion is the current version of the IndexDb + // runtime. Used for migration purposes. currentVersion uint = 1 ) -// NewWasmEventModel returns a [channels.EventModel] backed by a wasmModel. +// MessageReceivedCallback is called any time a message is received or updated +type MessageReceivedCallback func(uuid uint64, channelID *id.ID) + +// NewWASMEventModelBuilder returns an EventModelBuilder which allows +// the channel manager to define the path but the callback is the same +// across the board. +func NewWASMEventModelBuilder( + cb MessageReceivedCallback) channels.EventModelBuilder { + fn := func(path string) (channels.EventModel, error) { + return NewWASMEventModel(path, cb) + } + return fn +} + +// NewWASMEventModel returns a [channels.EventModel] backed by a wasmModel. // The name should be a base64 encoding of the users public key. -func NewWasmEventModel(pubkeyBase64 string) (channels.EventModel, error) { - databaseName := pubkeyBase64 + databaseSuffix - return newWasmModel(databaseName) +func NewWASMEventModel(path string, cb MessageReceivedCallback) ( + channels.EventModel, error) { + databaseName := path + databaseSuffix + return newWASMModel(databaseName, cb) } -// newWasmModel creates the given [idb.Database] and returns a wasmModel. -func newWasmModel(databaseName string) (*wasmModel, error) { +// newWASMModel creates the given [idb.Database] and returns a wasmModel. +func newWASMModel(databaseName string, cb MessageReceivedCallback) ( + *wasmModel, error) { // Attempt to open database object ctx, cancel := newContext() defer cancel() @@ -61,7 +79,7 @@ func newWasmModel(databaseName string) (*wasmModel, error) { // Wait for database open to finish db, err := openRequest.Await(ctx) - return &wasmModel{db: db}, err + return &wasmModel{db: db, receivedMessageCB: cb}, err } // v1Upgrade performs the v0 -> v1 database upgrade. -- GitLab