Skip to content

Commit

Permalink
Merge pull request #56 from matrix-org/kegan/archived-rooms
Browse files Browse the repository at this point in the history
Add syncLeftRooms()
  • Loading branch information
kegsay committed Dec 18, 2015
2 parents da560ff + 1174147 commit 2eec76b
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 26 deletions.
30 changes: 30 additions & 0 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2110,6 +2110,36 @@ MatrixClient.prototype.search = function(opts, callback) {
};


/**
* Populate the store with rooms the user has left.
* @return {module:client.Promise} Resolves: TODO - Resolved when the rooms have
* been added to the data store.
* @return {module:http-api.MatrixError} Rejects: with an error response.
*/
MatrixClient.prototype.syncLeftRooms = function() {
// Guard against multiple calls whilst ongoing and multiple calls post success
if (this._syncedLeftRooms) {
return q([]); // don't call syncRooms again if it succeeded.
}
if (this._syncLeftRoomsPromise) {
return this._syncLeftRoomsPromise; // return the ongoing request
}
var self = this;
var syncApi = new SyncApi(this);
this._syncLeftRoomsPromise = syncApi.syncLeftRooms();

// cleanup locks
this._syncLeftRoomsPromise.then(function(res) {
console.log("Marking success of sync left room request");
self._syncedLeftRooms = true; // flip the bit on success
}).finally(function() {
self._syncLeftRoomsPromise = null; // cleanup ongoing request state
});

return this._syncLeftRoomsPromise;
};


/**
* Create a new filter.
* @param {Object} content The HTTP body for the request
Expand Down
118 changes: 92 additions & 26 deletions lib/sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ var Filter = require("./filter");
// to determine the max time we're willing to wait.
var BUFFER_PERIOD_MS = 20 * 1000;

function getFilterName(userId) {
function getFilterName(userId, suffix) {
// scope this on the user ID because people may login on many accounts
// and they all need to be stored!
return "FILTER_SYNC_" + userId;
return "FILTER_SYNC_" + userId + (suffix ? "_" + suffix : "");
}



/**
* <b>Internal class - unstable.</b>
* Construct an entity which is able to sync with a homeserver.
Expand All @@ -38,7 +40,6 @@ function SyncApi(client, opts) {
this.client = client;
opts = opts || {};
opts.initialSyncLimit = opts.initialSyncLimit || 8;
opts.includeArchivedRooms = opts.includeArchivedRooms || false;
opts.resolveInvitesToProfiles = opts.resolveInvitesToProfiles || false;
opts.pollTimeout = opts.pollTimeout || (30 * 1000);
opts.pendingEventOrdering = opts.pendingEventOrdering || "chronological";
Expand Down Expand Up @@ -75,6 +76,69 @@ SyncApi.prototype.createRoom = function(roomId) {
return room;
};

/**
* Sync rooms the user has left.
* @return {Promise} Resolved when they've been added to the store.
*/
SyncApi.prototype.syncLeftRooms = function() {
var client = this.client;
var self = this;

// grab a filter with limit=1 and include_leave=true
var filter = new Filter(this.client.credentials.userId);
filter.setTimelineLimit(1);
filter.setIncludeLeaveRooms(true);

var localTimeoutMs = this.opts.pollTimeout + BUFFER_PERIOD_MS;
var qps = {
timeout: 1 // don't want to block since this is a single isolated req
};

return this._getOrCreateFilter(
getFilterName(client.credentials.userId, "LEFT_ROOMS"), filter
).then(function(filterId) {
qps.filter = filterId;
return client._http.authedRequestWithPrefix(
undefined, "GET", "/sync", qps, undefined, httpApi.PREFIX_V2_ALPHA,
localTimeoutMs
);
}).then(function(data) {
var leaveRooms = [];
if (data.rooms && data.rooms.leave) {
leaveRooms = self._mapSyncResponseToRoomArray(data.rooms.leave);
}
var rooms = [];
leaveRooms.forEach(function(leaveObj) {
var room = leaveObj.room;
rooms.push(room);
if (!leaveObj.isBrandNewRoom) {
// the intention behind syncLeftRooms is to add in rooms which were
// *omitted* from the initial /sync. Rooms the user were joined to
// but then left whilst the app is running will appear in this list
// and we do not want to bother with them since they will have the
// current state already (and may get dupe messages if we add
// yet more timeline events!), so skip them.
// NB: When we persist rooms to localStorage this will be more
// complicated...
return;
}
leaveObj.timeline = leaveObj.timeline || {};
var timelineEvents = self._mapSyncEventsFormat(leaveObj.timeline, room);
var stateEvents = self._mapSyncEventsFormat(leaveObj.state, room);
var paginationToken = (
leaveObj.timeline.limited ? leaveObj.timeline.prev_batch : null
);
self._processRoomEvents(
room, stateEvents, timelineEvents, paginationToken
);
room.recalculate(client.credentials.userId);
client.store.storeRoom(room);
client.emit("Room", room);
});
return rooms;
});
};

/**
* Main entry point
*/
Expand Down Expand Up @@ -104,27 +168,14 @@ SyncApi.prototype.sync = function() {
attempt = attempt || 0;
attempt += 1;

var filter = new Filter(client.credentials.userId);
filter.setTimelineLimit(self.opts.initialSyncLimit);

// Get or create filter
var filterId = client.store.getFilterIdByName(
getFilterName(client.credentials.userId)
);
if (filterId) {
// super, just use that.
self._getOrCreateFilter(
getFilterName(client.credentials.userId), filter
).done(function(filterId) {
console.log("Using existing filter ID %s", filterId);
self._sync({ filterId: filterId });
return;
}

// create a filter
var filter = new Filter(client.credentials.userId);
filter.setTimelineLimit(self.opts.initialSyncLimit);
client.createFilter(filter.getDefinition()).done(function(filter) {
client.store.setFilterIdByName(
getFilterName(client.credentials.userId), filter.filterId
);
console.log("Created filter ", filter.filterId);
self._sync({ filterId: filter.filterId }); // Now start the /sync loop
}, retryHandler(attempt, getFilter));
}

Expand Down Expand Up @@ -159,8 +210,6 @@ SyncApi.prototype._sync = function(syncOptions, attempt) {
var self = this;
attempt = attempt || 1;

// TODO include archived rooms flag.

var qps = {
filter: syncOptions.filterId,
timeout: this.opts.pollTimeout,
Expand Down Expand Up @@ -313,9 +362,6 @@ SyncApi.prototype._sync = function(syncOptions, attempt) {
var room = leaveObj.room;
var timelineEvents = self._mapSyncEventsFormat(leaveObj.timeline, room);
room.addEvents(timelineEvents);

// TODO: honour includeArchived opt

timelineEvents.forEach(function(e) { client.emit("event", e); });
});
}
Expand Down Expand Up @@ -345,6 +391,26 @@ SyncApi.prototype._sync = function(syncOptions, attempt) {
});
};

/**
* @param {string} filterName
* @param {Filter} filter
* @return {Promise<String>} Filter ID
*/
SyncApi.prototype._getOrCreateFilter = function(filterName, filter) {
var client = this.client;
var filterId = client.store.getFilterIdByName(filterName);
if (filterId) {
// super, just use that.
return q(filterId);
}

// create a filter
return client.createFilter(filter.getDefinition()).then(function(createdFilter) {
client.store.setFilterIdByName(filterName, createdFilter.filterId);
return createdFilter.filterId;
});
};

/**
* @param {Object} obj
* @return {Object[]}
Expand Down

0 comments on commit 2eec76b

Please sign in to comment.