Sasha f3627c46a4
feat!: use ShardingParams on subscriptions, make Decoder/Encoder auto sharding friendly by default (#1958)
* fix: use pubsubTopic from current ones if not set

* fix: improve type on dial method

* enforce same pubusb on filter.subscribe, make content topic to pubsub mapping default for decoder / encoder

* fix mapping problem

* update tests

* add error handling

* fix typo

* up lock

* rm lock

* up lock

* remove only

* fix content topic

* fix ephemeral test

* fix filter unsubscribe test

* up utils

* fix subscribe test

* up interfaces and filter api

* remove only

* up ping test

* fix subscribe test

* fix push test

* fix lightPush

* fix multiple pubsub

* remove only, fix subscribe filter test

* remove only

* fix cluster ID selection and named sharding subscription test

* fix unsubscribe test

* fix light push test

* fix light push test

* fix push test

* fix relay publish

* create runNode and fix relay tests

* generalize runNodes, fix some tests

* fix store tests

* fix toAsyncIterator tests

* remove only

* fix lightPush

* use generics

* try fix test

* run failing tests

* remove only

* address failed tests, remove DefaultPubsubTopic dependency in some tests
2024-04-28 11:15:17 +02:00

217 lines
6.3 KiB
TypeScript

import { DecodedMessage } from "@waku/core";
import type { LightNode } from "@waku/interfaces";
import { bytesToUtf8 } from "@waku/utils/bytes";
import { expect } from "chai";
import {
afterEachCustom,
beforeEachCustom,
ServiceNode,
tearDownNodes
} from "../../src/index.js";
import {
runStoreNodes,
sendMessages,
startAndConnectLightNode,
TestDecoder,
TestDecoder2,
TestShardInfo,
totalMsgs
} from "./utils.js";
describe("Waku Store, cursor", function () {
this.timeout(15000);
let waku: LightNode;
let waku2: LightNode;
let nwaku: ServiceNode;
beforeEachCustom(this, async () => {
[nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo);
});
afterEachCustom(this, async () => {
await tearDownNodes(nwaku, [waku, waku2]);
});
[
[2, 4],
[0, 20],
[10, 40],
[19, 20],
[19, 50],
[110, 120]
].forEach(([cursorIndex, messageCount]) => {
it(`Passing a valid cursor at ${cursorIndex} index when there are ${messageCount} messages`, async function () {
await sendMessages(
nwaku,
messageCount,
TestDecoder.contentTopic,
TestDecoder.pubsubTopic
);
// messages in reversed order (first message at last index)
const messages: DecodedMessage[] = [];
for await (const page of waku.store.queryGenerator([TestDecoder])) {
for await (const msg of page.reverse()) {
messages.push(msg as DecodedMessage);
}
}
// create cursor to extract messages after the cursorIndex
const cursor = waku.store.createCursor(messages[cursorIndex]);
const messagesAfterCursor: DecodedMessage[] = [];
for await (const page of waku.store.queryGenerator([TestDecoder], {
cursor
})) {
for await (const msg of page.reverse()) {
if (msg) {
messagesAfterCursor.push(msg as DecodedMessage);
}
}
}
expect(messages.length).be.eql(messageCount);
expect(messagesAfterCursor.length).be.eql(messageCount - cursorIndex - 1);
if (cursorIndex == messages.length - 1) {
// in this case the cursor will return nothin because it points at the end of the list
expect(messagesAfterCursor).be.eql([]);
} else {
expect(bytesToUtf8(messagesAfterCursor[0].payload)).to.be.eq(
bytesToUtf8(messages[cursorIndex + 1].payload)
);
expect(
bytesToUtf8(
messagesAfterCursor[messagesAfterCursor.length - 1].payload
)
).to.be.eq(bytesToUtf8(messages[messages.length - 1].payload));
}
});
});
it("Reusing cursor across nodes", async function () {
await sendMessages(
nwaku,
totalMsgs,
TestDecoder.contentTopic,
TestDecoder.pubsubTopic
);
waku2 = await startAndConnectLightNode(nwaku, TestShardInfo);
// messages in reversed order (first message at last index)
const messages: DecodedMessage[] = [];
for await (const page of waku.store.queryGenerator([TestDecoder])) {
for await (const msg of page.reverse()) {
messages.push(msg as DecodedMessage);
}
}
// create cursor to extract messages after the cursorIndex
const cursor = waku.store.createCursor(messages[5]);
// query node2 with the cursor from node1
const messagesAfterCursor: DecodedMessage[] = [];
for await (const page of waku2.store.queryGenerator([TestDecoder], {
cursor
})) {
for await (const msg of page.reverse()) {
if (msg) {
messagesAfterCursor.push(msg as DecodedMessage);
}
}
}
expect(messages.length).be.eql(totalMsgs);
expect(messagesAfterCursor.length).be.eql(totalMsgs - 6);
expect(bytesToUtf8(messagesAfterCursor[0].payload)).to.be.eq(
bytesToUtf8(messages[6].payload)
);
expect(
bytesToUtf8(messagesAfterCursor[messagesAfterCursor.length - 1].payload)
).to.be.eq(bytesToUtf8(messages[messages.length - 1].payload));
});
it("Passing cursor with wrong message digest", async function () {
await sendMessages(
nwaku,
totalMsgs,
TestDecoder.contentTopic,
TestDecoder.pubsubTopic
);
const messages: DecodedMessage[] = [];
for await (const page of waku.store.queryGenerator([TestDecoder])) {
for await (const msg of page.reverse()) {
messages.push(msg as DecodedMessage);
}
}
const cursor = waku.store.createCursor(messages[5]);
// setting a wrong digest
cursor.digest = new Uint8Array([]);
const messagesAfterCursor: DecodedMessage[] = [];
try {
for await (const page of waku.store.queryGenerator([TestDecoder], {
cursor
})) {
for await (const msg of page.reverse()) {
if (msg) {
messagesAfterCursor.push(msg as DecodedMessage);
}
}
}
// Should return same as go-waku. Raised bug: https://github.com/waku-org/nwaku/issues/2117
expect(messagesAfterCursor.length).to.eql(0);
} catch (error) {
if (
nwaku.type === "go-waku" &&
typeof error === "string" &&
error.includes("History response contains an Error: INVALID_CURSOR")
) {
return;
}
throw error instanceof Error
? new Error(`Unexpected error: ${error.message}`)
: error;
}
});
it("Passing cursor with wrong pubsubTopic", async function () {
await sendMessages(
nwaku,
totalMsgs,
TestDecoder.contentTopic,
TestDecoder.pubsubTopic
);
const messages: DecodedMessage[] = [];
for await (const page of waku.store.queryGenerator([TestDecoder])) {
for await (const msg of page.reverse()) {
messages.push(msg as DecodedMessage);
}
}
messages[5].pubsubTopic = TestDecoder2.pubsubTopic;
const cursor = waku.store.createCursor(messages[5]);
try {
for await (const page of waku.store.queryGenerator([TestDecoder], {
cursor
})) {
void page;
}
throw new Error("Cursor with wrong pubsubtopic was accepted");
} catch (err) {
if (
!(err instanceof Error) ||
!err.message.includes(
`Cursor pubsub topic (${TestDecoder2.pubsubTopic}) does not match decoder pubsub topic (${TestDecoder.pubsubTopic})`
)
) {
throw err;
}
}
});
});