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

delete old messages when channel is left

parent 6aa8e0ba
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 dump ObjectStore: %+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
......
...@@ -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,58 @@ func TestWasmModel_DuplicateReceives(t *testing.T) { ...@@ -210,3 +211,58 @@ 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 < expectedMessages; i++ {
testStr := testString + strconv.Itoa(i)
testMsgId := channel.MakeMessageID([]byte(testStr), &id.ID{1})
eventModel.ReceiveMessage(deleteChannel, testMsgId, testStr,
testStr, cid, time.Now(), time.Second, rounds.Round{ID: id.Round(0)}, 0, channels.Sent)
}
for i := expectedMessages; i < totalMessages; i++ {
testStr := testString + strconv.Itoa(i)
testMsgId := channel.MakeMessageID([]byte(testStr), &id.ID{1})
eventModel.ReceiveMessage(keepChannel, 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
} }
_, err = messageStore.CreateIndex(messageStoreMessageIndex,
messageStoreMessageIndexOpts := idb.IndexOptions{ js.ValueOf(messageStoreMessage),
idb.IndexOptions{
Unique: true, Unique: true,
MultiEntry: false, MultiEntry: false,
} })
_, err = messageStore.CreateIndex(messageStoreMessageIndex,
js.ValueOf(messageStoreMessage), messageStoreMessageIndexOpts)
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.
Please register or to comment