Store performance improvements (#849)

This commit is contained in:
Hanno Cornelius
2022-02-17 11:00:45 +01:00
committed by GitHub
parent d851d48424
commit bb3e59454e
9 changed files with 789 additions and 311 deletions
+3 -1
View File
@@ -19,7 +19,9 @@ import
./v2/test_namespacing_utils,
./v2/test_waku_dnsdisc,
./v2/test_waku_discv5,
./v2/test_enr_utils
./v2/test_enr_utils,
./v2/test_waku_store_queue,
./v2/test_pagination_utils
when defined(rln):
import ./v2/test_waku_rln_relay
+83
View File
@@ -0,0 +1,83 @@
{.used.}
import
testutils/unittests,
chronos,
stew/byteutils,
libp2p/crypto/crypto,
../../waku/v2/utils/pagination
procSuite "Pagination utils":
## Helpers
proc hashFromStr(input: string): MDigest[256] =
var ctx: sha256
ctx.init()
ctx.update(input.toBytes()) # converts the input to bytes
let hashed = ctx.finish() # computes the hash
ctx.clear()
return hashed
## Test vars
let
smallIndex1 = Index(digest: hashFromStr("1234"),
receiverTime: 0.00,
senderTime: 1000.00)
smallIndex2 = Index(digest: hashFromStr("1234567"), # digest is less significant than senderTime
receiverTime: 0.00,
senderTime: 1000.00)
largeIndex1 = Index(digest: hashFromStr("1234"),
receiverTime: 0.00,
senderTime: 9000.00) # only senderTime differ from smallIndex1
largeIndex2 = Index(digest: hashFromStr("12345"), # only digest differs from smallIndex1
receiverTime: 0.00,
senderTime: 1000.00)
eqIndex1 = Index(digest: hashFromStr("0003"),
receiverTime: 0.00,
senderTime: 54321.00)
eqIndex2 = Index(digest: hashFromStr("0003"),
receiverTime: 0.00,
senderTime: 54321.00)
eqIndex3 = Index(digest: hashFromStr("0003"),
receiverTime: 9999.00, # receiverTime difference should have no effect on comparisons
senderTime: 54321.00)
## Test suite
asyncTest "Index comparison":
check:
# Index comparison with senderTime diff
cmp(smallIndex1, largeIndex1) < 0
cmp(smallIndex2, largeIndex1) < 0
# Index comparison with digest diff
cmp(smallIndex1, smallIndex2) < 0
cmp(smallIndex1, largeIndex2) < 0
cmp(smallIndex2, largeIndex2) > 0
cmp(largeIndex1, largeIndex2) > 0
# Index comparison when equal
cmp(eqIndex1, eqIndex2) == 0
# receiverTime difference play no role
cmp(eqIndex1, eqIndex3) == 0
asyncTest "Index equality":
check:
# Exactly equal
eqIndex1 == eqIndex2
# Receiver time plays no role
eqIndex1 == eqIndex3
# Unequal sender time
smallIndex1 != largeIndex1
# Unequal digest
smallIndex1 != smallIndex2
# Unequal hash and digest
smallIndex1 != eqIndex1
+69 -100
View File
@@ -1,18 +1,27 @@
{.used.}
import
std/[algorithm, options],
std/[algorithm, options, sequtils],
testutils/unittests, nimcrypto/sha2,
libp2p/protobuf/minprotobuf,
../../waku/v2/protocol/waku_store/waku_store,
../test_helpers
proc createSampleList(s: int): seq[IndexedWakuMessage] =
## takes s as input and outputs a sequence with s amount of IndexedWakuMessage
proc createSampleStoreQueue(s: int): StoreQueueRef =
## takes s as input and outputs a StoreQueue with s amount of IndexedWakuMessage
let testStoreQueue = StoreQueueRef.new(s)
var data {.noinit.}: array[32, byte]
for x in data.mitems: x = 1
for i in 0..<s:
result.add(IndexedWakuMessage(msg: WakuMessage(payload: @[byte i]), index: Index(receiverTime: float64(i), senderTime: float64(i), digest: MDigest[256](data: data)) ))
discard testStoreQueue.add(IndexedWakuMessage(msg: WakuMessage(payload: @[byte i]),
index: Index(receiverTime: float64(i),
senderTime: float64(i),
digest: MDigest[256](data: data)) ))
return testStoreQueue
procSuite "pagination":
test "Index computation test":
@@ -36,90 +45,48 @@ procSuite "pagination":
# the digests of two identical WakuMessages must be the same
index1.digest == index2.digest
test "Index comparison, IndexedWakuMessage comparison, and Sorting tests":
var data1 {.noinit.}: array[32, byte]
for x in data1.mitems: x = 1
var data2 {.noinit.}: array[32, byte]
for x in data2.mitems: x = 2
var data3 {.noinit.}: array[32, byte]
for x in data3.mitems: x = 3
let
index1 = Index(receiverTime: 2, senderTime: 1, digest: MDigest[256](data: data1))
index2 = Index(receiverTime: 2, senderTime: 1, digest: MDigest[256](data: data2))
index3 = Index(receiverTime: 1, senderTime: 2, digest: MDigest[256](data: data3))
iwm1 = IndexedWakuMessage(index: index1)
iwm2 = IndexedWakuMessage(index: index2)
iwm3 = IndexedWakuMessage(index: index3)
check:
indexComparison(index1, index1) == 0
indexComparison(index1, index2) == -1
indexComparison(index2, index1) == 1
indexComparison(index1, index3) == -1
indexComparison(index3, index1) == 1
check:
indexedWakuMessageComparison(iwm1, iwm1) == 0
indexedWakuMessageComparison(iwm1, iwm2) == -1
indexedWakuMessageComparison(iwm2, iwm1) == 1
indexedWakuMessageComparison(iwm1, iwm3) == -1
indexedWakuMessageComparison(iwm3, iwm1) == 1
var sortingList = @[iwm3, iwm1, iwm2]
sortingList.sort(indexedWakuMessageComparison)
check:
sortingList[0] == iwm1
sortingList[1] == iwm2
sortingList[2] == iwm3
test "Find Index test":
let msgList = createSampleList(10)
check:
msgList.findIndex(msgList[3].index).get() == 3
msgList.findIndex(Index()).isNone == true
test "Forward pagination test":
var
msgList = createSampleList(10)
pagingInfo = PagingInfo(pageSize: 2, cursor: msgList[3].index, direction: PagingDirection.FORWARD)
var
stQ = createSampleStoreQueue(10)
indexList = toSeq(stQ.fwdIterator()).mapIt(it[0]) # Seq copy of the store queue indices for verification
msgList = toSeq(stQ.fwdIterator()).mapIt(it[1].msg) # Seq copy of the store queue messages for verification
pagingInfo = PagingInfo(pageSize: 2, cursor: indexList[3], direction: PagingDirection.FORWARD)
# test for a normal pagination
var (data, newPagingInfo, error) = paginate(msgList, pagingInfo)
var (data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
data.len == 2
data == msgList[4..5]
newPagingInfo.cursor == msgList[5].index
newPagingInfo.cursor == indexList[5]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == pagingInfo.pageSize
error == HistoryResponseError.NONE
# test for an initial pagination request with an empty cursor
pagingInfo = PagingInfo(pageSize: 2, direction: PagingDirection.FORWARD)
(data, newPagingInfo, error) = paginate(msgList, pagingInfo)
(data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
data.len == 2
data == msgList[0..1]
newPagingInfo.cursor == msgList[1].index
newPagingInfo.cursor == indexList[1]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == 2
error == HistoryResponseError.NONE
# test for an initial pagination request with an empty cursor to fetch the entire history
pagingInfo = PagingInfo(pageSize: 13, direction: PagingDirection.FORWARD)
(data, newPagingInfo, error) = paginate(msgList, pagingInfo)
(data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
data.len == 10
data == msgList[0..9]
newPagingInfo.cursor == msgList[9].index
newPagingInfo.cursor == indexList[9]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == 10
error == HistoryResponseError.NONE
# test for an empty msgList
pagingInfo = PagingInfo(pageSize: 2, direction: PagingDirection.FORWARD)
(data, newPagingInfo, error) = paginate(@[], pagingInfo)
(data, newPagingInfo, error) = getPage(createSampleStoreQueue(0), pagingInfo)
check:
data.len == 0
newPagingInfo.pageSize == 0
@@ -128,19 +95,19 @@ procSuite "pagination":
error == HistoryResponseError.NONE
# test for a page size larger than the remaining messages
pagingInfo = PagingInfo(pageSize: 10, cursor: msgList[3].index, direction: PagingDirection.FORWARD)
(data, newPagingInfo, error) = paginate(msgList, pagingInfo)
pagingInfo = PagingInfo(pageSize: 10, cursor: indexList[3], direction: PagingDirection.FORWARD)
(data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
data.len == 6
data == msgList[4..9]
newPagingInfo.cursor == msgList[9].index
newPagingInfo.cursor == indexList[9]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == 6
error == HistoryResponseError.NONE
# test for a page size larger than the maximum allowed page size
pagingInfo = PagingInfo(pageSize: MaxPageSize+1, cursor: msgList[3].index, direction: PagingDirection.FORWARD)
(data, newPagingInfo, error) = paginate(msgList, pagingInfo)
pagingInfo = PagingInfo(pageSize: MaxPageSize+1, cursor: indexList[3], direction: PagingDirection.FORWARD)
(data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
uint64(data.len) <= MaxPageSize
newPagingInfo.direction == pagingInfo.direction
@@ -148,18 +115,18 @@ procSuite "pagination":
error == HistoryResponseError.NONE
# test for a cursor pointing to the end of the message list
pagingInfo = PagingInfo(pageSize: 10, cursor: msgList[9].index, direction: PagingDirection.FORWARD)
(data, newPagingInfo, error) = paginate(msgList, pagingInfo)
pagingInfo = PagingInfo(pageSize: 10, cursor: indexList[9], direction: PagingDirection.FORWARD)
(data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
data.len == 0
newPagingInfo.cursor == msgList[9].index
newPagingInfo.cursor == indexList[9]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == 0
error == HistoryResponseError.NONE
# test for an invalid cursor
pagingInfo = PagingInfo(pageSize: 10, cursor: computeIndex(WakuMessage(payload: @[byte 10])), direction: PagingDirection.FORWARD)
(data, newPagingInfo, error) = paginate(msgList, pagingInfo)
(data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
data.len == 0
newPagingInfo.cursor == pagingInfo.cursor
@@ -168,44 +135,46 @@ procSuite "pagination":
error == HistoryResponseError.INVALID_CURSOR
# test initial paging query over a message list with one message
var singleItemMsgList = msgList[0..0]
var singleItemMsgList = createSampleStoreQueue(1)
pagingInfo = PagingInfo(pageSize: 10, direction: PagingDirection.FORWARD)
(data, newPagingInfo, error) = paginate(singleItemMsgList, pagingInfo)
(data, newPagingInfo, error) = getPage(singleItemMsgList, pagingInfo)
check:
data.len == 1
newPagingInfo.cursor == msgList[0].index
newPagingInfo.cursor == indexList[0]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == 1
error == HistoryResponseError.NONE
# test pagination over a message list with one message
singleItemMsgList = msgList[0..0]
pagingInfo = PagingInfo(pageSize: 10, cursor: msgList[0].index, direction: PagingDirection.FORWARD)
(data, newPagingInfo, error) = paginate(singleItemMsgList, pagingInfo)
singleItemMsgList = createSampleStoreQueue(1)
pagingInfo = PagingInfo(pageSize: 10, cursor: indexList[0], direction: PagingDirection.FORWARD)
(data, newPagingInfo, error) = getPage(singleItemMsgList, pagingInfo)
check:
data.len == 0
newPagingInfo.cursor == msgList[0].index
newPagingInfo.cursor == indexList[0]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == 0
error == HistoryResponseError.NONE
test "Backward pagination test":
var
msgList = createSampleList(10)
pagingInfo = PagingInfo(pageSize: 2, cursor: msgList[3].index, direction: PagingDirection.BACKWARD)
stQ = createSampleStoreQueue(10)
indexList = toSeq(stQ.fwdIterator()).mapIt(it[0]) # Seq copy of the store queue indices for verification
msgList = toSeq(stQ.fwdIterator()).mapIt(it[1].msg) # Seq copy of the store queue messages for verification
pagingInfo = PagingInfo(pageSize: 2, cursor: indexList[3], direction: PagingDirection.BACKWARD)
# test for a normal pagination
var (data, newPagingInfo, error) = paginate(msgList, pagingInfo)
var (data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
data == msgList[1..2]
newPagingInfo.cursor == msgList[1].index
newPagingInfo.cursor == indexList[1]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == pagingInfo.pageSize
error == HistoryResponseError.NONE
# test for an empty msgList
pagingInfo = PagingInfo(pageSize: 2, direction: PagingDirection.BACKWARD)
(data, newPagingInfo, error) = paginate(@[], pagingInfo)
(data, newPagingInfo, error) = getPage(createSampleStoreQueue(0), pagingInfo)
check:
data.len == 0
newPagingInfo.pageSize == 0
@@ -215,40 +184,39 @@ procSuite "pagination":
# test for an initial pagination request with an empty cursor
pagingInfo = PagingInfo(pageSize: 2, direction: PagingDirection.BACKWARD)
(data, newPagingInfo, error) = paginate(msgList, pagingInfo)
(data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
data.len == 2
data == msgList[8..9]
newPagingInfo.cursor == msgList[8].index
newPagingInfo.cursor == indexList[8]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == 2
error == HistoryResponseError.NONE
# test for an initial pagination request with an empty cursor to fetch the entire history
pagingInfo = PagingInfo(pageSize: 13, direction: PagingDirection.BACKWARD)
(data, newPagingInfo, error) = paginate(msgList, pagingInfo)
(data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
data.len == 10
data == msgList[0..9]
newPagingInfo.cursor == msgList[0].index
newPagingInfo.cursor == indexList[0]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == 10
error == HistoryResponseError.NONE
# test for a page size larger than the remaining messages
pagingInfo = PagingInfo(pageSize: 5, cursor: msgList[3].index, direction: PagingDirection.BACKWARD)
(data, newPagingInfo, error) = paginate(msgList, pagingInfo)
pagingInfo = PagingInfo(pageSize: 5, cursor: indexList[3], direction: PagingDirection.BACKWARD)
(data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
data == msgList[0..2]
newPagingInfo.cursor == msgList[0].index
newPagingInfo.cursor == indexList[0]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == 3
error == HistoryResponseError.NONE
# test for a page size larger than the Maximum allowed page size
pagingInfo = PagingInfo(pageSize: MaxPageSize+1, cursor: msgList[3].index, direction: PagingDirection.BACKWARD)
(data, newPagingInfo, error) = paginate(msgList, pagingInfo)
pagingInfo = PagingInfo(pageSize: MaxPageSize+1, cursor: indexList[3], direction: PagingDirection.BACKWARD)
(data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
uint64(data.len) <= MaxPageSize
newPagingInfo.direction == pagingInfo.direction
@@ -256,19 +224,19 @@ procSuite "pagination":
error == HistoryResponseError.NONE
# test for a cursor pointing to the begining of the message list
pagingInfo = PagingInfo(pageSize: 5, cursor: msgList[0].index, direction: PagingDirection.BACKWARD)
(data, newPagingInfo, error) = paginate(msgList, pagingInfo)
pagingInfo = PagingInfo(pageSize: 5, cursor: indexList[0], direction: PagingDirection.BACKWARD)
(data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
data.len == 0
newPagingInfo.cursor == msgList[0].index
newPagingInfo.cursor == indexList[0]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == 0
error == HistoryResponseError.NONE
# test for an invalid cursor
pagingInfo = PagingInfo(pageSize: 5, cursor: computeIndex(WakuMessage(payload: @[byte 10])), direction: PagingDirection.BACKWARD)
(data, newPagingInfo, error) = paginate(msgList, pagingInfo)
(data, newPagingInfo, error) = getPage(stQ, pagingInfo)
check:
data.len == 0
newPagingInfo.cursor == pagingInfo.cursor
@@ -277,23 +245,23 @@ procSuite "pagination":
error == HistoryResponseError.INVALID_CURSOR
# test initial paging query over a message list with one message
var singleItemMsgList = msgList[0..0]
var singleItemMsgList = createSampleStoreQueue(1)
pagingInfo = PagingInfo(pageSize: 10, direction: PagingDirection.BACKWARD)
(data, newPagingInfo, error) = paginate(singleItemMsgList, pagingInfo)
(data, newPagingInfo, error) = getPage(singleItemMsgList, pagingInfo)
check:
data.len == 1
newPagingInfo.cursor == msgList[0].index
newPagingInfo.cursor == indexList[0]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == 1
error == HistoryResponseError.NONE
# test paging query over a message list with one message
singleItemMsgList = msgList[0..0]
pagingInfo = PagingInfo(pageSize: 10, cursor: msgList[0].index, direction: PagingDirection.BACKWARD)
(data, newPagingInfo, error) = paginate(singleItemMsgList, pagingInfo)
singleItemMsgList = createSampleStoreQueue(1)
pagingInfo = PagingInfo(pageSize: 10, cursor: indexList[0], direction: PagingDirection.BACKWARD)
(data, newPagingInfo, error) = getPage(singleItemMsgList, pagingInfo)
check:
data.len == 0
newPagingInfo.cursor == msgList[0].index
newPagingInfo.cursor == indexList[0]
newPagingInfo.direction == pagingInfo.direction
newPagingInfo.pageSize == 0
error == HistoryResponseError.NONE
@@ -319,6 +287,7 @@ suite "time-window history query":
timestampDecoded = msgDecoded.value.timestamp
check:
timestampDecoded == timestamp
test "Encode/Decode waku message without timestamp":
# test the encoding and decoding of a WakuMessage with an empty timestamp field
+3 -21
View File
@@ -634,8 +634,6 @@ procSuite "Waku Store":
for wakuMsg in msgList2:
# the pubsub topic should be DefaultTopic
await proto2.handleMessage(DefaultTopic, wakuMsg)
asyncTest "handle temporal history query with a valid time window":
var completionFut = newFuture[bool]()
@@ -686,22 +684,6 @@ procSuite "Waku Store":
check:
(await completionFut.withTimeout(5.seconds)) == true
test "find last seen message":
var
msgList = @[IndexedWakuMessage(msg: WakuMessage(payload: @[byte 0], contentTopic: ContentTopic("2"))),
IndexedWakuMessage(msg: WakuMessage(payload: @[byte 1],contentTopic: ContentTopic("1"), timestamp: float(1))),
IndexedWakuMessage(msg: WakuMessage(payload: @[byte 2],contentTopic: ContentTopic("2"), timestamp: float(2))),
IndexedWakuMessage(msg: WakuMessage(payload: @[byte 3],contentTopic: ContentTopic("1"), timestamp: float(3))),
IndexedWakuMessage(msg: WakuMessage(payload: @[byte 4],contentTopic: ContentTopic("2"), timestamp: float(4))),
IndexedWakuMessage(msg: WakuMessage(payload: @[byte 5],contentTopic: ContentTopic("1"), timestamp: float(9))),
IndexedWakuMessage(msg: WakuMessage(payload: @[byte 6],contentTopic: ContentTopic("2"), timestamp: float(6))),
IndexedWakuMessage(msg: WakuMessage(payload: @[byte 7],contentTopic: ContentTopic("1"), timestamp: float(7))),
IndexedWakuMessage(msg: WakuMessage(payload: @[byte 8],contentTopic: ContentTopic("2"), timestamp: float(8))),
IndexedWakuMessage(msg: WakuMessage(payload: @[byte 9],contentTopic: ContentTopic("1"),timestamp: float(5)))]
check:
findLastSeen(msgList) == float(9)
asyncTest "resume message history":
# starts a new node
var dialSwitch3 = newStandardSwitch()
@@ -808,15 +790,15 @@ procSuite "Waku Store":
let store = WakuStore.init(PeerManager.new(newStandardSwitch()), crypto.newRng(), capacity = capacity)
for i in 1..capacity:
await store.handleMessage(pubsubTopic, WakuMessage(payload: @[byte i], contentTopic: contentTopic))
await store.handleMessage(pubsubTopic, WakuMessage(payload: @[byte i], contentTopic: contentTopic, timestamp: i.float64))
await sleepAsync(1.millis) # Sleep a millisecond to ensure messages are stored chronologically
check:
store.messages.len == capacity # Store is at capacity
# Test that capacity holds
await store.handleMessage(pubsubTopic, WakuMessage(payload: @[byte (capacity + 1)], contentTopic: contentTopic))
await store.handleMessage(pubsubTopic, WakuMessage(payload: @[byte (capacity + 1)], contentTopic: contentTopic, timestamp: (capacity + 1).float64))
check:
store.messages.len == capacity # Store is still at capacity
store.messages.filterIt(it.msg.payload == @[byte (capacity + 1)]).len == 1 # Simple check to verify last added item is stored
store.messages.last().get().msg.payload == @[byte (capacity + 1)] # Simple check to verify last added item is stored
+298
View File
@@ -0,0 +1,298 @@
{.used.}
import
std/sequtils,
testutils/unittests,
../../waku/v2/protocol/waku_store/waku_store_types
procSuite "Sorted store queue":
# Helper functions
proc genIndexedWakuMessage(i: int8): IndexedWakuMessage =
## Use i to generate an IndexedWakuMessage
var data {.noinit.}: array[32, byte]
for x in data.mitems: x = i.byte
return IndexedWakuMessage(msg: WakuMessage(payload: @[byte i], timestamp: float64(i)),
index: Index(receiverTime: float64(i), senderTime: float64(i), digest: MDigest[256](data: data)))
# Test variables
let
capacity = 5
unsortedSet = [5,1,3,2,4]
var testStoreQueue = StoreQueueRef.new(capacity)
for i in unsortedSet:
discard testStoreQueue.add(genIndexedWakuMessage(i.int8))
test "Store queue can be created with limited capacity":
var stQ = StoreQueueRef.new(capacity)
check:
stQ.len == 0 # Empty when initialised
for i in 1..capacity: # Fill up the queue
check:
stQ.add(genIndexedWakuMessage(i.int8)).isOk()
check:
stQ.len == capacity
# Add one more. Capacity should not be exceeded.
check:
stQ.add(genIndexedWakuMessage(capacity.int8 + 1)).isOk()
check:
stQ.len == capacity
test "Store queue sort-on-insert works":
# Walk forward through the set and verify ascending order
var prevSmaller = genIndexedWakuMessage(min(unsortedSet).int8 - 1).index
for i in testStoreQueue.fwdIterator:
let (index, indexedWakuMessage) = i
check cmp(index, prevSmaller) > 0
prevSmaller = index
# Walk backward through the set and verify descending order
var prevLarger = genIndexedWakuMessage(max(unsortedSet).int8 + 1).index
for i in testStoreQueue.bwdIterator:
let (index, indexedWakuMessage) = i
check cmp(index, prevLarger) < 0
prevLarger = index
test "Can access first item from store queue":
let first = testStoreQueue.first()
check:
first.isOk()
first.get().msg.timestamp == 1.0
# Error condition
let emptyQ = StoreQueueRef.new(capacity)
check:
emptyQ.first().isErr()
test "Can access last item from store queue":
let last = testStoreQueue.last()
check:
last.isOk()
last.get().msg.timestamp == 5.0
# Error condition
let emptyQ = StoreQueueRef.new(capacity)
check:
emptyQ.last().isErr()
test "Store queue forward pagination works":
proc predicate(i: IndexedWakuMessage): bool = true # no filtering
var (res, pInfo, err) = testStoreQueue.getPage(predicate,
PagingInfo(pageSize: 3,
direction: PagingDirection.FORWARD))
check:
# First page
pInfo.pageSize == 3
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == 3.0
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[1,2,3]
(res, pInfo, err) = testStoreQueue.getPage(predicate,
pInfo)
check:
# Second page
pInfo.pageSize == 2
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == 5.0
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[4,5]
(res, pInfo, err) = testStoreQueue.getPage(predicate,
pInfo)
check:
# Empty last page
pInfo.pageSize == 0
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == 5.0
err == HistoryResponseError.NONE
res.len == 0
test "Store queue backward pagination works":
proc predicate(i: IndexedWakuMessage): bool = true # no filtering
var (res, pInfo, err) = testStoreQueue.getPage(predicate,
PagingInfo(pageSize: 3,
direction: PagingDirection.BACKWARD))
check:
# First page
pInfo.pageSize == 3
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == 3.0
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[3,4,5]
(res, pInfo, err) = testStoreQueue.getPage(predicate,
pInfo)
check:
# Second page
pInfo.pageSize == 2
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == 1.0
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[1,2]
(res, pInfo, err) = testStoreQueue.getPage(predicate,
pInfo)
check:
# Empty last page
pInfo.pageSize == 0
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == 1.0
err == HistoryResponseError.NONE
res.len == 0
test "Store queue pagination works with predicate":
proc onlyEvenTimes(i: IndexedWakuMessage): bool = i.msg.timestamp.int64 mod 2 == 0
proc onlyOddTimes(i: IndexedWakuMessage): bool = i.msg.timestamp.int64 mod 2 != 0
## Forward pagination: only even timestamped messages
var (res, pInfo, err) = testStoreQueue.getPage(onlyEvenTimes,
PagingInfo(pageSize: 2,
direction: PagingDirection.FORWARD))
check:
# First page
pInfo.pageSize == 2
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == 4.0
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[2,4]
(res, pInfo, err) = testStoreQueue.getPage(onlyEvenTimes,
pInfo)
check:
# Empty next page
pInfo.pageSize == 0
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == 4.0
err == HistoryResponseError.NONE
res.len == 0
## Backward pagination: only odd timestamped messages
(res, pInfo, err) = testStoreQueue.getPage(onlyOddTimes,
PagingInfo(pageSize: 2,
direction: PagingDirection.BACKWARD))
check:
# First page
pInfo.pageSize == 2
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == 3.0
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[3,5]
(res, pInfo, err) = testStoreQueue.getPage(onlyOddTimes,
pInfo)
check:
# Next page
pInfo.pageSize == 1
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == 1.0
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[1]
(res, pInfo, err) = testStoreQueue.getPage(onlyOddTimes,
pInfo)
check:
# Empty last page
pInfo.pageSize == 0
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == 1.0
err == HistoryResponseError.NONE
res.len == 0
test "Store queue pagination handles invalid cursor":
proc predicate(i: IndexedWakuMessage): bool = true # no filtering
# Invalid cursor in backwards direction
var (res, pInfo, err) = testStoreQueue.getPage(predicate,
PagingInfo(pageSize: 3,
cursor: Index(receiverTime: float64(3), senderTime: float64(3), digest: MDigest[256]()),
direction: PagingDirection.BACKWARD))
check:
# Empty response with error
pInfo.pageSize == 0
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == 3.0
err == HistoryResponseError.INVALID_CURSOR
res.len == 0
# Same test, but forward direction
(res, pInfo, err) = testStoreQueue.getPage(predicate,
PagingInfo(pageSize: 3,
cursor: Index(receiverTime: float64(3), senderTime: float64(3), digest: MDigest[256]()),
direction: PagingDirection.FORWARD))
check:
# Empty response with error
pInfo.pageSize == 0
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == 3.0
err == HistoryResponseError.INVALID_CURSOR
res.len == 0
test "Store queue pagination works on empty list":
var stQ = StoreQueueRef.new(capacity)
check:
stQ.len == 0 # Empty when initialised
proc predicate(i: IndexedWakuMessage): bool = true # no filtering
# Get page from empty queue in bwd dir
var (res, pInfo, err) = stQ.getPage(predicate,
PagingInfo(pageSize: 3,
direction: PagingDirection.BACKWARD))
check:
# Empty response
pInfo.pageSize == 0
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == 0.0
err == HistoryResponseError.NONE
res.len == 0
# Get page from empty queue in fwd dir
(res, pInfo, err) = stQ.getPage(predicate,
PagingInfo(pageSize: 3,
direction: PagingDirection.FORWARD))
check:
# Empty response
pInfo.pageSize == 0
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == 0.0
err == HistoryResponseError.NONE
res.len == 0
test "Can verify if store queue contains an index":
let
existingIndex = genIndexedWakuMessage(4).index
nonExistingIndex = genIndexedWakuMessage(99).index
check:
testStoreQueue.contains(existingIndex) == true
testStoreQueue.contains(nonExistingIndex) == false
+1 -1
View File
@@ -1149,7 +1149,7 @@ procSuite "WakuNode":
let index1 = computeIndex(msg1)
let output1 = store.put(index1, msg1, DefaultTopic)
check output1.isOk
node1.wakuStore.messages.add(IndexedWakuMessage(msg: msg1, index: index1, pubsubTopic: DefaultTopic))
discard node1.wakuStore.messages.add(IndexedWakuMessage(msg: msg1, index: index1, pubsubTopic: DefaultTopic))
# now run the resume proc
await node1.resume()