@river-build/sdk
Version:
For more details, visit the following resources:
161 lines • 7.68 kB
JavaScript
/**
*/
import { MembershipOp } from '@river-build/proto';
import { setTimeout } from 'timers/promises';
import { dlog } from '@river-build/dlog';
import { makeUniqueChannelStreamId, makeUserStreamId, streamIdFromBytes, streamIdToBytes, userIdFromAddress, } from '../../id';
import { makeEvent, unpackStream, unpackStreamEnvelopes } from '../../sign';
import { getChannelUpdatePayload, getMessagePayload, make_ChannelPayload_Inception, make_ChannelPayload_Message, make_MemberPayload_Membership2, make_SpacePayload_Inception, make_UserPayload_Inception, } from '../../types';
import { TEST_ENCRYPTED_MESSAGE_PROPS, lastEventFiltered, makeRandomUserContext, makeTestRpcClient, makeUniqueSpaceStreamId, } from '../testUtils';
const log = dlog('csb:test:nodeRestart');
describe.skip('nodeRestart', () => {
let bobsContext;
beforeEach(async () => {
bobsContext = await makeRandomUserContext();
});
// TODO: HNT-2611 fix and re-enable
test('bobCanChatAfterRestart', async () => {
log('start');
const bob = await makeTestRpcClient();
const bobsUserId = userIdFromAddress(bobsContext.creatorAddress);
const bobsUserStreamIdStr = makeUserStreamId(bobsUserId);
const bobsUserStreamId = streamIdToBytes(bobsUserStreamIdStr);
await bob.createStream({
events: [
await makeEvent(bobsContext, make_UserPayload_Inception({
streamId: bobsUserStreamId,
})),
],
streamId: bobsUserStreamId,
});
log('Bob created user, about to create space');
// Bob creates space and channel
const spacedStreamIdStr = makeUniqueSpaceStreamId();
const spacedStreamId = streamIdToBytes(spacedStreamIdStr);
const spaceInceptionEvent = await makeEvent(bobsContext, make_SpacePayload_Inception({
streamId: spacedStreamId,
}));
await bob.createStream({
events: [
spaceInceptionEvent,
await makeEvent(bobsContext, make_MemberPayload_Membership2({
userId: bobsUserId,
op: MembershipOp.SO_JOIN,
initiatorId: bobsUserId,
})),
],
streamId: spacedStreamId,
});
const { channelId } = await createNewChannelAndPostHello(bobsContext, spacedStreamId, bobsUserId, bob);
log('Restarting node');
await expect(bob.info({ debug: ['exit'] })).resolves.not.toThrow();
log('Waiting a bit');
await setTimeout(1000);
for (;;) {
log('Trying to connect');
try {
await bob.info({});
break;
}
catch (e) {
log('Failed to connect, retrying', 'error=', e);
await setTimeout(100);
}
}
log('Connected again, node restarted');
log('Reading back the channel, looking for hello');
await expect(getStreamAndExpectHello(bob, channelId)).resolves.not.toThrow();
log('Creating another channel, post hello');
const { channelId: channelId2 } = await createNewChannelAndPostHello(bobsContext, spacedStreamId, bobsUserId, bob);
await expect(getStreamAndExpectHello(bob, channelId2)).resolves.not.toThrow();
await countStreamBlocksAndSnapshots(bob, bobsUserStreamId);
await countStreamBlocksAndSnapshots(bob, spacedStreamId);
await countStreamBlocksAndSnapshots(bob, channelId);
await countStreamBlocksAndSnapshots(bob, channelId2);
log('done');
});
});
const createNewChannelAndPostHello = async (bobsContext, spacedStreamId, bobsUserId, bob) => {
const channelIdStr = makeUniqueChannelStreamId(streamIdFromBytes(spacedStreamId));
const channelId = streamIdToBytes(channelIdStr);
const channelInceptionEvent = await makeEvent(bobsContext, make_ChannelPayload_Inception({
streamId: channelId,
spaceId: spacedStreamId,
}));
const channelJoinEvent = await makeEvent(bobsContext, make_MemberPayload_Membership2({
userId: bobsUserId,
op: MembershipOp.SO_JOIN,
initiatorId: bobsUserId,
}));
const channelEvents = [channelInceptionEvent, channelJoinEvent];
log('creating channel with events=', channelEvents);
await bob.createStream({
events: channelEvents,
streamId: channelId,
});
log('Bob created channel, reads it back');
const channel = await bob.getStream({ streamId: channelId });
expect(channel).toBeDefined();
expect(channel.stream).toBeDefined();
expect(channel.stream?.nextSyncCookie?.streamId).toEqual(channelId);
let nextHash = channel.stream?.miniblocks.at(-1)?.header?.hash;
expect(nextHash).toBeDefined();
// Now there must be "channel created" event in the space stream.
const spaceResponse = await bob.getStream({ streamId: spacedStreamId });
const channelCreatePayload = lastEventFiltered(await unpackStreamEnvelopes(spaceResponse.stream, undefined), getChannelUpdatePayload);
expect(channelCreatePayload).toBeDefined();
expect(channelCreatePayload?.channelId).toEqual(channelId);
// Post 1000 hellos to the channel
for (let i = 0; i < 1000; i++) {
const e = await makeEvent(bobsContext, make_ChannelPayload_Message({
...TEST_ENCRYPTED_MESSAGE_PROPS,
ciphertext: `hello ${i}`,
}), nextHash);
await expect(bob.addEvent({
streamId: channelId,
event: e,
})).resolves.not.toThrow();
nextHash = (await bob.getLastMiniblockHash({ streamId: channelId })).hash;
}
// Post just hello to the channel
const helloEvent = await makeEvent(bobsContext, make_ChannelPayload_Message({
...TEST_ENCRYPTED_MESSAGE_PROPS,
ciphertext: 'hello',
}), nextHash);
const lastHash = (await bob.getLastMiniblockHash({ streamId: channelId })).hash;
await expect(bob.addEvent({
streamId: channelId,
event: helloEvent,
})).resolves.not.toThrow();
return { channelId, lastHash };
};
const getStreamAndExpectHello = async (bob, channelId) => {
const channel2 = await bob.getStream({ streamId: channelId });
expect(channel2).toBeDefined();
expect(channel2.stream).toBeDefined();
expect(channel2.stream?.nextSyncCookie?.streamId).toEqual(channelId);
const hello = lastEventFiltered(await unpackStreamEnvelopes(channel2.stream, undefined), getMessagePayload);
expect(hello).toBeDefined();
expect(hello?.ciphertext).toEqual('hello');
};
const countStreamBlocksAndSnapshots = async (bob, streamId) => {
const response = await bob.getStream({ streamId: streamId });
expect(response).toBeDefined();
expect(response.stream).toBeDefined();
expect(response.stream?.nextSyncCookie?.streamId).toEqual(streamId);
const stream = await unpackStream(response.stream, undefined);
const minipoolEventNum = stream.streamAndCookie.events.length;
let totalEvents = minipoolEventNum;
const miniblocks = stream.streamAndCookie.miniblocks.length;
let snapshots = 0;
for (const mb of stream.streamAndCookie.miniblocks) {
expect(mb.header).toBeDefined();
totalEvents += mb.events.length;
if (mb.header?.snapshot !== undefined) {
snapshots++;
}
}
log('Counted snapshots', 'streamId=', streamId, 'miniblocks=', miniblocks, 'snapshots=', snapshots, 'minipoolEventNum=', minipoolEventNum, 'totalEvents=', totalEvents);
return { miniblocks, snapshots, minipoolEventNum, totalEvents };
};
//# sourceMappingURL=restart.test.js.map