Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persist unsent messages for subsequent sessions #1655

Merged
merged 5 commits into from
Apr 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions spec/unit/room.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {EventStatus, MatrixEvent} from "../../src/models/event";
import {EventTimeline} from "../../src/models/event-timeline";
import {RoomState} from "../../src/models/room-state";
import {Room} from "../../src/models/room";
import {TestClient} from "../TestClient";

describe("Room", function() {
const roomId = "!foo:bar";
Expand Down Expand Up @@ -1176,7 +1177,10 @@ describe("Room", function() {
describe("addPendingEvent", function() {
it("should add pending events to the pendingEventList if " +
"pendingEventOrdering == 'detached'", function() {
const room = new Room(roomId, null, userA, {
const client = (new TestClient(
"@alice:example.com", "alicedevice",
)).client;
const room = new Room(roomId, client, userA, {
pendingEventOrdering: "detached",
});
const eventA = utils.mkMessage({
Expand Down Expand Up @@ -1226,7 +1230,10 @@ describe("Room", function() {

describe("updatePendingEvent", function() {
it("should remove cancelled events from the pending list", function() {
const room = new Room(roomId, null, userA, {
const client = (new TestClient(
"@alice:example.com", "alicedevice",
)).client;
const room = new Room(roomId, client, userA, {
pendingEventOrdering: "detached",
});
const eventA = utils.mkMessage({
Expand Down
72 changes: 63 additions & 9 deletions src/models/room.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ export function Room(roomId, client, myUserId, opts) {
opts = opts || {};
opts.pendingEventOrdering = opts.pendingEventOrdering || "chronological";

this._client = client;

// In some cases, we add listeners for every displayed Matrix event, so it's
// common to have quite a few more than the default limit.
this.setMaxListeners(100);
Expand Down Expand Up @@ -189,6 +191,16 @@ export function Room(roomId, client, myUserId, opts) {

if (this._opts.pendingEventOrdering == "detached") {
this._pendingEventList = [];
const serializedPendingEventList = client._sessionStore.store.getItem(pendingEventsKey(this.roomId));
if (serializedPendingEventList) {
JSON.parse(serializedPendingEventList)
.forEach(serializedEvent => {
const event = new MatrixEvent(serializedEvent);
event.setStatus(EventStatus.NOT_SENT);
const txnId = client.makeTxnId();
germain-gg marked this conversation as resolved.
Show resolved Hide resolved
this.addPendingEvent(event, txnId);
});
}
}

// read by megolm; boolean value - null indicates "use global value"
Expand All @@ -197,14 +209,21 @@ export function Room(roomId, client, myUserId, opts) {
this._summaryHeroes = null;
// awaited by getEncryptionTargetMembers while room members are loading

this._client = client;
if (!this._opts.lazyLoadMembers) {
this._membersPromise = Promise.resolve();
} else {
this._membersPromise = null;
}
}

/**
* @param {string} roomId ID of the current room
* @returns {string} Storage key to retrieve pending events
*/
function pendingEventsKey(roomId) {
return `mx_pending_events_${roomId}`;
}

utils.inherits(Room, EventEmitter);

/**
Expand Down Expand Up @@ -357,6 +376,39 @@ Room.prototype.getPendingEvents = function() {
return this._pendingEventList;
};

/**
* Removes a pending event for this room
*
* @param {string} eventId
* @return {boolean} True if an element was removed.
*/
Room.prototype.removePendingEvent = function(eventId) {
if (this._opts.pendingEventOrdering !== "detached") {
throw new Error(
"Cannot call removePendingEvent with pendingEventOrdering == " +
this._opts.pendingEventOrdering);
}

const removed = utils.removeElement(
this._pendingEventList,
function(ev) {
return ev.getId() == eventId;
}, false,
);

const { store } = this._client._sessionStore;
if (this._pendingEventList.length > 0) {
store.setItem(
pendingEventsKey(this.roomId),
JSON.stringify(this._pendingEventList),
);
} else {
store.removeItem(pendingEventsKey(this.roomId));
}

return removed;
};

/**
* Check whether the pending event list contains a given event by ID.
* If pending event ordering is not "detached" then this returns false.
Expand Down Expand Up @@ -1192,7 +1244,7 @@ Room.prototype._addLiveEvent = function(event, duplicateStrategy, fromCache) {
* unique transaction id.
*/
Room.prototype.addPendingEvent = function(event, txnId) {
if (event.status !== EventStatus.SENDING) {
if (event.status !== EventStatus.SENDING && event.status !== EventStatus.NOT_SENT) {
throw new Error("addPendingEvent called on an event with status " +
event.status);
}
Expand All @@ -1219,7 +1271,11 @@ Room.prototype.addPendingEvent = function(event, txnId) {
event.setStatus(EventStatus.NOT_SENT);
}
this._pendingEventList.push(event);

const { store } = this._client._sessionStore;
store.setItem(
pendingEventsKey(this.roomId),
JSON.stringify(this._pendingEventList),
);
if (event.isRelation()) {
// For pending events, add them to the relations collection immediately.
// (The alternate case below already covers this as part of adding to
Expand Down Expand Up @@ -1310,12 +1366,7 @@ Room.prototype._handleRemoteEcho = function(remoteEvent, localEvent) {

// if it's in the pending list, remove it
if (this._pendingEventList) {
utils.removeElement(
this._pendingEventList,
function(ev) {
return ev.getId() == oldEventId;
}, false,
);
this.removePendingEvent(oldEventId);
}

// replace the event source (this will preserve the plaintext payload if
Expand Down Expand Up @@ -1421,6 +1472,9 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) {
for (let i = 0; i < this._timelineSets.length; i++) {
this._timelineSets[i].replaceEventId(oldEventId, newEventId);
}
if (this._opts.pendingEventOrdering === "detached") {
this.removePendingEvent(event.event.event_id);
}
} else if (newStatus == EventStatus.CANCELLED) {
// remove it from the pending event list, or the timeline.
if (this._pendingEventList) {
Expand Down