You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-07-31 15:24:23 +03:00
refactor: sliding sync: swap to lists-as-keys (#3076)
* refactor: sliding sync: swap to lists-as-keys Update the request/response API shape to match the latest MSC3575 version, which converts `lists` from being an array of list objects to being a map of list objects. * Linting * prettier * add extra setListRanges test * Default to right type
This commit is contained in:
@ -52,10 +52,9 @@ describe("SlidingSyncSdk", () => {
|
|||||||
const selfAccessToken = "aseukfgwef";
|
const selfAccessToken = "aseukfgwef";
|
||||||
|
|
||||||
const mockifySlidingSync = (s: SlidingSync): SlidingSync => {
|
const mockifySlidingSync = (s: SlidingSync): SlidingSync => {
|
||||||
s.getList = jest.fn();
|
s.getListParams = jest.fn();
|
||||||
s.getListData = jest.fn();
|
s.getListData = jest.fn();
|
||||||
s.getRoomSubscriptions = jest.fn();
|
s.getRoomSubscriptions = jest.fn();
|
||||||
s.listLength = jest.fn();
|
|
||||||
s.modifyRoomSubscriptionInfo = jest.fn();
|
s.modifyRoomSubscriptionInfo = jest.fn();
|
||||||
s.modifyRoomSubscriptions = jest.fn();
|
s.modifyRoomSubscriptions = jest.fn();
|
||||||
s.registerExtension = jest.fn();
|
s.registerExtension = jest.fn();
|
||||||
@ -115,7 +114,7 @@ describe("SlidingSyncSdk", () => {
|
|||||||
const testClient = new TestClient(selfUserId, "DEVICE", selfAccessToken);
|
const testClient = new TestClient(selfUserId, "DEVICE", selfAccessToken);
|
||||||
httpBackend = testClient.httpBackend;
|
httpBackend = testClient.httpBackend;
|
||||||
client = testClient.client;
|
client = testClient.client;
|
||||||
mockSlidingSync = mockifySlidingSync(new SlidingSync("", [], {}, client, 0));
|
mockSlidingSync = mockifySlidingSync(new SlidingSync("", new Map(), {}, client, 0));
|
||||||
if (testOpts.withCrypto) {
|
if (testOpts.withCrypto) {
|
||||||
httpBackend!.when("GET", "/room_keys/version").respond(404, {});
|
httpBackend!.when("GET", "/room_keys/version").respond(404, {});
|
||||||
await client!.initCrypto();
|
await client!.initCrypto();
|
||||||
@ -549,7 +548,7 @@ describe("SlidingSyncSdk", () => {
|
|||||||
it("emits SyncState.Reconnecting when < FAILED_SYNC_ERROR_THRESHOLD & SyncState.Error when over", async () => {
|
it("emits SyncState.Reconnecting when < FAILED_SYNC_ERROR_THRESHOLD & SyncState.Error when over", async () => {
|
||||||
mockSlidingSync!.emit(SlidingSyncEvent.Lifecycle, SlidingSyncState.Complete, {
|
mockSlidingSync!.emit(SlidingSyncEvent.Lifecycle, SlidingSyncState.Complete, {
|
||||||
pos: "h",
|
pos: "h",
|
||||||
lists: [],
|
lists: {},
|
||||||
rooms: {},
|
rooms: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
});
|
});
|
||||||
@ -577,7 +576,7 @@ describe("SlidingSyncSdk", () => {
|
|||||||
it("emits SyncState.Syncing after a previous SyncState.Error", async () => {
|
it("emits SyncState.Syncing after a previous SyncState.Error", async () => {
|
||||||
mockSlidingSync!.emit(SlidingSyncEvent.Lifecycle, SlidingSyncState.Complete, {
|
mockSlidingSync!.emit(SlidingSyncEvent.Lifecycle, SlidingSyncState.Complete, {
|
||||||
pos: "i",
|
pos: "i",
|
||||||
lists: [],
|
lists: {},
|
||||||
rooms: {},
|
rooms: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
});
|
});
|
||||||
|
@ -64,10 +64,10 @@ describe("SlidingSync", () => {
|
|||||||
let slidingSync: SlidingSync;
|
let slidingSync: SlidingSync;
|
||||||
|
|
||||||
it("should start the sync loop upon calling start()", async () => {
|
it("should start the sync loop upon calling start()", async () => {
|
||||||
slidingSync = new SlidingSync(proxyBaseUrl, [], {}, client!, 1);
|
slidingSync = new SlidingSync(proxyBaseUrl, new Map(), {}, client!, 1);
|
||||||
const fakeResp = {
|
const fakeResp = {
|
||||||
pos: "a",
|
pos: "a",
|
||||||
lists: [],
|
lists: {},
|
||||||
rooms: {},
|
rooms: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
};
|
};
|
||||||
@ -90,7 +90,7 @@ describe("SlidingSync", () => {
|
|||||||
|
|
||||||
it("should reset the connection on HTTP 400 and send everything again", async () => {
|
it("should reset the connection on HTTP 400 and send everything again", async () => {
|
||||||
// seed the connection with some lists, extensions and subscriptions to verify they are sent again
|
// seed the connection with some lists, extensions and subscriptions to verify they are sent again
|
||||||
slidingSync = new SlidingSync(proxyBaseUrl, [], {}, client!, 1);
|
slidingSync = new SlidingSync(proxyBaseUrl, new Map(), {}, client!, 1);
|
||||||
const roomId = "!sub:localhost";
|
const roomId = "!sub:localhost";
|
||||||
const subInfo = {
|
const subInfo = {
|
||||||
timeline_limit: 42,
|
timeline_limit: 42,
|
||||||
@ -114,7 +114,7 @@ describe("SlidingSync", () => {
|
|||||||
};
|
};
|
||||||
slidingSync.modifyRoomSubscriptions(new Set([roomId]));
|
slidingSync.modifyRoomSubscriptions(new Set([roomId]));
|
||||||
slidingSync.modifyRoomSubscriptionInfo(subInfo);
|
slidingSync.modifyRoomSubscriptionInfo(subInfo);
|
||||||
slidingSync.setList(0, listInfo);
|
slidingSync.setList("a", listInfo);
|
||||||
slidingSync.registerExtension(ext);
|
slidingSync.registerExtension(ext);
|
||||||
slidingSync.start();
|
slidingSync.start();
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ describe("SlidingSync", () => {
|
|||||||
expect(body.room_subscriptions).toEqual({
|
expect(body.room_subscriptions).toEqual({
|
||||||
[roomId]: subInfo,
|
[roomId]: subInfo,
|
||||||
});
|
});
|
||||||
expect(body.lists[0]).toEqual(listInfo);
|
expect(body.lists["a"]).toEqual(listInfo);
|
||||||
expect(body.extensions).toBeTruthy();
|
expect(body.extensions).toBeTruthy();
|
||||||
expect(body.extensions["custom_extension"]).toEqual({ initial: true });
|
expect(body.extensions["custom_extension"]).toEqual({ initial: true });
|
||||||
expect(req.queryParams!["pos"]).toBeUndefined();
|
expect(req.queryParams!["pos"]).toBeUndefined();
|
||||||
@ -137,7 +137,7 @@ describe("SlidingSync", () => {
|
|||||||
.respond(200, function () {
|
.respond(200, function () {
|
||||||
return {
|
return {
|
||||||
pos: "11",
|
pos: "11",
|
||||||
lists: [{ count: 5 }],
|
lists: { a: { count: 5 } },
|
||||||
extensions: {},
|
extensions: {},
|
||||||
txn_id: txnId,
|
txn_id: txnId,
|
||||||
};
|
};
|
||||||
@ -151,7 +151,7 @@ describe("SlidingSync", () => {
|
|||||||
const body = req.data;
|
const body = req.data;
|
||||||
logger.debug("got ", body);
|
logger.debug("got ", body);
|
||||||
expect(body.room_subscriptions).toBeFalsy();
|
expect(body.room_subscriptions).toBeFalsy();
|
||||||
expect(body.lists[0]).toEqual({
|
expect(body.lists["a"]).toEqual({
|
||||||
ranges: [[0, 10]],
|
ranges: [[0, 10]],
|
||||||
});
|
});
|
||||||
expect(body.extensions).toBeTruthy();
|
expect(body.extensions).toBeTruthy();
|
||||||
@ -161,7 +161,7 @@ describe("SlidingSync", () => {
|
|||||||
.respond(200, function () {
|
.respond(200, function () {
|
||||||
return {
|
return {
|
||||||
pos: "12",
|
pos: "12",
|
||||||
lists: [{ count: 5 }],
|
lists: { a: { count: 5 } },
|
||||||
extensions: {},
|
extensions: {},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -185,7 +185,7 @@ describe("SlidingSync", () => {
|
|||||||
expect(body.room_subscriptions).toEqual({
|
expect(body.room_subscriptions).toEqual({
|
||||||
[roomId]: subInfo,
|
[roomId]: subInfo,
|
||||||
});
|
});
|
||||||
expect(body.lists[0]).toEqual(listInfo);
|
expect(body.lists["a"]).toEqual(listInfo);
|
||||||
expect(body.extensions).toBeTruthy();
|
expect(body.extensions).toBeTruthy();
|
||||||
expect(body.extensions["custom_extension"]).toEqual({ initial: true });
|
expect(body.extensions["custom_extension"]).toEqual({ initial: true });
|
||||||
expect(req.queryParams!["pos"]).toBeUndefined();
|
expect(req.queryParams!["pos"]).toBeUndefined();
|
||||||
@ -193,7 +193,7 @@ describe("SlidingSync", () => {
|
|||||||
.respond(200, function () {
|
.respond(200, function () {
|
||||||
return {
|
return {
|
||||||
pos: "1",
|
pos: "1",
|
||||||
lists: [{ count: 6 }],
|
lists: { a: { count: 6 } },
|
||||||
extensions: {},
|
extensions: {},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -221,7 +221,7 @@ describe("SlidingSync", () => {
|
|||||||
|
|
||||||
it("should be able to subscribe to a room", async () => {
|
it("should be able to subscribe to a room", async () => {
|
||||||
// add the subscription
|
// add the subscription
|
||||||
slidingSync = new SlidingSync(proxyBaseUrl, [], roomSubInfo, client!, 1);
|
slidingSync = new SlidingSync(proxyBaseUrl, new Map(), roomSubInfo, client!, 1);
|
||||||
slidingSync.modifyRoomSubscriptions(new Set([roomId]));
|
slidingSync.modifyRoomSubscriptions(new Set([roomId]));
|
||||||
httpBackend!
|
httpBackend!
|
||||||
.when("POST", syncUrl)
|
.when("POST", syncUrl)
|
||||||
@ -233,7 +233,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "a",
|
pos: "a",
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {
|
rooms: {
|
||||||
[roomId]: wantRoomData,
|
[roomId]: wantRoomData,
|
||||||
@ -266,7 +266,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "a",
|
pos: "a",
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {
|
rooms: {
|
||||||
[roomId]: wantRoomData,
|
[roomId]: wantRoomData,
|
||||||
@ -313,7 +313,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {
|
rooms: {
|
||||||
[anotherRoomID]: anotherRoomData,
|
[anotherRoomID]: anotherRoomData,
|
||||||
@ -344,7 +344,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [],
|
lists: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
const p = listenUntil(slidingSync, "SlidingSync.Lifecycle", (state) => {
|
const p = listenUntil(slidingSync, "SlidingSync.Lifecycle", (state) => {
|
||||||
@ -402,19 +402,19 @@ describe("SlidingSync", () => {
|
|||||||
is_dm: true,
|
is_dm: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
slidingSync = new SlidingSync(proxyBaseUrl, [listReq], {}, client!, 1);
|
slidingSync = new SlidingSync(proxyBaseUrl, new Map([["a", listReq]]), {}, client!, 1);
|
||||||
httpBackend!
|
httpBackend!
|
||||||
.when("POST", syncUrl)
|
.when("POST", syncUrl)
|
||||||
.check(function (req) {
|
.check(function (req) {
|
||||||
const body = req.data;
|
const body = req.data;
|
||||||
logger.log("list", body);
|
logger.log("list", body);
|
||||||
expect(body.lists).toBeTruthy();
|
expect(body.lists).toBeTruthy();
|
||||||
expect(body.lists[0]).toEqual(listReq);
|
expect(body.lists["a"]).toEqual(listReq);
|
||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "a",
|
pos: "a",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 500,
|
count: 500,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -424,7 +424,7 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
rooms: rooms,
|
rooms: rooms,
|
||||||
});
|
});
|
||||||
const listenerData: Record<string, MSC3575RoomData> = {};
|
const listenerData: Record<string, MSC3575RoomData> = {};
|
||||||
@ -444,15 +444,14 @@ describe("SlidingSync", () => {
|
|||||||
expect(listenerData[roomB]).toEqual(rooms[roomB]);
|
expect(listenerData[roomB]).toEqual(rooms[roomB]);
|
||||||
expect(listenerData[roomC]).toEqual(rooms[roomC]);
|
expect(listenerData[roomC]).toEqual(rooms[roomC]);
|
||||||
|
|
||||||
expect(slidingSync.listLength()).toEqual(1);
|
|
||||||
slidingSync.off(SlidingSyncEvent.RoomData, dataListener);
|
slidingSync.off(SlidingSyncEvent.RoomData, dataListener);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be possible to retrieve list data", () => {
|
it("should be possible to retrieve list data", () => {
|
||||||
expect(slidingSync.getList(0)).toBeDefined();
|
expect(slidingSync.getListParams("a")).toBeDefined();
|
||||||
expect(slidingSync.getList(5)).toBeNull();
|
expect(slidingSync.getListParams("b")).toBeNull();
|
||||||
expect(slidingSync.getListData(5)).toBeNull();
|
expect(slidingSync.getListData("b")).toBeNull();
|
||||||
const syncData = slidingSync.getListData(0)!;
|
const syncData = slidingSync.getListData("a")!;
|
||||||
expect(syncData.joinedCount).toEqual(500); // from previous test
|
expect(syncData.joinedCount).toEqual(500); // from previous test
|
||||||
expect(syncData.roomIndexToRoomId).toEqual({
|
expect(syncData.roomIndexToRoomId).toEqual({
|
||||||
0: roomA,
|
0: roomA,
|
||||||
@ -467,17 +466,17 @@ describe("SlidingSync", () => {
|
|||||||
.when("POST", syncUrl)
|
.when("POST", syncUrl)
|
||||||
.check(function (req) {
|
.check(function (req) {
|
||||||
const body = req.data;
|
const body = req.data;
|
||||||
logger.log("next ranges", body.lists[0].ranges);
|
logger.log("next ranges", body.lists["a"].ranges);
|
||||||
expect(body.lists).toBeTruthy();
|
expect(body.lists).toBeTruthy();
|
||||||
expect(body.lists[0]).toEqual({
|
expect(body.lists["a"]).toEqual({
|
||||||
// only the ranges should be sent as the rest are unchanged and sticky
|
// only the ranges should be sent as the rest are unchanged and sticky
|
||||||
ranges: newRanges,
|
ranges: newRanges,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 500,
|
count: 500,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -487,15 +486,17 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const responseProcessed = listenUntil(slidingSync, "SlidingSync.Lifecycle", (state) => {
|
const responseProcessed = listenUntil(slidingSync, "SlidingSync.Lifecycle", (state) => {
|
||||||
return state === SlidingSyncState.RequestFinished;
|
return state === SlidingSyncState.RequestFinished;
|
||||||
});
|
});
|
||||||
slidingSync.setListRanges(0, newRanges);
|
slidingSync.setListRanges("a", newRanges);
|
||||||
await httpBackend!.flushAllExpected();
|
await httpBackend!.flushAllExpected();
|
||||||
await responseProcessed;
|
await responseProcessed;
|
||||||
|
// setListRanges for an invalid list key returns an error
|
||||||
|
await expect(slidingSync.setListRanges("idontexist", newRanges)).rejects.toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be possible to add an extra list", async () => {
|
it("should be possible to add an extra list", async () => {
|
||||||
@ -513,19 +514,19 @@ describe("SlidingSync", () => {
|
|||||||
const body = req.data;
|
const body = req.data;
|
||||||
logger.log("extra list", body);
|
logger.log("extra list", body);
|
||||||
expect(body.lists).toBeTruthy();
|
expect(body.lists).toBeTruthy();
|
||||||
expect(body.lists[0]).toEqual({
|
expect(body.lists["a"]).toEqual({
|
||||||
// only the ranges should be sent as the rest are unchanged and sticky
|
// only the ranges should be sent as the rest are unchanged and sticky
|
||||||
ranges: newRanges,
|
ranges: newRanges,
|
||||||
});
|
});
|
||||||
expect(body.lists[1]).toEqual(extraListReq);
|
expect(body.lists["b"]).toEqual(extraListReq);
|
||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "c",
|
pos: "c",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 500,
|
count: 500,
|
||||||
},
|
},
|
||||||
{
|
b: {
|
||||||
count: 50,
|
count: 50,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -535,10 +536,10 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
listenUntil(slidingSync, "SlidingSync.List", (listIndex, joinedCount, roomIndexToRoomId) => {
|
listenUntil(slidingSync, "SlidingSync.List", (listKey, joinedCount, roomIndexToRoomId) => {
|
||||||
expect(listIndex).toEqual(1);
|
expect(listKey).toEqual("b");
|
||||||
expect(joinedCount).toEqual(50);
|
expect(joinedCount).toEqual(50);
|
||||||
expect(roomIndexToRoomId).toEqual({
|
expect(roomIndexToRoomId).toEqual({
|
||||||
0: roomA,
|
0: roomA,
|
||||||
@ -550,7 +551,7 @@ describe("SlidingSync", () => {
|
|||||||
const responseProcessed = listenUntil(slidingSync, "SlidingSync.Lifecycle", (state) => {
|
const responseProcessed = listenUntil(slidingSync, "SlidingSync.Lifecycle", (state) => {
|
||||||
return state === SlidingSyncState.Complete;
|
return state === SlidingSyncState.Complete;
|
||||||
});
|
});
|
||||||
slidingSync.setList(1, extraListReq);
|
slidingSync.setList("b", extraListReq);
|
||||||
await httpBackend!.flushAllExpected();
|
await httpBackend!.flushAllExpected();
|
||||||
await responseProcessed;
|
await responseProcessed;
|
||||||
});
|
});
|
||||||
@ -559,8 +560,8 @@ describe("SlidingSync", () => {
|
|||||||
// move C (2) to A (0)
|
// move C (2) to A (0)
|
||||||
httpBackend!.when("POST", syncUrl).respond(200, {
|
httpBackend!.when("POST", syncUrl).respond(200, {
|
||||||
pos: "e",
|
pos: "e",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 500,
|
count: 500,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -574,16 +575,16 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
b: {
|
||||||
count: 50,
|
count: 50,
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
let listPromise = listenUntil(
|
let listPromise = listenUntil(
|
||||||
slidingSync,
|
slidingSync,
|
||||||
"SlidingSync.List",
|
"SlidingSync.List",
|
||||||
(listIndex, joinedCount, roomIndexToRoomId) => {
|
(listKey, joinedCount, roomIndexToRoomId) => {
|
||||||
expect(listIndex).toEqual(0);
|
expect(listKey).toEqual("a");
|
||||||
expect(joinedCount).toEqual(500);
|
expect(joinedCount).toEqual(500);
|
||||||
expect(roomIndexToRoomId).toEqual({
|
expect(roomIndexToRoomId).toEqual({
|
||||||
0: roomC,
|
0: roomC,
|
||||||
@ -603,8 +604,8 @@ describe("SlidingSync", () => {
|
|||||||
// move C (0) back to A (2)
|
// move C (0) back to A (2)
|
||||||
httpBackend!.when("POST", syncUrl).respond(200, {
|
httpBackend!.when("POST", syncUrl).respond(200, {
|
||||||
pos: "f",
|
pos: "f",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 500,
|
count: 500,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -618,13 +619,13 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
b: {
|
||||||
count: 50,
|
count: 50,
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
listPromise = listenUntil(slidingSync, "SlidingSync.List", (listIndex, joinedCount, roomIndexToRoomId) => {
|
listPromise = listenUntil(slidingSync, "SlidingSync.List", (listKey, joinedCount, roomIndexToRoomId) => {
|
||||||
expect(listIndex).toEqual(0);
|
expect(listKey).toEqual("a");
|
||||||
expect(joinedCount).toEqual(500);
|
expect(joinedCount).toEqual(500);
|
||||||
expect(roomIndexToRoomId).toEqual({
|
expect(roomIndexToRoomId).toEqual({
|
||||||
0: roomA,
|
0: roomA,
|
||||||
@ -644,8 +645,8 @@ describe("SlidingSync", () => {
|
|||||||
it("should ignore invalid list indexes", async () => {
|
it("should ignore invalid list indexes", async () => {
|
||||||
httpBackend!.when("POST", syncUrl).respond(200, {
|
httpBackend!.when("POST", syncUrl).respond(200, {
|
||||||
pos: "e",
|
pos: "e",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 500,
|
count: 500,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -654,16 +655,16 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
b: {
|
||||||
count: 50,
|
count: 50,
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
const listPromise = listenUntil(
|
const listPromise = listenUntil(
|
||||||
slidingSync,
|
slidingSync,
|
||||||
"SlidingSync.List",
|
"SlidingSync.List",
|
||||||
(listIndex, joinedCount, roomIndexToRoomId) => {
|
(listKey, joinedCount, roomIndexToRoomId) => {
|
||||||
expect(listIndex).toEqual(0);
|
expect(listKey).toEqual("a");
|
||||||
expect(joinedCount).toEqual(500);
|
expect(joinedCount).toEqual(500);
|
||||||
expect(roomIndexToRoomId).toEqual({
|
expect(roomIndexToRoomId).toEqual({
|
||||||
0: roomA,
|
0: roomA,
|
||||||
@ -684,8 +685,8 @@ describe("SlidingSync", () => {
|
|||||||
it("should be possible to update a list", async () => {
|
it("should be possible to update a list", async () => {
|
||||||
httpBackend!.when("POST", syncUrl).respond(200, {
|
httpBackend!.when("POST", syncUrl).respond(200, {
|
||||||
pos: "g",
|
pos: "g",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 42,
|
count: 42,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -699,13 +700,13 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
b: {
|
||||||
count: 50,
|
count: 50,
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
// update the list with a new filter
|
// update the list with a new filter
|
||||||
slidingSync.setList(0, {
|
slidingSync.setList("a", {
|
||||||
filters: {
|
filters: {
|
||||||
is_encrypted: true,
|
is_encrypted: true,
|
||||||
},
|
},
|
||||||
@ -714,8 +715,8 @@ describe("SlidingSync", () => {
|
|||||||
const listPromise = listenUntil(
|
const listPromise = listenUntil(
|
||||||
slidingSync,
|
slidingSync,
|
||||||
"SlidingSync.List",
|
"SlidingSync.List",
|
||||||
(listIndex, joinedCount, roomIndexToRoomId) => {
|
(listKey, joinedCount, roomIndexToRoomId) => {
|
||||||
expect(listIndex).toEqual(0);
|
expect(listKey).toEqual("a");
|
||||||
expect(joinedCount).toEqual(42);
|
expect(joinedCount).toEqual(42);
|
||||||
expect(roomIndexToRoomId).toEqual({
|
expect(roomIndexToRoomId).toEqual({
|
||||||
0: roomB,
|
0: roomB,
|
||||||
@ -738,12 +739,12 @@ describe("SlidingSync", () => {
|
|||||||
0: roomB,
|
0: roomB,
|
||||||
1: roomC,
|
1: roomC,
|
||||||
};
|
};
|
||||||
expect(slidingSync.getListData(0)!.roomIndexToRoomId).toEqual(indexToRoomId);
|
expect(slidingSync.getListData("a")!.roomIndexToRoomId).toEqual(indexToRoomId);
|
||||||
httpBackend!.when("POST", syncUrl).respond(200, {
|
httpBackend!.when("POST", syncUrl).respond(200, {
|
||||||
pos: "f",
|
pos: "f",
|
||||||
// currently the list is [B,C] so we will insert D then immediately delete it
|
// currently the list is [B,C] so we will insert D then immediately delete it
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 500,
|
count: 500,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -761,16 +762,16 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
b: {
|
||||||
count: 50,
|
count: 50,
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
const listPromise = listenUntil(
|
const listPromise = listenUntil(
|
||||||
slidingSync,
|
slidingSync,
|
||||||
"SlidingSync.List",
|
"SlidingSync.List",
|
||||||
(listIndex, joinedCount, roomIndexToRoomId) => {
|
(listKey, joinedCount, roomIndexToRoomId) => {
|
||||||
expect(listIndex).toEqual(0);
|
expect(listKey).toEqual("a");
|
||||||
expect(joinedCount).toEqual(500);
|
expect(joinedCount).toEqual(500);
|
||||||
expect(roomIndexToRoomId).toEqual(indexToRoomId);
|
expect(roomIndexToRoomId).toEqual(indexToRoomId);
|
||||||
return true;
|
return true;
|
||||||
@ -785,14 +786,14 @@ describe("SlidingSync", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should handle deletions correctly", async () => {
|
it("should handle deletions correctly", async () => {
|
||||||
expect(slidingSync.getListData(0)!.roomIndexToRoomId).toEqual({
|
expect(slidingSync.getListData("a")!.roomIndexToRoomId).toEqual({
|
||||||
0: roomB,
|
0: roomB,
|
||||||
1: roomC,
|
1: roomC,
|
||||||
});
|
});
|
||||||
httpBackend!.when("POST", syncUrl).respond(200, {
|
httpBackend!.when("POST", syncUrl).respond(200, {
|
||||||
pos: "g",
|
pos: "g",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 499,
|
count: 499,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -801,16 +802,16 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
b: {
|
||||||
count: 50,
|
count: 50,
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
const listPromise = listenUntil(
|
const listPromise = listenUntil(
|
||||||
slidingSync,
|
slidingSync,
|
||||||
"SlidingSync.List",
|
"SlidingSync.List",
|
||||||
(listIndex, joinedCount, roomIndexToRoomId) => {
|
(listKey, joinedCount, roomIndexToRoomId) => {
|
||||||
expect(listIndex).toEqual(0);
|
expect(listKey).toEqual("a");
|
||||||
expect(joinedCount).toEqual(499);
|
expect(joinedCount).toEqual(499);
|
||||||
expect(roomIndexToRoomId).toEqual({
|
expect(roomIndexToRoomId).toEqual({
|
||||||
0: roomC,
|
0: roomC,
|
||||||
@ -827,13 +828,13 @@ describe("SlidingSync", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should handle insertions correctly", async () => {
|
it("should handle insertions correctly", async () => {
|
||||||
expect(slidingSync.getListData(0)!.roomIndexToRoomId).toEqual({
|
expect(slidingSync.getListData("a")!.roomIndexToRoomId).toEqual({
|
||||||
0: roomC,
|
0: roomC,
|
||||||
});
|
});
|
||||||
httpBackend!.when("POST", syncUrl).respond(200, {
|
httpBackend!.when("POST", syncUrl).respond(200, {
|
||||||
pos: "h",
|
pos: "h",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 500,
|
count: 500,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -843,16 +844,16 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
b: {
|
||||||
count: 50,
|
count: 50,
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
let listPromise = listenUntil(
|
let listPromise = listenUntil(
|
||||||
slidingSync,
|
slidingSync,
|
||||||
"SlidingSync.List",
|
"SlidingSync.List",
|
||||||
(listIndex, joinedCount, roomIndexToRoomId) => {
|
(listKey, joinedCount, roomIndexToRoomId) => {
|
||||||
expect(listIndex).toEqual(0);
|
expect(listKey).toEqual("a");
|
||||||
expect(joinedCount).toEqual(500);
|
expect(joinedCount).toEqual(500);
|
||||||
expect(roomIndexToRoomId).toEqual({
|
expect(roomIndexToRoomId).toEqual({
|
||||||
0: roomC,
|
0: roomC,
|
||||||
@ -870,8 +871,8 @@ describe("SlidingSync", () => {
|
|||||||
|
|
||||||
httpBackend!.when("POST", syncUrl).respond(200, {
|
httpBackend!.when("POST", syncUrl).respond(200, {
|
||||||
pos: "h",
|
pos: "h",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 501,
|
count: 501,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -881,13 +882,13 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
b: {
|
||||||
count: 50,
|
count: 50,
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
listPromise = listenUntil(slidingSync, "SlidingSync.List", (listIndex, joinedCount, roomIndexToRoomId) => {
|
listPromise = listenUntil(slidingSync, "SlidingSync.List", (listKey, joinedCount, roomIndexToRoomId) => {
|
||||||
expect(listIndex).toEqual(0);
|
expect(listKey).toEqual("a");
|
||||||
expect(joinedCount).toEqual(501);
|
expect(joinedCount).toEqual(501);
|
||||||
expect(roomIndexToRoomId).toEqual({
|
expect(roomIndexToRoomId).toEqual({
|
||||||
0: roomC,
|
0: roomC,
|
||||||
@ -910,11 +911,14 @@ describe("SlidingSync", () => {
|
|||||||
it("should handle insertions with a spurious DELETE correctly", async () => {
|
it("should handle insertions with a spurious DELETE correctly", async () => {
|
||||||
slidingSync = new SlidingSync(
|
slidingSync = new SlidingSync(
|
||||||
proxyBaseUrl,
|
proxyBaseUrl,
|
||||||
[
|
new Map([
|
||||||
{
|
[
|
||||||
ranges: [[0, 20]],
|
"a",
|
||||||
},
|
{
|
||||||
],
|
ranges: [[0, 20]],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]),
|
||||||
{},
|
{},
|
||||||
client!,
|
client!,
|
||||||
1,
|
1,
|
||||||
@ -922,22 +926,22 @@ describe("SlidingSync", () => {
|
|||||||
// initially start with nothing
|
// initially start with nothing
|
||||||
httpBackend!.when("POST", syncUrl).respond(200, {
|
httpBackend!.when("POST", syncUrl).respond(200, {
|
||||||
pos: "a",
|
pos: "a",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 0,
|
count: 0,
|
||||||
ops: [],
|
ops: [],
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
slidingSync.start();
|
slidingSync.start();
|
||||||
await httpBackend!.flushAllExpected();
|
await httpBackend!.flushAllExpected();
|
||||||
expect(slidingSync.getListData(0)!.roomIndexToRoomId).toEqual({});
|
expect(slidingSync.getListData("a")!.roomIndexToRoomId).toEqual({});
|
||||||
|
|
||||||
// insert a room
|
// insert a room
|
||||||
httpBackend!.when("POST", syncUrl).respond(200, {
|
httpBackend!.when("POST", syncUrl).respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 1,
|
count: 1,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -951,18 +955,18 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
await httpBackend!.flushAllExpected();
|
await httpBackend!.flushAllExpected();
|
||||||
expect(slidingSync.getListData(0)!.roomIndexToRoomId).toEqual({
|
expect(slidingSync.getListData("a")!.roomIndexToRoomId).toEqual({
|
||||||
0: roomA,
|
0: roomA,
|
||||||
});
|
});
|
||||||
|
|
||||||
// insert another room
|
// insert another room
|
||||||
httpBackend!.when("POST", syncUrl).respond(200, {
|
httpBackend!.when("POST", syncUrl).respond(200, {
|
||||||
pos: "c",
|
pos: "c",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 1,
|
count: 1,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -976,10 +980,10 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
await httpBackend!.flushAllExpected();
|
await httpBackend!.flushAllExpected();
|
||||||
expect(slidingSync.getListData(0)!.roomIndexToRoomId).toEqual({
|
expect(slidingSync.getListData("a")!.roomIndexToRoomId).toEqual({
|
||||||
0: roomB,
|
0: roomB,
|
||||||
1: roomA,
|
1: roomA,
|
||||||
});
|
});
|
||||||
@ -987,8 +991,8 @@ describe("SlidingSync", () => {
|
|||||||
// insert a final room
|
// insert a final room
|
||||||
httpBackend!.when("POST", syncUrl).respond(200, {
|
httpBackend!.when("POST", syncUrl).respond(200, {
|
||||||
pos: "c",
|
pos: "c",
|
||||||
lists: [
|
lists: {
|
||||||
{
|
a: {
|
||||||
count: 1,
|
count: 1,
|
||||||
ops: [
|
ops: [
|
||||||
{
|
{
|
||||||
@ -1002,10 +1006,10 @@ describe("SlidingSync", () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
await httpBackend!.flushAllExpected();
|
await httpBackend!.flushAllExpected();
|
||||||
expect(slidingSync.getListData(0)!.roomIndexToRoomId).toEqual({
|
expect(slidingSync.getListData("a")!.roomIndexToRoomId).toEqual({
|
||||||
0: roomC,
|
0: roomC,
|
||||||
1: roomB,
|
1: roomB,
|
||||||
2: roomA,
|
2: roomA,
|
||||||
@ -1028,7 +1032,7 @@ describe("SlidingSync", () => {
|
|||||||
required_state: [["m.room.name", ""]],
|
required_state: [["m.room.name", ""]],
|
||||||
};
|
};
|
||||||
// add the subscription
|
// add the subscription
|
||||||
slidingSync = new SlidingSync(proxyBaseUrl, [], roomSubInfo, client!, 1);
|
slidingSync = new SlidingSync(proxyBaseUrl, new Map(), roomSubInfo, client!, 1);
|
||||||
// modification before SlidingSync.start()
|
// modification before SlidingSync.start()
|
||||||
const subscribePromise = slidingSync.modifyRoomSubscriptions(new Set([roomId]));
|
const subscribePromise = slidingSync.modifyRoomSubscriptions(new Set([roomId]));
|
||||||
let txnId: string | undefined;
|
let txnId: string | undefined;
|
||||||
@ -1046,7 +1050,7 @@ describe("SlidingSync", () => {
|
|||||||
return {
|
return {
|
||||||
pos: "aaa",
|
pos: "aaa",
|
||||||
txn_id: txnId,
|
txn_id: txnId,
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {
|
rooms: {
|
||||||
[roomId]: {
|
[roomId]: {
|
||||||
@ -1065,7 +1069,7 @@ describe("SlidingSync", () => {
|
|||||||
const newList = {
|
const newList = {
|
||||||
ranges: [[0, 20]],
|
ranges: [[0, 20]],
|
||||||
};
|
};
|
||||||
const promise = slidingSync.setList(0, newList);
|
const promise = slidingSync.setList("a", newList);
|
||||||
let txnId: string | undefined;
|
let txnId: string | undefined;
|
||||||
httpBackend!
|
httpBackend!
|
||||||
.when("POST", syncUrl)
|
.when("POST", syncUrl)
|
||||||
@ -1073,7 +1077,7 @@ describe("SlidingSync", () => {
|
|||||||
const body = req.data;
|
const body = req.data;
|
||||||
logger.debug("got ", body);
|
logger.debug("got ", body);
|
||||||
expect(body.room_subscriptions).toBeFalsy();
|
expect(body.room_subscriptions).toBeFalsy();
|
||||||
expect(body.lists[0]).toEqual(newList);
|
expect(body.lists["a"]).toEqual(newList);
|
||||||
expect(body.txn_id).toBeTruthy();
|
expect(body.txn_id).toBeTruthy();
|
||||||
txnId = body.txn_id;
|
txnId = body.txn_id;
|
||||||
})
|
})
|
||||||
@ -1081,7 +1085,7 @@ describe("SlidingSync", () => {
|
|||||||
return {
|
return {
|
||||||
pos: "bbb",
|
pos: "bbb",
|
||||||
txn_id: txnId,
|
txn_id: txnId,
|
||||||
lists: [{ count: 5 }],
|
lists: { a: { count: 5 } },
|
||||||
extensions: {},
|
extensions: {},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -1090,7 +1094,7 @@ describe("SlidingSync", () => {
|
|||||||
expect(txnId).toBeDefined();
|
expect(txnId).toBeDefined();
|
||||||
});
|
});
|
||||||
it("should resolve setListRanges during a connection", async () => {
|
it("should resolve setListRanges during a connection", async () => {
|
||||||
const promise = slidingSync.setListRanges(0, [[20, 40]]);
|
const promise = slidingSync.setListRanges("a", [[20, 40]]);
|
||||||
let txnId: string | undefined;
|
let txnId: string | undefined;
|
||||||
httpBackend!
|
httpBackend!
|
||||||
.when("POST", syncUrl)
|
.when("POST", syncUrl)
|
||||||
@ -1098,7 +1102,7 @@ describe("SlidingSync", () => {
|
|||||||
const body = req.data;
|
const body = req.data;
|
||||||
logger.debug("got ", body);
|
logger.debug("got ", body);
|
||||||
expect(body.room_subscriptions).toBeFalsy();
|
expect(body.room_subscriptions).toBeFalsy();
|
||||||
expect(body.lists[0]).toEqual({
|
expect(body.lists["a"]).toEqual({
|
||||||
ranges: [[20, 40]],
|
ranges: [[20, 40]],
|
||||||
});
|
});
|
||||||
expect(body.txn_id).toBeTruthy();
|
expect(body.txn_id).toBeTruthy();
|
||||||
@ -1108,7 +1112,7 @@ describe("SlidingSync", () => {
|
|||||||
return {
|
return {
|
||||||
pos: "ccc",
|
pos: "ccc",
|
||||||
txn_id: txnId,
|
txn_id: txnId,
|
||||||
lists: [{ count: 5 }],
|
lists: { a: { count: 5 } },
|
||||||
extensions: {},
|
extensions: {},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -1150,10 +1154,10 @@ describe("SlidingSync", () => {
|
|||||||
const pushTxn = function (req: MockHttpBackend["requests"][0]) {
|
const pushTxn = function (req: MockHttpBackend["requests"][0]) {
|
||||||
gotTxnIds.push(req.data.txn_id);
|
gotTxnIds.push(req.data.txn_id);
|
||||||
};
|
};
|
||||||
const failPromise = slidingSync.setListRanges(0, [[20, 40]]);
|
const failPromise = slidingSync.setListRanges("a", [[20, 40]]);
|
||||||
httpBackend!.when("POST", syncUrl).check(pushTxn).respond(200, { pos: "e" }); // missing txn_id
|
httpBackend!.when("POST", syncUrl).check(pushTxn).respond(200, { pos: "e" }); // missing txn_id
|
||||||
await httpBackend!.flushAllExpected();
|
await httpBackend!.flushAllExpected();
|
||||||
const failPromise2 = slidingSync.setListRanges(0, [[60, 70]]);
|
const failPromise2 = slidingSync.setListRanges("a", [[60, 70]]);
|
||||||
httpBackend!.when("POST", syncUrl).check(pushTxn).respond(200, { pos: "f" }); // missing txn_id
|
httpBackend!.when("POST", syncUrl).check(pushTxn).respond(200, { pos: "f" }); // missing txn_id
|
||||||
await httpBackend!.flushAllExpected();
|
await httpBackend!.flushAllExpected();
|
||||||
|
|
||||||
@ -1162,7 +1166,7 @@ describe("SlidingSync", () => {
|
|||||||
expect(failPromise).rejects.toEqual(gotTxnIds[0]);
|
expect(failPromise).rejects.toEqual(gotTxnIds[0]);
|
||||||
expect(failPromise2).rejects.toEqual(gotTxnIds[1]);
|
expect(failPromise2).rejects.toEqual(gotTxnIds[1]);
|
||||||
|
|
||||||
const okPromise = slidingSync.setListRanges(0, [[0, 20]]);
|
const okPromise = slidingSync.setListRanges("a", [[0, 20]]);
|
||||||
let txnId: string | undefined;
|
let txnId: string | undefined;
|
||||||
httpBackend!
|
httpBackend!
|
||||||
.when("POST", syncUrl)
|
.when("POST", syncUrl)
|
||||||
@ -1187,10 +1191,10 @@ describe("SlidingSync", () => {
|
|||||||
const pushTxn = function (req: MockHttpBackend["requests"][0]) {
|
const pushTxn = function (req: MockHttpBackend["requests"][0]) {
|
||||||
gotTxnIds.push(req.data?.txn_id);
|
gotTxnIds.push(req.data?.txn_id);
|
||||||
};
|
};
|
||||||
const A = slidingSync.setListRanges(0, [[20, 40]]);
|
const A = slidingSync.setListRanges("a", [[20, 40]]);
|
||||||
httpBackend!.when("POST", syncUrl).check(pushTxn).respond(200, { pos: "A" });
|
httpBackend!.when("POST", syncUrl).check(pushTxn).respond(200, { pos: "A" });
|
||||||
await httpBackend!.flushAllExpected();
|
await httpBackend!.flushAllExpected();
|
||||||
const B = slidingSync.setListRanges(0, [[60, 70]]);
|
const B = slidingSync.setListRanges("a", [[60, 70]]);
|
||||||
httpBackend!.when("POST", syncUrl).check(pushTxn).respond(200, { pos: "B" }); // missing txn_id
|
httpBackend!.when("POST", syncUrl).check(pushTxn).respond(200, { pos: "B" }); // missing txn_id
|
||||||
await httpBackend!.flushAllExpected();
|
await httpBackend!.flushAllExpected();
|
||||||
|
|
||||||
@ -1198,7 +1202,7 @@ describe("SlidingSync", () => {
|
|||||||
// which is a fail.
|
// which is a fail.
|
||||||
expect(A).rejects.toEqual(gotTxnIds[0]);
|
expect(A).rejects.toEqual(gotTxnIds[0]);
|
||||||
|
|
||||||
const C = slidingSync.setListRanges(0, [[0, 20]]);
|
const C = slidingSync.setListRanges("a", [[0, 20]]);
|
||||||
let pendingC = true;
|
let pendingC = true;
|
||||||
C.finally(() => {
|
C.finally(() => {
|
||||||
pendingC = false;
|
pendingC = false;
|
||||||
@ -1219,7 +1223,7 @@ describe("SlidingSync", () => {
|
|||||||
expect(pendingC).toBe(true); // C is pending still
|
expect(pendingC).toBe(true); // C is pending still
|
||||||
});
|
});
|
||||||
it("should do nothing for unknown txn_ids", async () => {
|
it("should do nothing for unknown txn_ids", async () => {
|
||||||
const promise = slidingSync.setListRanges(0, [[20, 40]]);
|
const promise = slidingSync.setListRanges("a", [[20, 40]]);
|
||||||
let pending = true;
|
let pending = true;
|
||||||
promise.finally(() => {
|
promise.finally(() => {
|
||||||
pending = false;
|
pending = false;
|
||||||
@ -1231,7 +1235,7 @@ describe("SlidingSync", () => {
|
|||||||
const body = req.data;
|
const body = req.data;
|
||||||
logger.debug("got ", body);
|
logger.debug("got ", body);
|
||||||
expect(body.room_subscriptions).toBeFalsy();
|
expect(body.room_subscriptions).toBeFalsy();
|
||||||
expect(body.lists[0]).toEqual({
|
expect(body.lists["a"]).toEqual({
|
||||||
ranges: [[20, 40]],
|
ranges: [[20, 40]],
|
||||||
});
|
});
|
||||||
expect(body.txn_id).toBeTruthy();
|
expect(body.txn_id).toBeTruthy();
|
||||||
@ -1241,7 +1245,7 @@ describe("SlidingSync", () => {
|
|||||||
return {
|
return {
|
||||||
pos: "ccc",
|
pos: "ccc",
|
||||||
txn_id: "bogus transaction id",
|
txn_id: "bogus transaction id",
|
||||||
lists: [{ count: 5 }],
|
lists: { a: { count: 5 } },
|
||||||
extensions: {},
|
extensions: {},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -1279,7 +1283,7 @@ describe("SlidingSync", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
it("should be possible to use custom subscriptions on startup", async () => {
|
it("should be possible to use custom subscriptions on startup", async () => {
|
||||||
const slidingSync = new SlidingSync(proxyBaseUrl, [], defaultSub, client!, 1);
|
const slidingSync = new SlidingSync(proxyBaseUrl, new Map(), defaultSub, client!, 1);
|
||||||
// the intention is for clients to set this up at startup
|
// the intention is for clients to set this up at startup
|
||||||
slidingSync.addCustomSubscription(customSubName1, customSub1);
|
slidingSync.addCustomSubscription(customSubName1, customSub1);
|
||||||
slidingSync.addCustomSubscription(customSubName2, customSub2);
|
slidingSync.addCustomSubscription(customSubName2, customSub2);
|
||||||
@ -1302,7 +1306,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {},
|
rooms: {},
|
||||||
});
|
});
|
||||||
@ -1312,7 +1316,7 @@ describe("SlidingSync", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should be possible to use custom subscriptions mid-connection", async () => {
|
it("should be possible to use custom subscriptions mid-connection", async () => {
|
||||||
const slidingSync = new SlidingSync(proxyBaseUrl, [], defaultSub, client!, 1);
|
const slidingSync = new SlidingSync(proxyBaseUrl, new Map(), defaultSub, client!, 1);
|
||||||
// the intention is for clients to set this up at startup
|
// the intention is for clients to set this up at startup
|
||||||
slidingSync.addCustomSubscription(customSubName1, customSub1);
|
slidingSync.addCustomSubscription(customSubName1, customSub1);
|
||||||
slidingSync.addCustomSubscription(customSubName2, customSub2);
|
slidingSync.addCustomSubscription(customSubName2, customSub2);
|
||||||
@ -1326,7 +1330,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {},
|
rooms: {},
|
||||||
});
|
});
|
||||||
@ -1344,7 +1348,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {},
|
rooms: {},
|
||||||
});
|
});
|
||||||
@ -1363,7 +1367,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {},
|
rooms: {},
|
||||||
});
|
});
|
||||||
@ -1383,7 +1387,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {},
|
rooms: {},
|
||||||
});
|
});
|
||||||
@ -1395,7 +1399,7 @@ describe("SlidingSync", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("uses the default subscription for unknown subscription names", async () => {
|
it("uses the default subscription for unknown subscription names", async () => {
|
||||||
const slidingSync = new SlidingSync(proxyBaseUrl, [], defaultSub, client!, 1);
|
const slidingSync = new SlidingSync(proxyBaseUrl, new Map(), defaultSub, client!, 1);
|
||||||
slidingSync.addCustomSubscription(customSubName1, customSub1);
|
slidingSync.addCustomSubscription(customSubName1, customSub1);
|
||||||
slidingSync.useCustomSubscription(roomA, "unknown name");
|
slidingSync.useCustomSubscription(roomA, "unknown name");
|
||||||
slidingSync.modifyRoomSubscriptions(new Set<string>([roomA]));
|
slidingSync.modifyRoomSubscriptions(new Set<string>([roomA]));
|
||||||
@ -1410,7 +1414,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {},
|
rooms: {},
|
||||||
});
|
});
|
||||||
@ -1420,7 +1424,7 @@ describe("SlidingSync", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not be possible to add/modify an already added custom subscription", async () => {
|
it("should not be possible to add/modify an already added custom subscription", async () => {
|
||||||
const slidingSync = new SlidingSync(proxyBaseUrl, [], defaultSub, client!, 1);
|
const slidingSync = new SlidingSync(proxyBaseUrl, new Map(), defaultSub, client!, 1);
|
||||||
slidingSync.addCustomSubscription(customSubName1, customSub1);
|
slidingSync.addCustomSubscription(customSubName1, customSub1);
|
||||||
slidingSync.addCustomSubscription(customSubName1, customSub2);
|
slidingSync.addCustomSubscription(customSubName1, customSub2);
|
||||||
slidingSync.useCustomSubscription(roomA, customSubName1);
|
slidingSync.useCustomSubscription(roomA, customSubName1);
|
||||||
@ -1436,7 +1440,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {},
|
rooms: {},
|
||||||
});
|
});
|
||||||
@ -1446,7 +1450,7 @@ describe("SlidingSync", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should change the custom subscription if they are different", async () => {
|
it("should change the custom subscription if they are different", async () => {
|
||||||
const slidingSync = new SlidingSync(proxyBaseUrl, [], defaultSub, client!, 1);
|
const slidingSync = new SlidingSync(proxyBaseUrl, new Map(), defaultSub, client!, 1);
|
||||||
slidingSync.addCustomSubscription(customSubName1, customSub1);
|
slidingSync.addCustomSubscription(customSubName1, customSub1);
|
||||||
slidingSync.addCustomSubscription(customSubName2, customSub2);
|
slidingSync.addCustomSubscription(customSubName2, customSub2);
|
||||||
slidingSync.useCustomSubscription(roomA, customSubName1);
|
slidingSync.useCustomSubscription(roomA, customSubName1);
|
||||||
@ -1463,7 +1467,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {},
|
rooms: {},
|
||||||
});
|
});
|
||||||
@ -1484,7 +1488,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {},
|
rooms: {},
|
||||||
});
|
});
|
||||||
@ -1506,7 +1510,7 @@ describe("SlidingSync", () => {
|
|||||||
})
|
})
|
||||||
.respond(200, {
|
.respond(200, {
|
||||||
pos: "b",
|
pos: "b",
|
||||||
lists: [],
|
lists: {},
|
||||||
extensions: {},
|
extensions: {},
|
||||||
rooms: {},
|
rooms: {},
|
||||||
});
|
});
|
||||||
@ -1559,7 +1563,7 @@ describe("SlidingSync", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
it("should be able to register an extension", async () => {
|
it("should be able to register an extension", async () => {
|
||||||
slidingSync = new SlidingSync(proxyBaseUrl, [], {}, client!, 1);
|
slidingSync = new SlidingSync(proxyBaseUrl, new Map(), {}, client!, 1);
|
||||||
slidingSync.registerExtension(extPre);
|
slidingSync.registerExtension(extPre);
|
||||||
|
|
||||||
const callbackOrder: string[] = [];
|
const callbackOrder: string[] = [];
|
||||||
@ -1684,7 +1688,7 @@ describe("SlidingSync", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("is not possible to register the same extension name twice", async () => {
|
it("is not possible to register the same extension name twice", async () => {
|
||||||
slidingSync = new SlidingSync(proxyBaseUrl, [], {}, client!, 1);
|
slidingSync = new SlidingSync(proxyBaseUrl, new Map(), {}, client!, 1);
|
||||||
slidingSync.registerExtension(extPre);
|
slidingSync.registerExtension(extPre);
|
||||||
expect(() => {
|
expect(() => {
|
||||||
slidingSync.registerExtension(extPre);
|
slidingSync.registerExtension(extPre);
|
||||||
|
@ -70,7 +70,7 @@ export interface MSC3575List extends MSC3575RoomSubscription {
|
|||||||
*/
|
*/
|
||||||
export interface MSC3575SlidingSyncRequest {
|
export interface MSC3575SlidingSyncRequest {
|
||||||
// json body params
|
// json body params
|
||||||
lists?: MSC3575List[];
|
lists?: Record<string, MSC3575List>;
|
||||||
unsubscribe_rooms?: string[];
|
unsubscribe_rooms?: string[];
|
||||||
room_subscriptions?: Record<string, MSC3575RoomSubscription>;
|
room_subscriptions?: Record<string, MSC3575RoomSubscription>;
|
||||||
extensions?: object;
|
extensions?: object;
|
||||||
@ -137,7 +137,7 @@ type Operation = DeleteOperation | InsertOperation | InvalidateOperation | SyncO
|
|||||||
export interface MSC3575SlidingSyncResponse {
|
export interface MSC3575SlidingSyncResponse {
|
||||||
pos: string;
|
pos: string;
|
||||||
txn_id?: string;
|
txn_id?: string;
|
||||||
lists: ListResponse[];
|
lists: Record<string, ListResponse>;
|
||||||
rooms: Record<string, MSC3575RoomData>;
|
rooms: Record<string, MSC3575RoomData>;
|
||||||
extensions: Record<string, object>;
|
extensions: Record<string, object>;
|
||||||
}
|
}
|
||||||
@ -332,11 +332,7 @@ export type SlidingSyncEventHandlerMap = {
|
|||||||
resp: MSC3575SlidingSyncResponse | null,
|
resp: MSC3575SlidingSyncResponse | null,
|
||||||
err?: Error,
|
err?: Error,
|
||||||
) => void;
|
) => void;
|
||||||
[SlidingSyncEvent.List]: (
|
[SlidingSyncEvent.List]: (listKey: string, joinedCount: number, roomIndexToRoomId: Record<number, string>) => void;
|
||||||
listIndex: number,
|
|
||||||
joinedCount: number,
|
|
||||||
roomIndexToRoomId: Record<number, string>,
|
|
||||||
) => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -346,7 +342,7 @@ export type SlidingSyncEventHandlerMap = {
|
|||||||
* To hook this up with the JS SDK, you need to use SlidingSyncSdk.
|
* To hook this up with the JS SDK, you need to use SlidingSyncSdk.
|
||||||
*/
|
*/
|
||||||
export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSyncEventHandlerMap> {
|
export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSyncEventHandlerMap> {
|
||||||
private lists: SlidingList[];
|
private lists: Map<string, SlidingList>;
|
||||||
private listModifiedCount = 0;
|
private listModifiedCount = 0;
|
||||||
private terminated = false;
|
private terminated = false;
|
||||||
// flag set when resend() is called because we cannot rely on detecting AbortError in JS SDK :(
|
// flag set when resend() is called because we cannot rely on detecting AbortError in JS SDK :(
|
||||||
@ -380,13 +376,16 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
private readonly proxyBaseUrl: string,
|
private readonly proxyBaseUrl: string,
|
||||||
lists: MSC3575List[],
|
lists: Map<string, MSC3575List>,
|
||||||
private roomSubscriptionInfo: MSC3575RoomSubscription,
|
private roomSubscriptionInfo: MSC3575RoomSubscription,
|
||||||
private readonly client: MatrixClient,
|
private readonly client: MatrixClient,
|
||||||
private readonly timeoutMS: number,
|
private readonly timeoutMS: number,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.lists = lists.map((l) => new SlidingList(l));
|
this.lists = new Map<string, SlidingList>();
|
||||||
|
lists.forEach((list, key) => {
|
||||||
|
this.lists.set(key, new SlidingList(list));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -423,70 +422,70 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the length of the sliding lists.
|
* Get the room index data for a list.
|
||||||
* @returns The number of lists in the sync request
|
* @param key - The list key
|
||||||
*/
|
|
||||||
public listLength(): number {
|
|
||||||
return this.lists.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the room data for a list.
|
|
||||||
* @param index - The list index
|
|
||||||
* @returns The list data which contains the rooms in this list
|
* @returns The list data which contains the rooms in this list
|
||||||
*/
|
*/
|
||||||
public getListData(index: number): { joinedCount: number; roomIndexToRoomId: Record<number, string> } | null {
|
public getListData(key: string): { joinedCount: number; roomIndexToRoomId: Record<number, string> } | null {
|
||||||
if (!this.lists[index]) {
|
const data = this.lists.get(key);
|
||||||
|
if (!data) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
joinedCount: this.lists[index].joinedCount,
|
joinedCount: data.joinedCount,
|
||||||
roomIndexToRoomId: Object.assign({}, this.lists[index].roomIndexToRoomId),
|
roomIndexToRoomId: Object.assign({}, data.roomIndexToRoomId),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the full list parameters for a list index. This function is provided for callers to use
|
* Get the full request list parameters for a list index. This function is provided for callers to use
|
||||||
* in conjunction with setList to update fields on an existing list.
|
* in conjunction with setList to update fields on an existing list.
|
||||||
* @param index - The list index to get the list for.
|
* @param key - The list key to get the params for.
|
||||||
* @returns A copy of the list or undefined.
|
* @returns A copy of the list params or undefined.
|
||||||
*/
|
*/
|
||||||
public getList(index: number): MSC3575List | null {
|
public getListParams(key: string): MSC3575List | null {
|
||||||
if (!this.lists[index]) {
|
const params = this.lists.get(key);
|
||||||
|
if (!params) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return this.lists[index].getList(true);
|
return params.getList(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set new ranges for an existing list. Calling this function when _only_ the ranges have changed
|
* Set new ranges for an existing list. Calling this function when _only_ the ranges have changed
|
||||||
* is more efficient than calling setList(index,list) as this function won't resend sticky params,
|
* is more efficient than calling setList(index,list) as this function won't resend sticky params,
|
||||||
* whereas setList always will.
|
* whereas setList always will.
|
||||||
* @param index - The list index to modify
|
* @param key - The list key to modify
|
||||||
* @param ranges - The new ranges to apply.
|
* @param ranges - The new ranges to apply.
|
||||||
* @returns A promise which resolves to the transaction ID when it has been received down sync
|
* @returns A promise which resolves to the transaction ID when it has been received down sync
|
||||||
* (or rejects with the transaction ID if the action was not applied e.g the request was cancelled
|
* (or rejects with the transaction ID if the action was not applied e.g the request was cancelled
|
||||||
* immediately after sending, in which case the action will be applied in the subsequent request)
|
* immediately after sending, in which case the action will be applied in the subsequent request)
|
||||||
*/
|
*/
|
||||||
public setListRanges(index: number, ranges: number[][]): Promise<string> {
|
public setListRanges(key: string, ranges: number[][]): Promise<string> {
|
||||||
this.lists[index].updateListRange(ranges);
|
const list = this.lists.get(key);
|
||||||
|
if (!list) {
|
||||||
|
return Promise.reject(new Error("no list with key " + key));
|
||||||
|
}
|
||||||
|
list.updateListRange(ranges);
|
||||||
return this.resend();
|
return this.resend();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add or replace a list. Calling this function will interrupt the /sync request to resend new
|
* Add or replace a list. Calling this function will interrupt the /sync request to resend new
|
||||||
* lists.
|
* lists.
|
||||||
* @param index - The index to modify
|
* @param key - The key to modify
|
||||||
* @param list - The new list parameters.
|
* @param list - The new list parameters.
|
||||||
* @returns A promise which resolves to the transaction ID when it has been received down sync
|
* @returns A promise which resolves to the transaction ID when it has been received down sync
|
||||||
* (or rejects with the transaction ID if the action was not applied e.g the request was cancelled
|
* (or rejects with the transaction ID if the action was not applied e.g the request was cancelled
|
||||||
* immediately after sending, in which case the action will be applied in the subsequent request)
|
* immediately after sending, in which case the action will be applied in the subsequent request)
|
||||||
*/
|
*/
|
||||||
public setList(index: number, list: MSC3575List): Promise<string> {
|
public setList(key: string, list: MSC3575List): Promise<string> {
|
||||||
if (this.lists[index]) {
|
const existingList = this.lists.get(key);
|
||||||
this.lists[index].replaceList(list);
|
if (existingList) {
|
||||||
|
existingList.replaceList(list);
|
||||||
|
this.lists.set(key, existingList);
|
||||||
} else {
|
} else {
|
||||||
this.lists[index] = new SlidingList(list);
|
this.lists.set(key, new SlidingList(list));
|
||||||
}
|
}
|
||||||
this.listModifiedCount += 1;
|
this.listModifiedCount += 1;
|
||||||
return this.resend();
|
return this.resend();
|
||||||
@ -592,32 +591,44 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
this.emit(SlidingSyncEvent.Lifecycle, state, resp, err);
|
this.emit(SlidingSyncEvent.Lifecycle, state, resp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
private shiftRight(listIndex: number, hi: number, low: number): void {
|
private shiftRight(listKey: string, hi: number, low: number): void {
|
||||||
|
const list = this.lists.get(listKey);
|
||||||
|
if (!list) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// l h
|
// l h
|
||||||
// 0,1,2,3,4 <- before
|
// 0,1,2,3,4 <- before
|
||||||
// 0,1,2,2,3 <- after, hi is deleted and low is duplicated
|
// 0,1,2,2,3 <- after, hi is deleted and low is duplicated
|
||||||
for (let i = hi; i > low; i--) {
|
for (let i = hi; i > low; i--) {
|
||||||
if (this.lists[listIndex].isIndexInRange(i)) {
|
if (list.isIndexInRange(i)) {
|
||||||
this.lists[listIndex].roomIndexToRoomId[i] = this.lists[listIndex].roomIndexToRoomId[i - 1];
|
list.roomIndexToRoomId[i] = list.roomIndexToRoomId[i - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private shiftLeft(listIndex: number, hi: number, low: number): void {
|
private shiftLeft(listKey: string, hi: number, low: number): void {
|
||||||
|
const list = this.lists.get(listKey);
|
||||||
|
if (!list) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// l h
|
// l h
|
||||||
// 0,1,2,3,4 <- before
|
// 0,1,2,3,4 <- before
|
||||||
// 0,1,3,4,4 <- after, low is deleted and hi is duplicated
|
// 0,1,3,4,4 <- after, low is deleted and hi is duplicated
|
||||||
for (let i = low; i < hi; i++) {
|
for (let i = low; i < hi; i++) {
|
||||||
if (this.lists[listIndex].isIndexInRange(i)) {
|
if (list.isIndexInRange(i)) {
|
||||||
this.lists[listIndex].roomIndexToRoomId[i] = this.lists[listIndex].roomIndexToRoomId[i + 1];
|
list.roomIndexToRoomId[i] = list.roomIndexToRoomId[i + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeEntry(listIndex: number, index: number): void {
|
private removeEntry(listKey: string, index: number): void {
|
||||||
|
const list = this.lists.get(listKey);
|
||||||
|
if (!list) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// work out the max index
|
// work out the max index
|
||||||
let max = -1;
|
let max = -1;
|
||||||
for (const n in this.lists[listIndex].roomIndexToRoomId) {
|
for (const n in list.roomIndexToRoomId) {
|
||||||
if (Number(n) > max) {
|
if (Number(n) > max) {
|
||||||
max = Number(n);
|
max = Number(n);
|
||||||
}
|
}
|
||||||
@ -626,14 +637,18 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Everything higher than the gap needs to be shifted left.
|
// Everything higher than the gap needs to be shifted left.
|
||||||
this.shiftLeft(listIndex, max, index);
|
this.shiftLeft(listKey, max, index);
|
||||||
delete this.lists[listIndex].roomIndexToRoomId[max];
|
delete list.roomIndexToRoomId[max];
|
||||||
}
|
}
|
||||||
|
|
||||||
private addEntry(listIndex: number, index: number): void {
|
private addEntry(listKey: string, index: number): void {
|
||||||
|
const list = this.lists.get(listKey);
|
||||||
|
if (!list) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// work out the max index
|
// work out the max index
|
||||||
let max = -1;
|
let max = -1;
|
||||||
for (const n in this.lists[listIndex].roomIndexToRoomId) {
|
for (const n in list.roomIndexToRoomId) {
|
||||||
if (Number(n) > max) {
|
if (Number(n) > max) {
|
||||||
max = Number(n);
|
max = Number(n);
|
||||||
}
|
}
|
||||||
@ -642,30 +657,37 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Everything higher than the gap needs to be shifted right, +1 so we don't delete the highest element
|
// Everything higher than the gap needs to be shifted right, +1 so we don't delete the highest element
|
||||||
this.shiftRight(listIndex, max + 1, index);
|
this.shiftRight(listKey, max + 1, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
private processListOps(list: ListResponse, listIndex: number): void {
|
private processListOps(list: ListResponse, listKey: string): void {
|
||||||
let gapIndex = -1;
|
let gapIndex = -1;
|
||||||
|
const listData = this.lists.get(listKey);
|
||||||
|
if (!listData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
list.ops.forEach((op: Operation) => {
|
list.ops.forEach((op: Operation) => {
|
||||||
|
if (!listData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (op.op) {
|
switch (op.op) {
|
||||||
case "DELETE": {
|
case "DELETE": {
|
||||||
logger.debug("DELETE", listIndex, op.index, ";");
|
logger.debug("DELETE", listKey, op.index, ";");
|
||||||
delete this.lists[listIndex].roomIndexToRoomId[op.index];
|
delete listData.roomIndexToRoomId[op.index];
|
||||||
if (gapIndex !== -1) {
|
if (gapIndex !== -1) {
|
||||||
// we already have a DELETE operation to process, so process it.
|
// we already have a DELETE operation to process, so process it.
|
||||||
this.removeEntry(listIndex, gapIndex);
|
this.removeEntry(listKey, gapIndex);
|
||||||
}
|
}
|
||||||
gapIndex = op.index;
|
gapIndex = op.index;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "INSERT": {
|
case "INSERT": {
|
||||||
logger.debug("INSERT", listIndex, op.index, op.room_id, ";");
|
logger.debug("INSERT", listKey, op.index, op.room_id, ";");
|
||||||
if (this.lists[listIndex].roomIndexToRoomId[op.index]) {
|
if (listData.roomIndexToRoomId[op.index]) {
|
||||||
// something is in this space, shift items out of the way
|
// something is in this space, shift items out of the way
|
||||||
if (gapIndex < 0) {
|
if (gapIndex < 0) {
|
||||||
// we haven't been told where to shift from, so make way for a new room entry.
|
// we haven't been told where to shift from, so make way for a new room entry.
|
||||||
this.addEntry(listIndex, op.index);
|
this.addEntry(listKey, op.index);
|
||||||
} else if (gapIndex > op.index) {
|
} else if (gapIndex > op.index) {
|
||||||
// the gap is further down the list, shift every element to the right
|
// the gap is further down the list, shift every element to the right
|
||||||
// starting at the gap so we can just shift each element in turn:
|
// starting at the gap so we can just shift each element in turn:
|
||||||
@ -674,11 +696,11 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
// [A,B,B,C] i=2
|
// [A,B,B,C] i=2
|
||||||
// [A,A,B,C] i=1
|
// [A,A,B,C] i=1
|
||||||
// Terminate. We'll assign into op.index next.
|
// Terminate. We'll assign into op.index next.
|
||||||
this.shiftRight(listIndex, gapIndex, op.index);
|
this.shiftRight(listKey, gapIndex, op.index);
|
||||||
} else if (gapIndex < op.index) {
|
} else if (gapIndex < op.index) {
|
||||||
// the gap is further up the list, shift every element to the left
|
// the gap is further up the list, shift every element to the left
|
||||||
// starting at the gap so we can just shift each element in turn
|
// starting at the gap so we can just shift each element in turn
|
||||||
this.shiftLeft(listIndex, op.index, gapIndex);
|
this.shiftLeft(listKey, op.index, gapIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// forget the gap, we don't need it anymore. This is outside the check for
|
// forget the gap, we don't need it anymore. This is outside the check for
|
||||||
@ -686,15 +708,15 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
// forget the gap, not conditionally based on the presence of a room in the INSERT
|
// forget the gap, not conditionally based on the presence of a room in the INSERT
|
||||||
// position. Without this, DELETE 0; INSERT 0; would do the wrong thing.
|
// position. Without this, DELETE 0; INSERT 0; would do the wrong thing.
|
||||||
gapIndex = -1;
|
gapIndex = -1;
|
||||||
this.lists[listIndex].roomIndexToRoomId[op.index] = op.room_id;
|
listData.roomIndexToRoomId[op.index] = op.room_id;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "INVALIDATE": {
|
case "INVALIDATE": {
|
||||||
const startIndex = op.range[0];
|
const startIndex = op.range[0];
|
||||||
for (let i = startIndex; i <= op.range[1]; i++) {
|
for (let i = startIndex; i <= op.range[1]; i++) {
|
||||||
delete this.lists[listIndex].roomIndexToRoomId[i];
|
delete listData.roomIndexToRoomId[i];
|
||||||
}
|
}
|
||||||
logger.debug("INVALIDATE", listIndex, op.range[0], op.range[1], ";");
|
logger.debug("INVALIDATE", listKey, op.range[0], op.range[1], ";");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "SYNC": {
|
case "SYNC": {
|
||||||
@ -704,9 +726,9 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
if (!roomId) {
|
if (!roomId) {
|
||||||
break; // we are at the end of list
|
break; // we are at the end of list
|
||||||
}
|
}
|
||||||
this.lists[listIndex].roomIndexToRoomId[i] = roomId;
|
listData.roomIndexToRoomId[i] = roomId;
|
||||||
}
|
}
|
||||||
logger.debug("SYNC", listIndex, op.range[0], op.range[1], (op.room_ids || []).join(" "), ";");
|
logger.debug("SYNC", listKey, op.range[0], op.range[1], (op.room_ids || []).join(" "), ";");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -714,7 +736,7 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
if (gapIndex !== -1) {
|
if (gapIndex !== -1) {
|
||||||
// we already have a DELETE operation to process, so process it
|
// we already have a DELETE operation to process, so process it
|
||||||
// Everything higher than the gap needs to be shifted left.
|
// Everything higher than the gap needs to be shifted left.
|
||||||
this.removeEntry(listIndex, gapIndex);
|
this.removeEntry(listKey, gapIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -814,10 +836,12 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
let resp: MSC3575SlidingSyncResponse | undefined;
|
let resp: MSC3575SlidingSyncResponse | undefined;
|
||||||
try {
|
try {
|
||||||
const listModifiedCount = this.listModifiedCount;
|
const listModifiedCount = this.listModifiedCount;
|
||||||
|
const reqLists: Record<string, MSC3575List> = {};
|
||||||
|
this.lists.forEach((l: SlidingList, key: string) => {
|
||||||
|
reqLists[key] = l.getList(false);
|
||||||
|
});
|
||||||
const reqBody: MSC3575SlidingSyncRequest = {
|
const reqBody: MSC3575SlidingSyncRequest = {
|
||||||
lists: this.lists.map((l) => {
|
lists: reqLists,
|
||||||
return l.getList(false);
|
|
||||||
}),
|
|
||||||
pos: currentPos,
|
pos: currentPos,
|
||||||
timeout: this.timeoutMS,
|
timeout: this.timeoutMS,
|
||||||
clientTimeout: this.timeoutMS + BUFFER_PERIOD_MS,
|
clientTimeout: this.timeoutMS + BUFFER_PERIOD_MS,
|
||||||
@ -866,11 +890,15 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
l.setModified(false);
|
l.setModified(false);
|
||||||
});
|
});
|
||||||
// set default empty values so we don't need to null check
|
// set default empty values so we don't need to null check
|
||||||
resp.lists = resp.lists || [];
|
resp.lists = resp.lists || {};
|
||||||
resp.rooms = resp.rooms || {};
|
resp.rooms = resp.rooms || {};
|
||||||
resp.extensions = resp.extensions || {};
|
resp.extensions = resp.extensions || {};
|
||||||
resp.lists.forEach((val, i) => {
|
Object.keys(resp.lists).forEach((key: string) => {
|
||||||
this.lists[i].joinedCount = val.count;
|
const list = this.lists.get(key);
|
||||||
|
if (!list || !resp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
list.joinedCount = resp.lists[key].count;
|
||||||
});
|
});
|
||||||
this.invokeLifecycleListeners(SlidingSyncState.RequestFinished, resp);
|
this.invokeLifecycleListeners(SlidingSyncState.RequestFinished, resp);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -899,25 +927,24 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
this.invokeRoomDataListeners(roomId, resp!.rooms[roomId]);
|
this.invokeRoomDataListeners(roomId, resp!.rooms[roomId]);
|
||||||
});
|
});
|
||||||
|
|
||||||
const listIndexesWithUpdates: Set<number> = new Set();
|
const listKeysWithUpdates: Set<string> = new Set();
|
||||||
if (!doNotUpdateList) {
|
if (!doNotUpdateList) {
|
||||||
resp.lists.forEach((list, listIndex) => {
|
for (const [key, list] of Object.entries(resp.lists)) {
|
||||||
list.ops = list.ops || [];
|
list.ops = list.ops || [];
|
||||||
if (list.ops.length > 0) {
|
if (list.ops.length > 0) {
|
||||||
listIndexesWithUpdates.add(listIndex);
|
listKeysWithUpdates.add(key);
|
||||||
}
|
}
|
||||||
this.processListOps(list, listIndex);
|
this.processListOps(list, key);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
this.invokeLifecycleListeners(SlidingSyncState.Complete, resp);
|
this.invokeLifecycleListeners(SlidingSyncState.Complete, resp);
|
||||||
this.onPostExtensionsResponse(resp.extensions);
|
this.onPostExtensionsResponse(resp.extensions);
|
||||||
listIndexesWithUpdates.forEach((i) => {
|
listKeysWithUpdates.forEach((listKey: string) => {
|
||||||
this.emit(
|
const list = this.lists.get(listKey);
|
||||||
SlidingSyncEvent.List,
|
if (!list) {
|
||||||
i,
|
return;
|
||||||
this.lists[i].joinedCount,
|
}
|
||||||
Object.assign({}, this.lists[i].roomIndexToRoomId),
|
this.emit(SlidingSyncEvent.List, listKey, list.joinedCount, Object.assign({}, list.roomIndexToRoomId));
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.resolveTransactionDefers(resp.txn_id);
|
this.resolveTransactionDefers(resp.txn_id);
|
||||||
|
Reference in New Issue
Block a user