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

adjust structure of context deadline in impl.go

parent 1245f8e6
No related branches found
No related tags found
3 merge requests!116XX-4684 / Use new wasm-utils repo,!113adjust structure of context deadline in impl.go,!67fix for latest client release
......@@ -121,19 +121,19 @@ func (w *wasmModel) deleteMsgByChannel(channelID *id.ID) error {
"Unable to get Index: %+v", err)
}
// Perform the operation
// Set up the operation
keyRange, err := idb.NewKeyRangeOnly(impl.EncodeBytes(channelID.Marshal()))
cursorRequest, err := index.OpenCursorRange(keyRange, idb.CursorNext)
if err != nil {
return errors.WithMessagef(parentErr, "Unable to open Cursor: %+v", err)
}
ctx, cancel := impl.NewContext()
err = cursorRequest.Iter(ctx,
// Perform the operation
err = impl.SendCursorRequest(cursorRequest,
func(cursor *idb.CursorWithValue) error {
_, err := cursor.Delete()
return err
})
cancel()
if err != nil {
return errors.WithMessagef(parentErr,
"Unable to delete Message data: %+v", err)
......
......@@ -81,6 +81,8 @@ func newWASMModel(databaseName string, encryption cryptoChannel.Cipher,
db, err := openRequest.Await(ctx)
if err != nil {
return nil, err
} else if ctx.Err() != nil {
return nil, ctx.Err()
}
wrapper := &wasmModel{
......@@ -90,7 +92,6 @@ func newWASMModel(databaseName string, encryption cryptoChannel.Cipher,
deletedMessageCB: deletedMessageCB,
mutedUserCB: mutedUserCB,
}
return wrapper, nil
}
......
......@@ -75,10 +75,11 @@ func newWASMModel(databaseName string, encryption cryptoChannel.Cipher,
db, err := openRequest.Await(ctx)
if err != nil {
return nil, err
} else if ctx.Err() != nil {
return nil, ctx.Err()
}
wrapper := &wasmModel{db: db, receivedMessageCB: cb, cipher: encryption}
return wrapper, nil
}
......
......@@ -30,9 +30,6 @@ const (
// ErrDoesNotExist is an error string for got undefined on Get operations.
ErrDoesNotExist = "result is undefined"
// ErrUniqueConstraint is an error string for failed uniqueness inserts.
ErrUniqueConstraint = "at least one key does not satisfy the uniqueness requirements"
)
// NewContext builds a context for indexedDb operations.
......@@ -45,6 +42,31 @@ func EncodeBytes(input []byte) js.Value {
return js.ValueOf(base64.StdEncoding.EncodeToString(input))
}
// SendRequest is a wrapper for the request.Await() method providing a timeout.
func SendRequest(request *idb.Request) (js.Value, error) {
ctx, cancel := NewContext()
defer cancel()
result, err := request.Await(ctx)
if err != nil {
return js.Undefined(), err
} else if ctx.Err() != nil {
return js.Undefined(), ctx.Err()
}
return result, nil
}
// SendCursorRequest is a wrapper for the cursorRequest.Await() method providing a timeout.
func SendCursorRequest(cur *idb.CursorWithValueRequest,
iterFunc func(cursor *idb.CursorWithValue) error) error {
ctx, cancel := NewContext()
defer cancel()
err := cur.Iter(ctx, iterFunc)
if ctx.Err() != nil {
return ctx.Err()
}
return err
}
// Get is a generic helper for getting values from the given [idb.ObjectStore].
// Only usable by primary key.
func Get(db *idb.Database, objectStoreName string, key js.Value) (js.Value, error) {
......@@ -62,22 +84,18 @@ func Get(db *idb.Database, objectStoreName string, key js.Value) (js.Value, erro
"Unable to get ObjectStore: %+v", err)
}
// Perform the operation
// Set up the operation
getRequest, err := store.Get(key)
if err != nil {
return js.Undefined(), 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()
// Perform the operation
resultObj, err := SendRequest(getRequest)
if err != nil {
return js.Undefined(), errors.WithMessagef(parentErr,
"Unable to get from ObjectStore: %+v", err)
} else if err = ctx.Err(); errors.Is(err, context.DeadlineExceeded) {
return js.Null(), errors.Wrapf(err, "timed out after %s", dbTimeout)
} else if resultObj.IsUndefined() {
return js.Undefined(), errors.WithMessagef(parentErr,
"Unable to get from ObjectStore: %s", ErrDoesNotExist)
......@@ -105,14 +123,15 @@ func GetAll(db *idb.Database, objectStoreName string) ([]js.Value, error) {
"Unable to get ObjectStore: %+v", err)
}
// Perform the operation
result := make([]js.Value, 0)
// Set up the operation
cursorRequest, err := store.OpenCursor(idb.CursorNext)
if err != nil {
return nil, errors.WithMessagef(parentErr, "Unable to open Cursor: %+v", err)
}
ctx, cancel := NewContext()
err = cursorRequest.Iter(ctx,
result := make([]js.Value, 0)
// Perform the operation
err = SendCursorRequest(cursorRequest,
func(cursor *idb.CursorWithValue) error {
row, err := cursor.Value()
if err != nil {
......@@ -121,7 +140,6 @@ func GetAll(db *idb.Database, objectStoreName string) ([]js.Value, error) {
result = append(result, row)
return nil
})
cancel()
if err != nil {
return nil, errors.WithMessagef(parentErr, err.Error())
}
......@@ -152,22 +170,18 @@ func GetIndex(db *idb.Database, objectStoreName,
"Unable to get Index: %+v", err)
}
// Perform the operation
// Set up the operation
getRequest, err := idx.Get(key)
if err != nil {
return js.Undefined(), 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()
// Perform the operation
resultObj, err := SendRequest(getRequest)
if err != nil {
return js.Undefined(), errors.WithMessagef(parentErr,
"Unable to get from ObjectStore: %+v", err)
} else if err = ctx.Err(); errors.Is(err, context.DeadlineExceeded) {
return js.Null(), errors.Wrapf(err, "timed out after %s", dbTimeout)
} else if resultObj.IsUndefined() {
return js.Undefined(), errors.WithMessagef(parentErr,
"Unable to get from ObjectStore: %s", ErrDoesNotExist)
......@@ -193,25 +207,21 @@ func Put(db *idb.Database, objectStoreName string, value js.Value) (js.Value, er
return js.Undefined(), errors.Errorf("Unable to get ObjectStore: %+v", err)
}
// Perform the operation
// Set up the operation
request, err := store.Put(value)
if err != nil {
return js.Undefined(), errors.Errorf("Unable to Put: %+v", err)
}
// Wait for the operation to return
ctx, cancel := NewContext()
result, err := request.Await(ctx)
cancel()
// Perform the operation
resultObj, err := SendRequest(request)
if err != nil {
return js.Undefined(), errors.Errorf("Putting value failed: %+v\n%s",
err, utils.JsToJson(value))
} else if err = ctx.Err(); errors.Is(err, context.DeadlineExceeded) {
return js.Null(), errors.Wrapf(err, "timed out after %s", dbTimeout)
}
jww.DEBUG.Printf("Successfully put value in %s: %s",
objectStoreName, utils.JsToJson(value))
return result, nil
return resultObj, nil
}
// Delete is a generic helper for removing values from the given
......@@ -232,21 +242,17 @@ func Delete(db *idb.Database, objectStoreName string, key js.Value) error {
}
// Perform the operation
_, err = store.Delete(key)
deleteRequest, err := store.Delete(key)
if err != nil {
return errors.WithMessagef(parentErr,
"Unable to Delete from ObjectStore: %+v", err)
}
// Wait for the operation to return
ctx, cancel := NewContext()
err = txn.Await(ctx)
cancel()
// Perform the operation
_, err = SendRequest(deleteRequest.Request)
if err != nil {
return errors.WithMessagef(parentErr,
"Unable to Delete from ObjectStore: %+v", err)
} else if err = ctx.Err(); errors.Is(err, context.DeadlineExceeded) {
return errors.Wrapf(err, "timed out after %s", dbTimeout)
}
jww.DEBUG.Printf("Successfully deleted value at %s/%s",
objectStoreName, utils.JsToJson(key))
......@@ -290,17 +296,18 @@ func Dump(db *idb.Database, objectStoreName string) ([]string, error) {
return nil, errors.WithMessagef(parentErr,
"Unable to get ObjectStore: %+v", err)
}
// Set up the operation
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,
// Perform the operation
err = SendCursorRequest(cursorRequest,
func(cursor *idb.CursorWithValue) error {
value, err := cursor.Value()
if err != nil {
......@@ -311,7 +318,6 @@ func Dump(db *idb.Database, objectStoreName string) ([]string, error) {
jww.DEBUG.Printf("- %v", valueStr)
return nil
})
cancel()
if err != nil {
return nil, errors.WithMessagef(parentErr,
"Unable to dump ObjectStore: %+v", err)
......
......@@ -11,9 +11,11 @@ package impl
import (
"github.com/hack-pad/go-indexeddb/idb"
jww "github.com/spf13/jwalterweatherman"
"strings"
"syscall/js"
"testing"
"time"
)
// Error path: Tests that Get returns an error when trying to get a message that
......@@ -92,3 +94,52 @@ func newTestDB(name, index string, t *testing.T) *idb.Database {
return db
}
// TestBenchmark ensures IndexedDb can take at least n operations per second.
func TestBenchmark(t *testing.T) {
jww.SetStdoutThreshold(jww.LevelInfo)
benchmarkDb(50, t)
}
// benchmarkDb sends n operations to IndexedDb and prints errors.
func benchmarkDb(n int, t *testing.T) {
jww.INFO.Printf("Benchmarking IndexedDb: %d total.", n)
objectStoreName := "test"
testValue := js.ValueOf(make(map[string]interface{}))
db := newTestDB(objectStoreName, "index", t)
type metric struct {
didSucceed bool
duration time.Duration
}
done := make(chan metric)
// Spawn n operations at the same time
startTime := time.Now()
for i := 0; i < n; i++ {
go func() {
opStart := time.Now()
_, err := Put(db, objectStoreName, testValue)
done <- metric{
didSucceed: err == nil,
duration: time.Since(opStart),
}
}()
}
// Wait for all to complete
didSucceed := true
for i := 0; i < n; i++ {
result := <-done
if !result.didSucceed {
didSucceed = false
}
jww.DEBUG.Printf("Operation time: %s", result.duration)
}
timeElapsed := time.Since(startTime)
jww.INFO.Printf("Benchmarking complete. Succeeded: %t\n"+
"Took %s, Average of %s.",
didSucceed, timeElapsed, timeElapsed/time.Duration(n))
}
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