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

Merge branch 'XX-4247/DeleteOldMessages' into 'release'

delete old messages when channel is left

See merge request !13
parents 6aa8e0ba bfb3b1d3
No related branches found
No related tags found
2 merge requests!60Revert "Fail a test to be sure it works",!13delete old messages when channel is left
...@@ -20,12 +20,12 @@ import ( ...@@ -20,12 +20,12 @@ import (
"github.com/hack-pad/go-indexeddb/idb" "github.com/hack-pad/go-indexeddb/idb"
"github.com/pkg/errors" "github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/xxdk-wasm/utils"
"gitlab.com/elixxir/client/channels" "gitlab.com/elixxir/client/channels"
"gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/client/cmix/rounds"
cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast" cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast"
cryptoChannel "gitlab.com/elixxir/crypto/channel" cryptoChannel "gitlab.com/elixxir/crypto/channel"
"gitlab.com/elixxir/xxdk-wasm/utils"
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
) )
...@@ -141,9 +141,60 @@ func (w *wasmModel) LeaveChannel(channelID *id.ID) { ...@@ -141,9 +141,60 @@ func (w *wasmModel) LeaveChannel(channelID *id.ID) {
"Deleting Channel failed: %+v", err)) "Deleting Channel failed: %+v", err))
return return
} }
// Clean up lingering data
err = w.deleteMsgByChannel(channelID)
if err != nil {
jww.ERROR.Printf("%+v", errors.WithMessagef(parentErr,
"Deleting Channel's Message data failed: %+v", err))
return
}
jww.DEBUG.Printf("Successfully deleted channel: %s", channelID) jww.DEBUG.Printf("Successfully deleted channel: %s", channelID)
} }
// deleteMsgByChannel is a private helper that uses messageStoreChannelIndex
// to delete all Message with the given Channel ID.
func (w *wasmModel) deleteMsgByChannel(channelID *id.ID) error {
parentErr := errors.New("failed to deleteMsgByChannel")
// Prepare the Transaction
txn, err := w.db.Transaction(idb.TransactionReadWrite, messageStoreName)
if err != nil {
return errors.WithMessagef(parentErr,
"Unable to create Transaction: %+v", err)
}
store, err := txn.ObjectStore(messageStoreName)
if err != nil {
return errors.WithMessagef(parentErr,
"Unable to get ObjectStore: %+v", err)
}
index, err := store.Index(messageStoreChannelIndex)
if err != nil {
return errors.WithMessagef(parentErr,
"Unable to get Index: %+v", err)
}
// Perform the operation
channelIdStr := base64.StdEncoding.EncodeToString(channelID.Marshal())
keyRange, err := idb.NewKeyRangeOnly(js.ValueOf(channelIdStr))
cursorRequest, err := index.OpenCursorRange(keyRange, idb.CursorNext)
if err != nil {
return errors.WithMessagef(parentErr, "Unable to open Cursor: %+v", err)
}
ctx, cancel := newContext()
err = cursorRequest.Iter(ctx,
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)
}
return nil
}
// ReceiveMessage is called whenever a message is received on a given channel. // ReceiveMessage is called whenever a message is received on a given channel.
// //
// It may be called multiple times on the same message; it is incumbent on the // It may be called multiple times on the same message; it is incumbent on the
...@@ -159,7 +210,7 @@ func (w *wasmModel) ReceiveMessage(channelID *id.ID, ...@@ -159,7 +210,7 @@ func (w *wasmModel) ReceiveMessage(channelID *id.ID,
uuid, err := w.receiveHelper(msgToInsert) uuid, err := w.receiveHelper(msgToInsert)
if err != nil { if err != nil {
jww.ERROR.Printf("Failed to receiver message: %+v", err) jww.ERROR.Printf("Failed to receive Message: %+v", err)
} }
go w.receivedMessageCB(uuid, channelID, false) go w.receivedMessageCB(uuid, channelID, false)
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
"strconv"
"testing" "testing"
"time" "time"
...@@ -210,3 +211,59 @@ func TestWasmModel_DuplicateReceives(t *testing.T) { ...@@ -210,3 +211,59 @@ func TestWasmModel_DuplicateReceives(t *testing.T) {
} }
} }
} }
// TestWasmModel_deleteMsgByChannel is a happy path test. Inserts many messages,
// deletes some, and checks that the final result is as expected.
func TestWasmModel_deleteMsgByChannel(t *testing.T) {
testString := "test_deleteMsgByChannel"
totalMessages := 10
expectedMessages := 5
eventModel, err := newWASMModel(testString, dummyCallback)
if err != nil {
t.Fatalf("%+v", err)
}
// Create a test channel id
deleteChannel := id.NewIdFromString("deleteMe", id.Generic, t)
keepChannel := id.NewIdFromString("dontDeleteMe", id.Generic, t)
// Store some test messages
cid := channel.Identity{}
for i := 0; i < totalMessages; i++ {
testStr := testString + strconv.Itoa(i)
// Interleave the channel id to ensure cursor is behaving intelligently
thisChannel := deleteChannel
if i%2 == 0 {
thisChannel = keepChannel
}
testMsgId := channel.MakeMessageID([]byte(testStr), &id.ID{1})
eventModel.ReceiveMessage(thisChannel, testMsgId, testStr,
testStr, cid, time.Now(), time.Second, rounds.Round{ID: id.Round(0)}, 0, channels.Sent)
}
// Check pre-results
result, err := eventModel.dump(messageStoreName)
if err != nil {
t.Fatalf("%+v", err)
}
if len(result) != totalMessages {
t.Errorf("Expected %d messages, got %d", totalMessages, len(result))
}
// Do delete
err = eventModel.deleteMsgByChannel(deleteChannel)
if err != nil {
t.Error(err)
}
// Check final results
result, err = eventModel.dump(messageStoreName)
if err != nil {
t.Fatalf("%+v", err)
}
if len(result) != expectedMessages {
t.Errorf("Expected %d messages, got %d", expectedMessages, len(result))
}
}
...@@ -102,13 +102,12 @@ func v1Upgrade(db *idb.Database) error { ...@@ -102,13 +102,12 @@ func v1Upgrade(db *idb.Database) error {
if err != nil { if err != nil {
return err return err
} }
messageStoreMessageIndexOpts := idb.IndexOptions{
Unique: true,
MultiEntry: false,
}
_, err = messageStore.CreateIndex(messageStoreMessageIndex, _, err = messageStore.CreateIndex(messageStoreMessageIndex,
js.ValueOf(messageStoreMessage), messageStoreMessageIndexOpts) js.ValueOf(messageStoreMessage),
idb.IndexOptions{
Unique: true,
MultiEntry: false,
})
if err != nil { if err != nil {
return err return err
} }
......
...@@ -27,7 +27,6 @@ const ( ...@@ -27,7 +27,6 @@ const (
messageStoreParentIndex = "parent_message_id_index" messageStoreParentIndex = "parent_message_id_index"
messageStoreTimestampIndex = "timestamp_index" messageStoreTimestampIndex = "timestamp_index"
messageStorePinnedIndex = "pinned_index" messageStorePinnedIndex = "pinned_index"
messageStorePubkeyIndex = "pubkey_index"
// Message keyPath names (must match json struct tags). // Message keyPath names (must match json struct tags).
messageStoreMessage = "message_id" messageStoreMessage = "message_id"
......
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