Groups: On log fetch error from current revision, use joined_at_version

This commit is contained in:
Scott Nonnenberg 2024-08-22 07:31:55 +10:00 committed by GitHub
parent 78a95c23bb
commit a435b21a56
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 92 additions and 32 deletions

View file

@ -751,7 +751,7 @@ export async function buildAddMembersChange(
addPendingMembers.push(addPendingMemberAction);
}
const doesMemberNeedUnban = conversation.bannedMembersV2?.find(
const doesMemberNeedUnban = conversation.bannedMembersV2?.some(
bannedMember => bannedMember.serviceId === serviceId
);
if (doesMemberNeedUnban) {
@ -1020,7 +1020,7 @@ export function _maybeBuildAddBannedMemberActions({
'addMembersBanned' | 'deleteMembersBanned'
> {
const doesMemberNeedBan =
!group.bannedMembersV2?.find(member => member.serviceId === serviceId) &&
!group.bannedMembersV2?.some(member => member.serviceId === serviceId) &&
serviceId !== ourAci;
if (!doesMemberNeedBan) {
return {};
@ -1191,7 +1191,7 @@ export function buildAddMember({
actions.version = (group.revision || 0) + 1;
actions.addMembers = [addMember];
const doesMemberNeedUnban = group.bannedMembersV2?.find(
const doesMemberNeedUnban = group.bannedMembersV2?.some(
member => member.serviceId === serviceId
);
if (doesMemberNeedUnban) {
@ -3501,7 +3501,7 @@ async function getGroupUpdates({
const ourAci = window.storage.user.getCheckedAci();
const isInitialCreationMessage = isFirstFetch && newRevision === 0;
const weAreAwaitingApproval = (group.pendingAdminApprovalV2 || []).find(
const weAreAwaitingApproval = (group.pendingAdminApprovalV2 || []).some(
item => item.aci === ourAci
);
const isOneVersionUp =
@ -3565,18 +3565,18 @@ async function getGroupUpdates({
);
}
if (
(!isFirstFetch || isNumber(newRevision)) &&
window.Flags.GV2_ENABLE_CHANGE_PROCESSING
) {
const areWeMember = (group.membersV2 || []).some(item => item.aci === ourAci);
const isReJoin = !isFirstFetch && !areWeMember;
if (window.Flags.GV2_ENABLE_CHANGE_PROCESSING) {
try {
return await updateGroupViaLogs({
group,
newRevision,
});
} catch (error) {
const nextStep = isFirstFetch
? `fetching logs since ${newRevision}`
const nextStep = isReJoin
? 'attempting to fetch from re-join revision'
: 'fetching full state';
if (error.code === TEMPORAL_AUTH_REJECTED_CODE) {
@ -3595,6 +3595,30 @@ async function getGroupUpdates({
}
}
if (isReJoin && window.Flags.GV2_ENABLE_CHANGE_PROCESSING) {
try {
return await updateGroupViaLogs({
group,
newRevision,
isReJoin,
});
} catch (error) {
if (error.code === TEMPORAL_AUTH_REJECTED_CODE) {
// We will fail over to the updateGroupViaState call below
log.info(
`getGroupUpdates/${logId}: Temporal credential failure, now fetching full state`
);
} else if (error.code === GROUP_ACCESS_DENIED_CODE) {
// We will fail over to the updateGroupViaState call below
log.info(
`getGroupUpdates/${logId}: Log access denied, now fetching full state`
);
} else {
throw error;
}
}
}
if (window.Flags.GV2_ENABLE_STATE_PROCESSING) {
try {
return await updateGroupViaState({
@ -3887,9 +3911,11 @@ async function updateGroupViaSingleChange({
async function updateGroupViaLogs({
group,
newRevision,
isReJoin,
}: {
group: ConversationAttributesType;
newRevision: number | undefined;
isReJoin?: boolean;
}): Promise<UpdatesResultType> {
const logId = idForLogging(group.groupId);
const { publicParams, secretParams } = group;
@ -3900,15 +3926,15 @@ async function updateGroupViaLogs({
throw new Error('updateGroupViaLogs: group was missing secretParams!');
}
const currentRevision = isReJoin ? undefined : group.revision;
let includeFirstState = true;
log.info(
`updateGroupViaLogs/${logId}: Getting group delta from ` +
`${group.revision ?? '?'} to ${newRevision ?? '?'} for group ` +
`${currentRevision ?? '?'} to ${newRevision ?? '?'} for group ` +
`groupv2(${group.groupId})...`
);
const currentRevision = group.revision;
let includeFirstState = true;
// The range is inclusive so make sure that we always request the revision
// that we are currently at since we might want the latest full state in
// `integrateGroupChanges`.
@ -4217,9 +4243,13 @@ async function integrateGroupChange({
const isFirstFetch = !isNumber(group.revision);
const ourAci = window.storage.user.getCheckedAci();
const weAreAwaitingApproval = (group.pendingAdminApprovalV2 || []).find(
const weAreAwaitingApproval = (group.pendingAdminApprovalV2 || []).some(
item => item.aci === ourAci
);
const weAreInGroup = (group.membersV2 || []).some(
item => item.aci === ourAci
);
const isReJoin = !isFirstFetch && !weAreInGroup;
// These need to be populated from the groupChange. But we might not get one!
let isChangeSupported = false;
@ -4347,6 +4377,7 @@ async function integrateGroupChange({
isChangePresent: Boolean(groupChange),
isChangeSupported,
isFirstFetch,
isReJoin,
isSameVersion,
isMoreThanOneVersionUp,
weAreAwaitingApproval,
@ -4366,13 +4397,14 @@ async function integrateGroupChange({
} = await applyGroupState({
group: attributes,
groupState: decryptedGroupState,
sourceServiceId: isFirstFetch ? sourceServiceId : undefined,
sourceServiceId: isFirstFetch || isReJoin ? sourceServiceId : undefined,
});
const groupChangeMessages = extractDiffs({
old: attributes,
current: newAttributes,
sourceServiceId: isFirstFetch ? sourceServiceId : undefined,
sourceServiceId: isFirstFetch || isReJoin ? sourceServiceId : undefined,
isReJoin,
});
const newProfileKeys = profileKeysToMap(newProfileKeysList);
@ -4419,15 +4451,17 @@ async function integrateGroupChange({
function extractDiffs({
current,
dropInitialJoinMessage,
isReJoin,
old,
sourceServiceId,
promotedAciToPniMap,
sourceServiceId,
}: {
current: ConversationAttributesType;
dropInitialJoinMessage?: boolean;
isReJoin?: boolean;
old: ConversationAttributesType;
sourceServiceId?: ServiceIdString;
promotedAciToPniMap?: ReadonlyMap<AciString, PniString>;
sourceServiceId?: ServiceIdString;
}): Array<GroupChangeMessageType> {
const logId = idForLogging(old.groupId);
const details: Array<GroupV2ChangeDetailType> = [];
@ -4941,11 +4975,11 @@ function extractDiffs({
timerNotification = {
...generateBasicMessage(),
type: 'timer-notification',
sourceServiceId,
sourceServiceId: isReJoin ? undefined : sourceServiceId,
flags: Proto.DataMessage.Flags.EXPIRATION_TIMER_UPDATE,
expirationTimerUpdate: {
expireTimer,
sourceServiceId,
sourceServiceId: isReJoin ? undefined : sourceServiceId,
},
};
}