Skip to content
Snippets Groups Projects
Commit 11cf8728 authored by Jake Taylor's avatar Jake Taylor :lips:
Browse files

Merge branch 'hotfix/RefactorIndexedDb' into 'release'

refactor indexedDb to be more receptive to upcoming project changes

See merge request !41
parents 86e3f7d2 ef181d7c
No related branches found
No related tags found
2 merge requests!60Revert "Fail a test to be sure it works",!41refactor indexedDb to be more receptive to upcoming project changes
...@@ -7,13 +7,13 @@ ...@@ -7,13 +7,13 @@
//go:build js && wasm //go:build js && wasm
package indexedDb package channels
import ( import (
"context"
"crypto/ed25519" "crypto/ed25519"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"gitlab.com/elixxir/xxdk-wasm/indexedDb"
"sync" "sync"
"syscall/js" "syscall/js"
"time" "time"
...@@ -30,10 +30,6 @@ import ( ...@@ -30,10 +30,6 @@ import (
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
) )
// dbTimeout is the global timeout for operations with the storage
// [context.Context].
const dbTimeout = time.Second
// wasmModel implements [channels.EventModel] interface, which uses the channels // wasmModel implements [channels.EventModel] interface, which uses the channels
// system passed an object that adheres to in order to get events on the // system passed an object that adheres to in order to get events on the
// channel. // channel.
...@@ -44,11 +40,6 @@ type wasmModel struct { ...@@ -44,11 +40,6 @@ type wasmModel struct {
updateMux sync.Mutex updateMux sync.Mutex
} }
// newContext builds a context for database operations.
func newContext() (context.Context, context.CancelFunc) {
return context.WithTimeout(context.Background(), dbTimeout)
}
// JoinChannel is called whenever a channel is joined locally. // JoinChannel is called whenever a channel is joined locally.
func (w *wasmModel) JoinChannel(channel *cryptoBroadcast.Channel) { func (w *wasmModel) JoinChannel(channel *cryptoBroadcast.Channel) {
parentErr := errors.New("failed to JoinChannel") parentErr := errors.New("failed to JoinChannel")
...@@ -74,38 +65,11 @@ func (w *wasmModel) JoinChannel(channel *cryptoBroadcast.Channel) { ...@@ -74,38 +65,11 @@ func (w *wasmModel) JoinChannel(channel *cryptoBroadcast.Channel) {
return return
} }
// Prepare the Transaction _, err = indexedDb.Put(w.db, channelsStoreName, channelObj)
txn, err := w.db.Transaction(idb.TransactionReadWrite, channelsStoreName)
if err != nil { if err != nil {
jww.ERROR.Printf("%+v", errors.WithMessagef(parentErr, jww.ERROR.Printf("%+v", errors.WithMessagef(parentErr,
"Unable to create Transaction: %+v", err)) "Unable to put Channel: %+v", err))
return
}
store, err := txn.ObjectStore(channelsStoreName)
if err != nil {
jww.ERROR.Printf("%+v", errors.WithMessagef(parentErr,
"Unable to get ObjectStore: %+v", err))
return
} }
// Perform the operation
_, err = store.Put(channelObj)
if err != nil {
jww.ERROR.Printf("%+v", errors.WithMessagef(parentErr,
"Unable to Add Channel: %+v", err))
return
}
// Wait for the operation to return
ctx, cancel := newContext()
err = txn.Await(ctx)
cancel()
if err != nil {
jww.ERROR.Printf("%+v", errors.WithMessagef(parentErr,
"Adding Channel failed: %+v", err))
return
}
jww.DEBUG.Printf("Successfully added channel: %s", channel.ReceptionID)
} }
// LeaveChannel is called whenever a channel is left locally. // LeaveChannel is called whenever a channel is left locally.
...@@ -135,7 +99,7 @@ func (w *wasmModel) LeaveChannel(channelID *id.ID) { ...@@ -135,7 +99,7 @@ func (w *wasmModel) LeaveChannel(channelID *id.ID) {
} }
// Wait for the operation to return // Wait for the operation to return
ctx, cancel := newContext() ctx, cancel := indexedDb.NewContext()
err = txn.Await(ctx) err = txn.Await(ctx)
cancel() cancel()
if err != nil { if err != nil {
...@@ -183,7 +147,7 @@ func (w *wasmModel) deleteMsgByChannel(channelID *id.ID) error { ...@@ -183,7 +147,7 @@ func (w *wasmModel) deleteMsgByChannel(channelID *id.ID) error {
if err != nil { if err != nil {
return errors.WithMessagef(parentErr, "Unable to open Cursor: %+v", err) return errors.WithMessagef(parentErr, "Unable to open Cursor: %+v", err)
} }
ctx, cancel := newContext() ctx, cancel := indexedDb.NewContext()
err = cursorRequest.Iter(ctx, err = cursorRequest.Iter(ctx,
func(cursor *idb.CursorWithValue) error { func(cursor *idb.CursorWithValue) error {
_, err := cursor.Delete() _, err := cursor.Delete()
...@@ -255,8 +219,8 @@ func (w *wasmModel) ReceiveReply(channelID *id.ID, ...@@ -255,8 +219,8 @@ func (w *wasmModel) ReceiveReply(channelID *id.ID,
} }
msgToInsert := buildMessage(channelID.Marshal(), messageID.Bytes(), msgToInsert := buildMessage(channelID.Marshal(), messageID.Bytes(),
replyTo.Bytes(), nickname, textBytes, pubKey, codeset, timestamp, lease, replyTo.Bytes(), nickname, textBytes, pubKey, codeset,
round.ID, mType, status) timestamp, lease, round.ID, mType, status)
uuid, err := w.receiveHelper(msgToInsert, false) uuid, err := w.receiveHelper(msgToInsert, false)
...@@ -322,7 +286,7 @@ func (w *wasmModel) UpdateSentStatus(uuid uint64, ...@@ -322,7 +286,7 @@ func (w *wasmModel) UpdateSentStatus(uuid uint64,
key := js.ValueOf(uuid) key := js.ValueOf(uuid)
// Use the key to get the existing Message // Use the key to get the existing Message
currentMsg, err := w.get(messageStoreName, key) currentMsg, err := indexedDb.Get(w.db, messageStoreName, key)
if err != nil { if err != nil {
return return
} }
...@@ -404,33 +368,14 @@ func (w *wasmModel) receiveHelper(newMessage *Message, isUpdate bool) (uint64, ...@@ -404,33 +368,14 @@ func (w *wasmModel) receiveHelper(newMessage *Message, isUpdate bool) (uint64,
messageObj.Delete("id") messageObj.Delete("id")
} }
// Prepare the Transaction // Store message to database
txn, err := w.db.Transaction(idb.TransactionReadWrite, messageStoreName) addReq, err := indexedDb.Put(w.db, messageStoreName, messageObj)
if err != nil {
return 0, errors.Errorf("Unable to create Transaction: %+v",
err)
}
store, err := txn.ObjectStore(messageStoreName)
if err != nil {
return 0, errors.Errorf("Unable to get ObjectStore: %+v", err)
}
// Perform the upsert (put) operation
addReq, err := store.Put(messageObj)
if err != nil {
return 0, errors.Errorf("Unable to upsert Message: %+v", err)
}
// Wait for the operation to return
ctx, cancel := newContext()
err = txn.Await(ctx)
cancel()
if err != nil { if err != nil {
return 0, errors.Errorf("Upserting Message failed: %+v", err) return 0, errors.Errorf("Unable to put Message: %+v", err)
} }
res, err := addReq.Result() res, err := addReq.Result()
if err != nil { if err != nil {
return 0, errors.Errorf("Getting result from request failed: %+v", err) return 0, errors.Errorf("Unable to get Message result: %+v", err)
} }
// NOTE: Sometimes the insert fails to return an error but hits a duplicate // NOTE: Sometimes the insert fails to return an error but hits a duplicate
...@@ -450,135 +395,19 @@ func (w *wasmModel) receiveHelper(newMessage *Message, isUpdate bool) (uint64, ...@@ -450,135 +395,19 @@ func (w *wasmModel) receiveHelper(newMessage *Message, isUpdate bool) (uint64,
return uuid, nil return uuid, nil
} }
// get is a generic private helper for getting values from the given // msgIDLookup gets the UUID of the Message with the given messageID.
// [idb.ObjectStore].
func (w *wasmModel) get(objectStoreName string, key js.Value) (string, error) {
parentErr := errors.Errorf("failed to get %s/%s", objectStoreName, key)
// Prepare the Transaction
txn, err := w.db.Transaction(idb.TransactionReadOnly, objectStoreName)
if err != nil {
return "", errors.WithMessagef(parentErr,
"Unable to create Transaction: %+v", err)
}
store, err := txn.ObjectStore(objectStoreName)
if err != nil {
return "", errors.WithMessagef(parentErr,
"Unable to get ObjectStore: %+v", err)
}
// Perform the operation
getRequest, err := store.Get(key)
if err != nil {
return "", errors.WithMessagef(parentErr,
"Unable to Get from ObjectStore: %+v", err)
}
// Wait for the operation to return
ctx, cancel := newContext()
resultObj, err := getRequest.Await(ctx)
cancel()
if err != nil {
return "", errors.WithMessagef(parentErr,
"Unable to get from ObjectStore: %+v", err)
}
// Process result into string
resultStr := utils.JsToJson(resultObj)
jww.DEBUG.Printf("Got from %s/%s: %s", objectStoreName, key, resultStr)
return resultStr, nil
}
func (w *wasmModel) msgIDLookup(messageID cryptoChannel.MessageID) (uint64, func (w *wasmModel) msgIDLookup(messageID cryptoChannel.MessageID) (uint64,
error) { error) {
parentErr := errors.Errorf("failed to get %s/%s", messageStoreName, msgIDStr := js.ValueOf(base64.StdEncoding.EncodeToString(messageID.Bytes()))
messageID) resultObj, err := indexedDb.GetIndex(w.db, messageStoreName,
messageStoreMessageIndex, msgIDStr)
// Prepare the Transaction
txn, err := w.db.Transaction(idb.TransactionReadOnly, messageStoreName)
if err != nil {
return 0, errors.WithMessagef(parentErr,
"Unable to create Transaction: %+v", err)
}
store, err := txn.ObjectStore(messageStoreName)
if err != nil {
return 0, errors.WithMessagef(parentErr,
"Unable to get ObjectStore: %+v", err)
}
idx, err := store.Index(messageStoreMessageIndex)
if err != nil {
return 0, errors.WithMessagef(parentErr,
"Unable to get index: %+v", err)
}
msgIDStr := base64.StdEncoding.EncodeToString(messageID.Bytes())
keyReq, err := idx.Get(js.ValueOf(msgIDStr))
if err != nil {
return 0, errors.WithMessagef(parentErr,
"Unable to get keyReq: %+v", err)
}
// Wait for the operation to return
ctx, cancel := newContext()
keyObj, err := keyReq.Await(ctx)
cancel()
if err != nil { if err != nil {
return 0, errors.WithMessagef(parentErr, return 0, err
"Unable to get from ObjectStore: %+v", err)
} }
// Process result into string
resultStr := utils.JsToJson(keyObj)
jww.DEBUG.Printf("Index lookup of %s/%s/%s: %s", messageStoreName,
messageStoreMessageIndex, msgIDStr, resultStr)
uuid := uint64(0) uuid := uint64(0)
if !keyObj.IsUndefined() { if !resultObj.IsUndefined() {
uuid = uint64(keyObj.Get("id").Int()) uuid = uint64(resultObj.Get("id").Int())
} }
return uuid, nil return uuid, nil
} }
// dump returns the given [idb.ObjectStore] contents to string slice for
// debugging purposes.
func (w *wasmModel) dump(objectStoreName string) ([]string, error) {
parentErr := errors.Errorf("failed to dump %s", objectStoreName)
txn, err := w.db.Transaction(idb.TransactionReadOnly, objectStoreName)
if err != nil {
return nil, errors.WithMessagef(parentErr,
"Unable to create Transaction: %+v", err)
}
store, err := txn.ObjectStore(objectStoreName)
if err != nil {
return nil, errors.WithMessagef(parentErr,
"Unable to get ObjectStore: %+v", err)
}
cursorRequest, err := store.OpenCursor(idb.CursorNext)
if err != nil {
return nil, errors.WithMessagef(parentErr,
"Unable to open Cursor: %+v", err)
}
// Run the query
jww.DEBUG.Printf("%s values:", objectStoreName)
results := make([]string, 0)
ctx, cancel := newContext()
err = cursorRequest.Iter(ctx,
func(cursor *idb.CursorWithValue) error {
value, err := cursor.Value()
if err != nil {
return err
}
valueStr := utils.JsToJson(value)
results = append(results, valueStr)
jww.DEBUG.Printf("- %v", valueStr)
return nil
})
cancel()
if err != nil {
return nil, errors.WithMessagef(parentErr,
"Unable to dump ObjectStore: %+v", err)
}
return results, nil
}
...@@ -7,12 +7,13 @@ ...@@ -7,12 +7,13 @@
//go:build js && wasm //go:build js && wasm
package indexedDb package channels
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/hack-pad/go-indexeddb/idb" "github.com/hack-pad/go-indexeddb/idb"
"gitlab.com/elixxir/xxdk-wasm/indexedDb"
"gitlab.com/elixxir/xxdk-wasm/storage" "gitlab.com/elixxir/xxdk-wasm/storage"
"gitlab.com/xx_network/primitives/netTime" "gitlab.com/xx_network/primitives/netTime"
"os" "os"
...@@ -54,7 +55,7 @@ func Test_wasmModel_UpdateSentStatus(t *testing.T) { ...@@ -54,7 +55,7 @@ func Test_wasmModel_UpdateSentStatus(t *testing.T) {
} }
// Ensure one message is stored // Ensure one message is stored
results, err := eventModel.dump(messageStoreName) results, err := indexedDb.Dump(eventModel.db, messageStoreName)
if err != nil { if err != nil {
t.Fatalf("%+v", err) t.Fatalf("%+v", err)
} }
...@@ -68,7 +69,7 @@ func Test_wasmModel_UpdateSentStatus(t *testing.T) { ...@@ -68,7 +69,7 @@ func Test_wasmModel_UpdateSentStatus(t *testing.T) {
rounds.Round{ID: 8675309}, expectedStatus) rounds.Round{ID: 8675309}, expectedStatus)
// Check the resulting status // Check the resulting status
results, err = eventModel.dump(messageStoreName) results, err = indexedDb.Dump(eventModel.db, messageStoreName)
if err != nil { if err != nil {
t.Fatalf("%+v", err) t.Fatalf("%+v", err)
} }
...@@ -112,7 +113,7 @@ func Test_wasmModel_JoinChannel_LeaveChannel(t *testing.T) { ...@@ -112,7 +113,7 @@ func Test_wasmModel_JoinChannel_LeaveChannel(t *testing.T) {
} }
eventModel.JoinChannel(testChannel) eventModel.JoinChannel(testChannel)
eventModel.JoinChannel(testChannel2) eventModel.JoinChannel(testChannel2)
results, err := eventModel.dump(channelsStoreName) results, err := indexedDb.Dump(eventModel.db, channelsStoreName)
if err != nil { if err != nil {
t.Fatalf("%+v", err) t.Fatalf("%+v", err)
} }
...@@ -120,7 +121,7 @@ func Test_wasmModel_JoinChannel_LeaveChannel(t *testing.T) { ...@@ -120,7 +121,7 @@ func Test_wasmModel_JoinChannel_LeaveChannel(t *testing.T) {
t.Fatalf("Expected 2 channels to exist") t.Fatalf("Expected 2 channels to exist")
} }
eventModel.LeaveChannel(testChannel.ReceptionID) eventModel.LeaveChannel(testChannel.ReceptionID)
results, err = eventModel.dump(channelsStoreName) results, err = indexedDb.Dump(eventModel.db, channelsStoreName)
if err != nil { if err != nil {
t.Fatalf("%+v", err) t.Fatalf("%+v", err)
} }
...@@ -151,8 +152,6 @@ func Test_wasmModel_UUIDTest(t *testing.T) { ...@@ -151,8 +152,6 @@ func Test_wasmModel_UUIDTest(t *testing.T) {
uuids[i] = uuid uuids[i] = uuid
} }
_, _ = eventModel.dump(messageStoreName)
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
for j := i + 1; j < 10; j++ { for j := i + 1; j < 10; j++ {
if uuids[i] == uuids[j] { if uuids[i] == uuids[j] {
...@@ -186,8 +185,6 @@ func Test_wasmModel_DuplicateReceives(t *testing.T) { ...@@ -186,8 +185,6 @@ func Test_wasmModel_DuplicateReceives(t *testing.T) {
uuids[i] = uuid uuids[i] = uuid
} }
_, _ = eventModel.dump(messageStoreName)
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
for j := i + 1; j < 10; j++ { for j := i + 1; j < 10; j++ {
if uuids[i] != uuids[j] { if uuids[i] != uuids[j] {
...@@ -230,7 +227,7 @@ func Test_wasmModel_deleteMsgByChannel(t *testing.T) { ...@@ -230,7 +227,7 @@ func Test_wasmModel_deleteMsgByChannel(t *testing.T) {
} }
// Check pre-results // Check pre-results
result, err := eventModel.dump(messageStoreName) result, err := indexedDb.Dump(eventModel.db, messageStoreName)
if err != nil { if err != nil {
t.Fatalf("%+v", err) t.Fatalf("%+v", err)
} }
...@@ -245,7 +242,7 @@ func Test_wasmModel_deleteMsgByChannel(t *testing.T) { ...@@ -245,7 +242,7 @@ func Test_wasmModel_deleteMsgByChannel(t *testing.T) {
} }
// Check final results // Check final results
result, err = eventModel.dump(messageStoreName) result, err = indexedDb.Dump(eventModel.db, messageStoreName)
if err != nil { if err != nil {
t.Fatalf("%+v", err) t.Fatalf("%+v", err)
} }
...@@ -298,7 +295,7 @@ func TestWasmModel_receiveHelper_UniqueIndex(t *testing.T) { ...@@ -298,7 +295,7 @@ func TestWasmModel_receiveHelper_UniqueIndex(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("%+v", err) t.Fatalf("%+v", err)
} }
results, err := eventModel.dump(messageStoreName) results, err := indexedDb.Dump(eventModel.db, messageStoreName)
if err != nil { if err != nil {
t.Fatalf("%+v", err) t.Fatalf("%+v", err)
} }
...@@ -327,7 +324,7 @@ func TestWasmModel_receiveHelper_UniqueIndex(t *testing.T) { ...@@ -327,7 +324,7 @@ func TestWasmModel_receiveHelper_UniqueIndex(t *testing.T) {
// The update to duplicate message ID won't fail, // The update to duplicate message ID won't fail,
// but it just silently shouldn't happen // but it just silently shouldn't happen
results, err = eventModel.dump(messageStoreName) results, err = indexedDb.Dump(eventModel.db, messageStoreName)
if err != nil { if err != nil {
t.Fatalf("%+v", err) t.Fatalf("%+v", err)
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
//go:build js && wasm //go:build js && wasm
package indexedDb package channels
import ( import (
"github.com/hack-pad/go-indexeddb/idb" "github.com/hack-pad/go-indexeddb/idb"
...@@ -15,6 +15,7 @@ import ( ...@@ -15,6 +15,7 @@ import (
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/v4/channels" "gitlab.com/elixxir/client/v4/channels"
cryptoChannel "gitlab.com/elixxir/crypto/channel" cryptoChannel "gitlab.com/elixxir/crypto/channel"
"gitlab.com/elixxir/xxdk-wasm/indexedDb"
"gitlab.com/elixxir/xxdk-wasm/storage" "gitlab.com/elixxir/xxdk-wasm/storage"
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
"syscall/js" "syscall/js"
...@@ -58,7 +59,7 @@ func NewWASMEventModel(path string, encryption cryptoChannel.Cipher, ...@@ -58,7 +59,7 @@ func NewWASMEventModel(path string, encryption cryptoChannel.Cipher,
func newWASMModel(databaseName string, encryption cryptoChannel.Cipher, func newWASMModel(databaseName string, encryption cryptoChannel.Cipher,
cb MessageReceivedCallback) (*wasmModel, error) { cb MessageReceivedCallback) (*wasmModel, error) {
// Attempt to open database object // Attempt to open database object
ctx, cancel := newContext() ctx, cancel := indexedDb.NewContext()
defer cancel() defer cancel()
openRequest, err := idb.Global().Open(ctx, databaseName, currentVersion, openRequest, err := idb.Global().Open(ctx, databaseName, currentVersion,
func(db *idb.Database, oldVersion, newVersion uint) error { func(db *idb.Database, oldVersion, newVersion uint) error {
...@@ -206,7 +207,7 @@ func (w *wasmModel) hackTestDb() error { ...@@ -206,7 +207,7 @@ func (w *wasmModel) hackTestDb() error {
if helper != nil { if helper != nil {
return helper return helper
} }
result, err := w.get(messageStoreName, js.ValueOf(msgId)) result, err := indexedDb.Get(w.db, messageStoreName, js.ValueOf(msgId))
if err != nil { if err != nil {
return err return err
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
//go:build js && wasm //go:build js && wasm
package indexedDb package channels
import ( import (
"time" "time"
...@@ -60,7 +60,7 @@ type Message struct { ...@@ -60,7 +60,7 @@ type Message struct {
Round uint64 `json:"round"` Round uint64 `json:"round"`
// User cryptographic Identity struct -- could be pulled out // User cryptographic Identity struct -- could be pulled out
Pubkey []byte `json:"pubkey"` // Index Pubkey []byte `json:"pubkey"`
CodesetVersion uint8 `json:"codeset_version"` CodesetVersion uint8 `json:"codeset_version"`
} }
......
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2022 xx foundation //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file. //
////////////////////////////////////////////////////////////////////////////////
//go:build js && wasm
// This file contains several generic IndexedDB helper functions that
// may be useful for any IndexedDB implementations.
package indexedDb
import (
"context"
"github.com/hack-pad/go-indexeddb/idb"
"github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/xxdk-wasm/utils"
"syscall/js"
"time"
)
// dbTimeout is the global timeout for operations with the storage
// [context.Context].
const dbTimeout = time.Second
// NewContext builds a context for indexedDb operations.
func NewContext() (context.Context, context.CancelFunc) {
return context.WithTimeout(context.Background(), dbTimeout)
}
// Get is a generic helper for getting values from the given [idb.ObjectStore].
func Get(db *idb.Database, objectStoreName string, key js.Value) (string, error) {
parentErr := errors.Errorf("failed to Get %s/%s", objectStoreName, key)
// Prepare the Transaction
txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName)
if err != nil {
return "", errors.WithMessagef(parentErr,
"Unable to create Transaction: %+v", err)
}
store, err := txn.ObjectStore(objectStoreName)
if err != nil {
return "", errors.WithMessagef(parentErr,
"Unable to get ObjectStore: %+v", err)
}
// Perform the operation
getRequest, err := store.Get(key)
if err != nil {
return "", errors.WithMessagef(parentErr,
"Unable to Get from ObjectStore: %+v", err)
}
// Wait for the operation to return
ctx, cancel := NewContext()
resultObj, err := getRequest.Await(ctx)
cancel()
if err != nil {
return "", errors.WithMessagef(parentErr,
"Unable to get from ObjectStore: %+v", err)
}
// Process result into string
resultStr := utils.JsToJson(resultObj)
jww.DEBUG.Printf("Got from %s/%s: %s", objectStoreName, key, resultStr)
return resultStr, nil
}
// GetIndex is a generic helper for getting values from the given
// [idb.ObjectStore] using the given [idb.Index].
func GetIndex(db *idb.Database, objectStoreName string,
indexName string, key js.Value) (js.Value, error) {
parentErr := errors.Errorf("failed to GetIndex %s/%s/%s",
objectStoreName, indexName, key)
// Prepare the Transaction
txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName)
if err != nil {
return js.Value{}, errors.WithMessagef(parentErr,
"Unable to create Transaction: %+v", err)
}
store, err := txn.ObjectStore(objectStoreName)
if err != nil {
return js.Value{}, errors.WithMessagef(parentErr,
"Unable to get ObjectStore: %+v", err)
}
idx, err := store.Index(indexName)
if err != nil {
return js.Value{}, errors.WithMessagef(parentErr,
"Unable to get Index: %+v", err)
}
// Perform the operation
getRequest, err := idx.Get(key)
if err != nil {
return js.Value{}, errors.WithMessagef(parentErr,
"Unable to Get from ObjectStore: %+v", err)
}
// Wait for the operation to return
ctx, cancel := NewContext()
resultObj, err := getRequest.Await(ctx)
cancel()
if err != nil {
return js.Value{}, errors.WithMessagef(parentErr,
"Unable to get from ObjectStore: %+v", err)
}
// Process result into string
resultStr := utils.JsToJson(resultObj)
jww.DEBUG.Printf("Got from %s/%s/%s: %s",
objectStoreName, indexName, key, resultStr)
return resultObj, nil
}
// Put is a generic helper for putting values into the given [idb.ObjectStore].
// Equivalent to insert if not exists else update.
func Put(db *idb.Database, objectStoreName string, value js.Value) (*idb.Request, error) {
// Prepare the Transaction
txn, err := db.Transaction(idb.TransactionReadWrite, objectStoreName)
if err != nil {
return nil, errors.Errorf("Unable to create Transaction: %+v", err)
}
store, err := txn.ObjectStore(objectStoreName)
if err != nil {
return nil, errors.Errorf("Unable to get ObjectStore: %+v", err)
}
// Perform the operation
request, err := store.Put(value)
if err != nil {
return nil, errors.Errorf("Unable to Put: %+v", err)
}
// Wait for the operation to return
ctx, cancel := NewContext()
err = txn.Await(ctx)
cancel()
if err != nil {
return nil, errors.Errorf("Putting value failed: %+v", err)
}
jww.DEBUG.Printf("Successfully put value in %s: %v",
objectStoreName, value.String())
return request, nil
}
// Delete is a generic helper for removing values from the given [idb.ObjectStore].
func Delete(db *idb.Database, objectStoreName string, key js.Value) error {
parentErr := errors.Errorf("failed to Delete %s/%s", objectStoreName, key)
// Prepare the Transaction
txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName)
if err != nil {
return errors.WithMessagef(parentErr,
"Unable to create Transaction: %+v", err)
}
store, err := txn.ObjectStore(objectStoreName)
if err != nil {
return errors.WithMessagef(parentErr,
"Unable to get ObjectStore: %+v", err)
}
// Perform the operation
deleteRequest, err := store.Delete(key)
if err != nil {
return errors.WithMessagef(parentErr,
"Unable to Get from ObjectStore: %+v", err)
}
// Wait for the operation to return
ctx, cancel := NewContext()
err = deleteRequest.Await(ctx)
cancel()
if err != nil {
return errors.WithMessagef(parentErr,
"Unable to delete from ObjectStore: %+v", err)
}
return nil
}
// Dump returns the given [idb.ObjectStore] contents to string slice for
// testing and debugging purposes.
func Dump(db *idb.Database, objectStoreName string) ([]string, error) {
parentErr := errors.Errorf("failed to Dump %s", objectStoreName)
txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName)
if err != nil {
return nil, errors.WithMessagef(parentErr,
"Unable to create Transaction: %+v", err)
}
store, err := txn.ObjectStore(objectStoreName)
if err != nil {
return nil, errors.WithMessagef(parentErr,
"Unable to get ObjectStore: %+v", err)
}
cursorRequest, err := store.OpenCursor(idb.CursorNext)
if err != nil {
return nil, errors.WithMessagef(parentErr,
"Unable to open Cursor: %+v", err)
}
// Run the query
jww.DEBUG.Printf("%s values:", objectStoreName)
results := make([]string, 0)
ctx, cancel := NewContext()
err = cursorRequest.Iter(ctx,
func(cursor *idb.CursorWithValue) error {
value, err := cursor.Value()
if err != nil {
return err
}
valueStr := utils.JsToJson(value)
results = append(results, valueStr)
jww.DEBUG.Printf("- %v", valueStr)
return nil
})
cancel()
if err != nil {
return nil, errors.WithMessagef(parentErr,
"Unable to dump ObjectStore: %+v", err)
}
return results, nil
}
...@@ -11,12 +11,12 @@ package wasm ...@@ -11,12 +11,12 @@ package wasm
import ( import (
"encoding/base64" "encoding/base64"
"gitlab.com/elixxir/xxdk-wasm/indexedDb/channels"
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
"sync" "sync"
"syscall/js" "syscall/js"
"gitlab.com/elixxir/client/v4/bindings" "gitlab.com/elixxir/client/v4/bindings"
"gitlab.com/elixxir/xxdk-wasm/indexedDb"
"gitlab.com/elixxir/xxdk-wasm/utils" "gitlab.com/elixxir/xxdk-wasm/utils"
) )
...@@ -394,7 +394,7 @@ func newChannelsManagerWithIndexedDb(cmixID int, privateIdentity []byte, ...@@ -394,7 +394,7 @@ func newChannelsManagerWithIndexedDb(cmixID int, privateIdentity []byte,
cb.Invoke(uuid, utils.CopyBytesToJS(channelID.Marshal()), update) cb.Invoke(uuid, utils.CopyBytesToJS(channelID.Marshal()), update)
} }
model := indexedDb.NewWASMEventModelBuilder(cipher, messageReceivedCB) model := channels.NewWASMEventModelBuilder(cipher, messageReceivedCB)
promiseFn := func(resolve, reject func(args ...any) js.Value) { promiseFn := func(resolve, reject func(args ...any) js.Value) {
cm, err := bindings.NewChannelsManagerGoEventModel( cm, err := bindings.NewChannelsManagerGoEventModel(
...@@ -493,7 +493,7 @@ func loadChannelsManagerWithIndexedDb(cmixID int, storageTag string, ...@@ -493,7 +493,7 @@ func loadChannelsManagerWithIndexedDb(cmixID int, storageTag string,
cb.Invoke(uuid, utils.CopyBytesToJS(channelID.Marshal()), updated) cb.Invoke(uuid, utils.CopyBytesToJS(channelID.Marshal()), updated)
} }
model := indexedDb.NewWASMEventModelBuilder(cipher, messageReceivedCB) model := channels.NewWASMEventModelBuilder(cipher, messageReceivedCB)
promiseFn := func(resolve, reject func(args ...any) js.Value) { promiseFn := func(resolve, reject func(args ...any) js.Value) {
cm, err := bindings.LoadChannelsManagerGoEventModel( cm, err := bindings.LoadChannelsManagerGoEventModel(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment