private CompletableFuture<Void> updateFirstUnseenOnFlagsUpdate(CassandraId mailboxId, UpdatedFlags updatedFlags) { if (updatedFlags.isModifiedToUnset(Flags.Flag.SEEN)) { return firstUnseenDAO.addUnread(mailboxId, updatedFlags.getUid()); } if (updatedFlags.isModifiedToSet(Flags.Flag.SEEN)) { return firstUnseenDAO.removeUnread(mailboxId, updatedFlags.getUid()); } return CompletableFuture.completedFuture(null); } }
public UpdatedFlagsDataTransferObject(UpdatedFlags updatedFlags) { this.uid = updatedFlags.getUid().asLong(); this.modseq = updatedFlags.getModSeq(); this.oldFlags = new FlagsDataTransferObject(updatedFlags.getOldFlags()); this.newFlags = new FlagsDataTransferObject(updatedFlags.getNewFlags()); }
private boolean interestingFlags(UpdatedFlags updated) { boolean result; final Iterator<Flags.Flag> it = updated.systemFlagIterator(); if (it.hasNext()) { final Flags.Flag flag = it.next(); if (flag.equals(uninterestingFlag)) { result = false; } else { result = true; } } else { result = false; } // See if we need to check the user flags if (result == false) { final Iterator<String> userIt = updated.userFlagIterator(); result = userIt.hasNext(); } return result; }
public boolean isUnchanged(Flags.Flag flag) { return !isModifiedToSet(flag) && !isModifiedToUnset(flag); }
private Stream<Pair<MailboxId, UpdatedFlags>> flagsUpdateWithRetry(Flags newState, MessageManager.FlagsUpdateMode updateMode, MailboxId mailboxId, MessageId messageId) { try { Pair<Flags, ComposedMessageIdWithMetaData> pair = new FunctionRunnerWithRetry(cassandraConfiguration.getFlagsUpdateMessageIdMaxRetry()) .executeAndRetrieveObject(() -> tryFlagsUpdate(newState, updateMode, mailboxId, messageId)); ComposedMessageIdWithMetaData composedMessageIdWithMetaData = pair.getRight(); Flags oldFlags = pair.getLeft(); return Stream.of(Pair.of(composedMessageIdWithMetaData.getComposedMessageId().getMailboxId(), UpdatedFlags.builder() .uid(composedMessageIdWithMetaData.getComposedMessageId().getUid()) .modSeq(composedMessageIdWithMetaData.getModSeq()) .oldFlags(oldFlags) .newFlags(composedMessageIdWithMetaData.getFlags()) .build())); } catch (LightweightTransactionException e) { throw new RuntimeException(e); } catch (MailboxDeleteDuringUpdateException e) { LOGGER.info("Mailbox {} was deleted during flag update", mailboxId); return Stream.of(); } }
@Test public void isModifiedToSetShouldReturnFalseWhenFlagIsOnNone() { UpdatedFlags updatedFlags = UpdatedFlags.builder() .newFlags(new Flags()) .oldFlags(new Flags()) .uid(UID) .modSeq(MOD_SEQ) .build(); assertThat(updatedFlags.isModifiedToSet(Flags.Flag.RECENT)).isFalse(); }
@Test public void isModifiedToUnsetShouldReturnFalseWhenFlagIsOnBoth() { UpdatedFlags updatedFlags = UpdatedFlags.builder() .newFlags(new Flags(Flags.Flag.RECENT)) .oldFlags(new Flags(Flags.Flag.RECENT)) .uid(UID) .modSeq(MOD_SEQ) .build(); assertThat(updatedFlags.isModifiedToUnset(Flags.Flag.RECENT)).isFalse(); }
@Test public void isUnchangedShouldReturnFalseWhenFlagOnlyInOldFlag() { UpdatedFlags updatedFlags = UpdatedFlags.builder() .newFlags(new Flags()) .oldFlags(new Flags(Flags.Flag.RECENT)) .uid(UID) .modSeq(MOD_SEQ) .build(); assertThat(updatedFlags.isUnchanged(Flags.Flag.RECENT)).isFalse(); }
flagUpdateUids.add(u.getUid()); for (int i = 0; i < uflags.size(); i++) { UpdatedFlags u = uflags.get(i); Iterator<Flag> flags = u.systemFlagIterator(); MailboxPath path = sm.getPath(); if (path != null && path.equals(event.getMailboxPath())) { sm.addRecent(u.getUid()); applicableFlags.add(flags.get(i).getNewFlags());
private UpdatedRepresentation createUpdatedDocumentPartFromUpdatedFlags(Mailbox mailbox, UpdatedFlags updatedFlags) { try { return new UpdatedRepresentation( indexIdFor(mailbox, updatedFlags.getUid()), messageToElasticSearchJson.getUpdatedJsonMessagePart( updatedFlags.getNewFlags(), updatedFlags.getModSeq())); } catch (JsonProcessingException e) { throw new RuntimeException("Error while creating updatedDocumentParts", e); } }
public MessageChangedFlags updateFlags(Mailbox mailbox, FlagsUpdateCalculator flagsUpdateCalculator, Iterator<MailboxMessage> messages) throws MailboxException { ImmutableList.Builder<UpdatedFlags> updatedFlags = ImmutableList.builder(); ImmutableList.Builder<MailboxMessage> changedFlags = ImmutableList.builder(); long modSeq = nextModSeq(mailbox); while (messages.hasNext()) { MailboxMessage member = messages.next(); Flags originalFlags = member.createFlags(); member.setFlags(flagsUpdateCalculator.buildNewFlags(originalFlags)); Flags newFlags = member.createFlags(); if (UpdatedFlags.flagsChanged(originalFlags, newFlags)) { member.setModSeq(modSeq); changedFlags.add(member); } updatedFlags.add(UpdatedFlags.builder() .uid(member.getUid()) .modSeq(member.getModSeq()) .newFlags(newFlags) .oldFlags(originalFlags) .build()); } return new MessageChangedFlags(updatedFlags.build().iterator(), changedFlags.build()); }
@Override public Map<MessageUid, Flags> setFlags(final Flags flags, final FlagsUpdateMode flagsUpdateMode, final MessageRange set, MailboxSession mailboxSession) throws MailboxException { if (!isWriteable(mailboxSession)) { throw new ReadOnlyException(getMailboxPath(), mailboxSession.getPathDelimiter()); } final SortedMap<MessageUid, Flags> newFlagsByUid = new TreeMap<>(); trimFlags(flags, mailboxSession); final MessageMapper messageMapper = mapperFactory.getMessageMapper(mailboxSession); Iterator<UpdatedFlags> it = messageMapper.execute(() -> messageMapper.updateFlags(getMailboxEntity(), new FlagsUpdateCalculator(flags, flagsUpdateMode), set)); final SortedMap<MessageUid, UpdatedFlags> uFlags = new TreeMap<>(); while (it.hasNext()) { UpdatedFlags flag = it.next(); newFlagsByUid.put(flag.getUid(), flag.getNewFlags()); uFlags.put(flag.getUid(), flag); } dispatcher.flagsUpdated(mailboxSession, new ArrayList<>(uFlags.keySet()), getMailboxEntity(), new ArrayList<>(uFlags.values())); return newFlagsByUid; }
private void dispatchFlagsChange(MailboxSession mailboxSession, MailboxId mailboxId, UpdatedFlags updatedFlags) throws MailboxException { if (updatedFlags.flagsChanged()) { Mailbox mailbox = mailboxSessionMapperFactory.getMailboxMapper(mailboxSession).findMailboxById(mailboxId); dispatcher.flagsUpdated(mailboxSession, updatedFlags.getUid(), mailbox, updatedFlags); } }
private CompletableFuture<FlagsUpdateStageResult> updateIndexesForUpdatesResult(CassandraId mailboxId, FlagsUpdateStageResult result) { return FluentFutureStream.of( result.getSucceeded().stream() .map(Throwing .function((UpdatedFlags updatedFlags) -> indexTableHandler.updateIndexOnFlagsUpdate(mailboxId, updatedFlags)) .fallbackTo(failedindex -> { LOGGER.error("Could not update flag indexes for mailboxId {} UID {}. This will lead to inconsistencies across Cassandra tables", mailboxId, failedindex.getUid()); return CompletableFuture.completedFuture(null); }))) .completableFuture() .thenApply(any -> result); }
public CompletableFuture<Void> updateIndexOnFlagsUpdate(CassandraId mailboxId, UpdatedFlags updatedFlags) { return CompletableFuture.allOf(manageUnseenMessageCountsOnFlagsUpdate(mailboxId, updatedFlags), manageRecentOnFlagsUpdate(mailboxId, updatedFlags), updateFirstUnseenOnFlagsUpdate(mailboxId, updatedFlags), applicableFlagDAO.updateApplicableFlags(mailboxId, ImmutableSet.copyOf(updatedFlags.userFlagIterator())), updateDeletedOnFlagsUpdate(mailboxId, updatedFlags)); }
@Test void updateIndexOnFlagsUpdateShouldNotChangeMessageCount() throws Exception { MailboxMessage message = mock(MailboxMessage.class); when(message.createFlags()).thenReturn(new Flags()); when(message.getUid()).thenReturn(MESSAGE_UID); testee.updateIndexOnAdd(message, MAILBOX_ID).join(); testee.updateIndexOnFlagsUpdate(MAILBOX_ID, UpdatedFlags.builder() .uid(MESSAGE_UID) .newFlags(new Flags(Flags.Flag.RECENT)) .oldFlags(new Flags()) .modSeq(MODSEQ) .build()).join(); Optional<Long> actual = mailboxCounterDAO.countMessagesInMailbox(mailbox).join(); assertThat(actual.isPresent()).isTrue(); assertThat(actual.get()).isEqualTo(1); }
@Test public void isModifiedToSetShouldReturnTrueWhenFlagOnlyInNewFlag() { UpdatedFlags updatedFlags = UpdatedFlags.builder() .newFlags(new Flags(Flags.Flag.RECENT)) .oldFlags(new Flags()) .uid(UID) .modSeq(MOD_SEQ) .build(); assertThat(updatedFlags.isModifiedToSet(Flags.Flag.RECENT)).isTrue(); }
@Test public void isModifiedToUnsetShouldReturnFalseWhenFlagOnlyInNewFlag() { UpdatedFlags updatedFlags = UpdatedFlags.builder() .newFlags(new Flags(Flags.Flag.RECENT)) .oldFlags(new Flags()) .uid(UID) .modSeq(MOD_SEQ) .build(); assertThat(updatedFlags.isModifiedToUnset(Flags.Flag.RECENT)).isFalse(); }
@Test public void isUnchangedShouldReturnTrueWhenFlagIsOnNone() { UpdatedFlags updatedFlags = UpdatedFlags.builder() .newFlags(new Flags()) .oldFlags(new Flags()) .uid(UID) .modSeq(MOD_SEQ) .build(); assertThat(updatedFlags.isUnchanged(Flags.Flag.RECENT)).isTrue(); }
flagUpdateUids.add(u.getUid()); Iterator<Flag> flags = u.systemFlagIterator(); MailboxPath path = sm.getPath(); if (path != null && path.equals(mailboxEvent.getMailboxPath())) { sm.addRecent(u.getUid()); applicableFlags.add(flag.getNewFlags());