Apply `retryFnIfNotJoined` to the rest of the endpoints

This commit is contained in:
Eric Eastwood 2023-06-22 22:39:38 -05:00
parent 2c2ce3e656
commit ae50a9f16f
1 changed files with 109 additions and 73 deletions

View File

@ -18,7 +18,6 @@ const {
fetchSuccessorInfo, fetchSuccessorInfo,
} = require('../lib/matrix-utils/fetch-room-data'); } = require('../lib/matrix-utils/fetch-room-data');
const fetchEventsFromTimestampBackwards = require('../lib/matrix-utils/fetch-events-from-timestamp-backwards'); const fetchEventsFromTimestampBackwards = require('../lib/matrix-utils/fetch-events-from-timestamp-backwards');
const ensureRoomJoined = require('../lib/matrix-utils/ensure-room-joined');
const createRetryFnIfNotJoined = require('../lib/matrix-utils/create-retry-fn-if-not-joined'); const createRetryFnIfNotJoined = require('../lib/matrix-utils/create-retry-fn-if-not-joined');
const resolveRoomIdOrAlias = require('../lib/matrix-utils/resolve-room-id-or-alias'); const resolveRoomIdOrAlias = require('../lib/matrix-utils/resolve-room-id-or-alias');
const timestampToEvent = require('../lib/matrix-utils/timestamp-to-event'); const timestampToEvent = require('../lib/matrix-utils/timestamp-to-event');
@ -181,21 +180,32 @@ router.get(
// the time before we join and looking backwards. // the time before we join and looking backwards.
const dateBeforeJoin = Date.now(); const dateBeforeJoin = Date.now();
// We have to wait for the room join to happen first before we can fetch // Resolve the room ID without joining the room (optimistically assume that we're
// any of the additional room info or messages. // already joined)
const roomId = await ensureRoomJoined(matrixAccessToken, roomIdOrAlias, { let viaServers = parseViaServersFromUserInput(req.query.via);
viaServers: parseViaServersFromUserInput(req.query.via), let roomId;
({ roomId, viaServers } = await resolveRoomIdOrAlias({
accessToken: matrixAccessToken,
roomIdOrAlias,
viaServers,
abortSignal: req.abortSignal,
}));
// And then we can always retry after joining if we fail somewhere
const retryFnIfNotJoined = createRetryFnIfNotJoined(matrixAccessToken, roomIdOrAlias, {
viaServers,
abortSignal: req.abortSignal, abortSignal: req.abortSignal,
}); });
// Find the closest day to the current time with messages // Find the closest day to the current time with messages
const { originServerTs } = await timestampToEvent({ const { originServerTs } = await retryFnIfNotJoined(() =>
accessToken: matrixAccessToken, timestampToEvent({
roomId, accessToken: matrixAccessToken,
ts: dateBeforeJoin, roomId,
direction: DIRECTION.backward, ts: dateBeforeJoin,
abortSignal: req.abortSignal, direction: DIRECTION.backward,
}); abortSignal: req.abortSignal,
})
);
if (!originServerTs) { if (!originServerTs) {
throw new StatusError(404, 'Unable to find day with history'); throw new StatusError(404, 'Unable to find day with history');
} }
@ -203,8 +213,8 @@ router.get(
// Redirect to a day with messages // Redirect to a day with messages
res.redirect( res.redirect(
matrixPublicArchiveURLCreator.archiveUrlForDate(roomIdOrAlias, new Date(originServerTs), { matrixPublicArchiveURLCreator.archiveUrlForDate(roomIdOrAlias, new Date(originServerTs), {
// We can avoid passing along the `via` query parameter because we already // We can avoid passing along the `viaServers` because our server already knows
// joined the room above (see `ensureRoomJoined`). // about the room given that we fetched data about it already.
// //
//viaServers: parseViaServersFromUserInput(req.query.via), //viaServers: parseViaServersFromUserInput(req.query.via),
}) })
@ -253,10 +263,18 @@ router.get(
`?timelineEndEventId must be a string or undefined but saw ${typeof timelineStartEventId}` `?timelineEndEventId must be a string or undefined but saw ${typeof timelineStartEventId}`
); );
// We have to wait for the room join to happen first before we can use the jump to // Resolve the room ID without joining the room (optimistically assume that we're
// date endpoint (or any other Matrix endpoint) // already joined)
const viaServers = parseViaServersFromUserInput(req.query.via); let viaServers = parseViaServersFromUserInput(req.query.via);
const roomId = await ensureRoomJoined(matrixAccessToken, roomIdOrAlias, { let roomId;
({ roomId, viaServers } = await resolveRoomIdOrAlias({
accessToken: matrixAccessToken,
roomIdOrAlias,
viaServers,
abortSignal: req.abortSignal,
}));
// And then we can always retry after joining if we fail somewhere
const retryFnIfNotJoined = createRetryFnIfNotJoined(matrixAccessToken, roomIdOrAlias, {
viaServers, viaServers,
abortSignal: req.abortSignal, abortSignal: req.abortSignal,
}); });
@ -298,28 +316,32 @@ router.get(
// Find the closest event to the given timestamp // Find the closest event to the given timestamp
[{ eventId: eventIdForClosestEvent, originServerTs: tsForClosestEvent }, roomCreateEventId] = [{ eventId: eventIdForClosestEvent, originServerTs: tsForClosestEvent }, roomCreateEventId] =
await Promise.all([ await Promise.all([
timestampToEvent({ retryFnIfNotJoined(() =>
accessToken: matrixAccessToken, timestampToEvent({
roomId, accessToken: matrixAccessToken,
ts: ts, roomId,
direction: dir, ts: ts,
// Since timestamps are untrusted and can be crafted to make loops in the direction: dir,
// timeline. We use this as a signal to keep progressing from this event // Since timestamps are untrusted and can be crafted to make loops in the
// regardless of what timestamp shenanigans are going on. See MSC3999 // timeline. We use this as a signal to keep progressing from this event
// (https://github.com/matrix-org/matrix-spec-proposals/pull/3999) // regardless of what timestamp shenanigans are going on. See MSC3999
// // (https://github.com/matrix-org/matrix-spec-proposals/pull/3999)
// TODO: Add tests for timestamp loops once Synapse supports MSC3999. We //
// currently just have this set in case some server has this implemented in // TODO: Add tests for timestamp loops once Synapse supports MSC3999. We
// the future but there currently is no implementation (as of 2023-04-17) and // currently just have this set in case some server has this implemented in
// we can't have passing tests without a server implementation first. // the future but there currently is no implementation (as of 2023-04-17) and
// // we can't have passing tests without a server implementation first.
// TODO: This isn't implemented yet //
fromCausalEventId, // TODO: This isn't implemented yet
abortSignal: req.abortSignal, fromCausalEventId,
}), abortSignal: req.abortSignal,
removeMe_fetchRoomCreateEventId(matrixAccessToken, roomId, { })
abortSignal: req.abortSignal, ),
}), retryFnIfNotJoined(() =>
removeMe_fetchRoomCreateEventId(matrixAccessToken, roomId, {
abortSignal: req.abortSignal,
})
),
]); ]);
// Without MSC3999, we currently only detect one kind of loop where the // Without MSC3999, we currently only detect one kind of loop where the
@ -444,14 +466,16 @@ router.get(
// for the actual room display that we redirect to from this route. No need for // for the actual room display that we redirect to from this route. No need for
// us go out 100 messages, only for us to go backwards 100 messages again in the // us go out 100 messages, only for us to go backwards 100 messages again in the
// next route. // next route.
const messageResData = await getMessagesResponseFromEventId({ const messageResData = await retryFnIfNotJoined(() =>
accessToken: matrixAccessToken, getMessagesResponseFromEventId({
roomId, accessToken: matrixAccessToken,
eventId: eventIdForClosestEvent, roomId,
dir: DIRECTION.forward, eventId: eventIdForClosestEvent,
limit: archiveMessageLimit, dir: DIRECTION.forward,
abortSignal: req.abortSignal, limit: archiveMessageLimit,
}); abortSignal: req.abortSignal,
})
);
if (!messageResData.chunk?.length) { if (!messageResData.chunk?.length) {
throw new StatusError( throw new StatusError(
@ -584,9 +608,11 @@ router.get(
predecessorRoomId, predecessorRoomId,
predecessorLastKnownEventId, predecessorLastKnownEventId,
predecessorViaServers, predecessorViaServers,
} = await fetchPredecessorInfo(matrixAccessToken, roomId, { } = await retryFnIfNotJoined(() =>
abortSignal: req.abortSignal, fetchPredecessorInfo(matrixAccessToken, roomId, {
}); abortSignal: req.abortSignal,
})
);
if (!predecessorRoomId) { if (!predecessorRoomId) {
throw new StatusError( throw new StatusError(
@ -595,18 +621,24 @@ router.get(
); );
} }
// We have to join the predecessor room before we can fetch the successor info // We can always retry after joining if we fail somewhere
// (this could be our first time seeing the room) const retryFnIfNotJoinedToPredecessorRoom = createRetryFnIfNotJoined(
await ensureRoomJoined(matrixAccessToken, predecessorRoomId, { matrixAccessToken,
viaServers, predecessorRoomId,
abortSignal: req.abortSignal, {
}); viaServers,
abortSignal: req.abortSignal,
}
);
const { const {
successorRoomId: successorRoomIdForPredecessor, successorRoomId: successorRoomIdForPredecessor,
successorSetTs: successorSetTsForPredecessor, successorSetTs: successorSetTsForPredecessor,
} = await fetchSuccessorInfo(matrixAccessToken, predecessorRoomId, { } = await retryFnIfNotJoinedToPredecessorRoom(() =>
abortSignal: req.abortSignal, fetchSuccessorInfo(matrixAccessToken, predecessorRoomId, {
}); abortSignal: req.abortSignal,
})
);
let tombstoneEventId; let tombstoneEventId;
if (!predecessorLastKnownEventId) { if (!predecessorLastKnownEventId) {
@ -617,13 +649,15 @@ router.get(
// //
// We just assume this is the tombstone event ID but in any case it gets us to // We just assume this is the tombstone event ID but in any case it gets us to
// an event that happened at the same time. // an event that happened at the same time.
({ eventId: tombstoneEventId } = await timestampToEvent({ ({ eventId: tombstoneEventId } = await retryFnIfNotJoinedToPredecessorRoom(() =>
accessToken: matrixAccessToken, timestampToEvent({
roomId: predecessorRoomId, accessToken: matrixAccessToken,
ts: successorSetTsForPredecessor, roomId: predecessorRoomId,
direction: DIRECTION.backward, ts: successorSetTsForPredecessor,
abortSignal: req.abortSignal, direction: DIRECTION.backward,
})); abortSignal: req.abortSignal,
})
));
} }
// Try to continue from the tombstone event in the predecessor room because // Try to continue from the tombstone event in the predecessor room because
@ -685,9 +719,11 @@ router.get(
); );
return; return;
} else if (dir === DIRECTION.forward) { } else if (dir === DIRECTION.forward) {
const { successorRoomId } = await fetchSuccessorInfo(matrixAccessToken, roomId, { const { successorRoomId } = await retryFnIfNotJoined(() =>
abortSignal: req.abortSignal, fetchSuccessorInfo(matrixAccessToken, roomId, {
}); abortSignal: req.abortSignal,
})
);
if (successorRoomId) { if (successorRoomId) {
// Jump to the successor room and continue at the first event of the room // Jump to the successor room and continue at the first event of the room
res.redirect( res.redirect(
@ -800,7 +836,7 @@ router.get(
viaServers, viaServers,
abortSignal: req.abortSignal, abortSignal: req.abortSignal,
})); }));
// And then we can always retry after joining if we fail somewhere
const retryFnIfNotJoined = createRetryFnIfNotJoined(matrixAccessToken, roomIdOrAlias, { const retryFnIfNotJoined = createRetryFnIfNotJoined(matrixAccessToken, roomIdOrAlias, {
viaServers, viaServers,
abortSignal: req.abortSignal, abortSignal: req.abortSignal,
@ -932,8 +968,8 @@ router.get(
// We purposely omit `scrollStartEventId` here because the canonical location // We purposely omit `scrollStartEventId` here because the canonical location
// for any given event ID is the page it resides on. // for any given event ID is the page it resides on.
// //
// We can avoid passing along the `viaServers` because we already joined the // We can avoid passing along the `viaServers` because our server already knows about
// room above (see `ensureRoomJoined`). // the room given that we fetched data about it already.
} }
), ),
shouldIndex, shouldIndex,