From 20b76fc1fd539bf95b8cb0d0ea7044718ec99972 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Tue, 6 Dec 2016 19:31:31 +0100 Subject: Move mail to sent folder after sending it --- common/pipeline.cpp | 2 +- common/synchronizer.cpp | 22 ++++++++++-------- common/synchronizer.h | 4 ++-- examples/dummyresource/resourcefactory.cpp | 4 ++-- .../mailtransportresource.cpp | 27 ++++++++++++++++++---- .../tests/mailtransporttest.cpp | 17 ++++++++++---- 6 files changed, 51 insertions(+), 25 deletions(-) diff --git a/common/pipeline.cpp b/common/pipeline.cpp index 1620667..4ea43eb 100644 --- a/common/pipeline.cpp +++ b/common/pipeline.cpp @@ -258,7 +258,7 @@ KAsync::Job Pipeline::modifiedEntity(void const *command, size_t size) return KAsync::error(0); } - auto newEntity = *ApplicationDomain::ApplicationDomainType::getInMemoryRepresentation(current, current.availableProperties()); + auto newEntity = *ApplicationDomain::ApplicationDomainType::getInMemoryCopy(current, current.availableProperties()); // Apply diff for (const auto &property : changeset) { diff --git a/common/synchronizer.cpp b/common/synchronizer.cpp index 036288e..fec848f 100644 --- a/common/synchronizer.cpp +++ b/common/synchronizer.cpp @@ -82,7 +82,6 @@ void Synchronizer::createEntity(const QByteArray &sinkId, const QByteArray &buff flatbuffers::FlatBufferBuilder entityFbb; mResourceContext.adaptorFactory(bufferType).createBuffer(domainObject, entityFbb); flatbuffers::FlatBufferBuilder fbb; - // This is the resource type and not the domain type auto entityId = fbb.CreateString(sinkId.toStdString()); auto type = fbb.CreateString(bufferType.toStdString()); auto delta = Sink::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); @@ -91,7 +90,7 @@ void Synchronizer::createEntity(const QByteArray &sinkId, const QByteArray &buff enqueueCommand(Sink::Commands::CreateEntityCommand, BufferUtils::extractBuffer(fbb)); } -void Synchronizer::modifyEntity(const QByteArray &sinkId, qint64 revision, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject) +void Synchronizer::modifyEntity(const QByteArray &sinkId, qint64 revision, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject, const QByteArray &newResource, bool remove) { // FIXME removals QByteArrayList deletedProperties; @@ -103,10 +102,10 @@ void Synchronizer::modifyEntity(const QByteArray &sinkId, qint64 revision, const auto entityId = fbb.CreateString(sinkId.toStdString()); auto modifiedProperties = BufferUtils::toVector(fbb, domainObject.changedProperties()); auto deletions = BufferUtils::toVector(fbb, deletedProperties); - // This is the resource type and not the domain type auto type = fbb.CreateString(bufferType.toStdString()); auto delta = Sink::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); - auto location = Sink::Commands::CreateModifyEntity(fbb, revision, entityId, deletions, type, delta, replayToSource, modifiedProperties); + auto resource = newResource.isEmpty() ? 0 : fbb.CreateString(newResource.constData()); + auto location = Sink::Commands::CreateModifyEntity(fbb, revision, entityId, deletions, type, delta, replayToSource, modifiedProperties, resource, remove); Sink::Commands::FinishModifyEntityBuffer(fbb, location); enqueueCommand(Sink::Commands::ModifyEntityCommand, BufferUtils::extractBuffer(fbb)); } @@ -247,9 +246,9 @@ QByteArrayList Synchronizer::resolveFilter(const QueryBase::Comparator &filter) } template -void Synchronizer::modify(const DomainType &entity) +void Synchronizer::modify(const DomainType &entity, const QByteArray &newResource, bool remove) { - modifyEntity(entity.identifier(), entity.revision(), ApplicationDomain::getTypeName(), entity); + modifyEntity(entity.identifier(), entity.revision(), ApplicationDomain::getTypeName(), entity, newResource, remove); } QList Synchronizer::getSyncRequests(const Sink::QueryBase &query) @@ -483,9 +482,12 @@ bool Synchronizer::allChangesReplayed() #define REGISTER_TYPE(T) \ template void Synchronizer::createOrModify(const QByteArray &bufferType, const QByteArray &remoteId, const T &entity, const QHash &mergeCriteria); \ - template void Synchronizer::modify(const T &entity); + template void Synchronizer::modify(const T &entity, const QByteArray &newResource, bool remove); + +#define SINK_REGISTER_TYPES() \ + REGISTER_TYPE(ApplicationDomain::Event); \ + REGISTER_TYPE(ApplicationDomain::Mail); \ + REGISTER_TYPE(ApplicationDomain::Folder); \ -REGISTER_TYPE(ApplicationDomain::Event); -REGISTER_TYPE(ApplicationDomain::Mail); -REGISTER_TYPE(ApplicationDomain::Folder); +SINK_REGISTER_TYPES() diff --git a/common/synchronizer.h b/common/synchronizer.h index f9b834e..00b5fba 100644 --- a/common/synchronizer.h +++ b/common/synchronizer.h @@ -79,7 +79,7 @@ protected: void enqueueCommand(int commandId, const QByteArray &data); void createEntity(const QByteArray &localId, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject); - void modifyEntity(const QByteArray &localId, qint64 revision, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject); + void modifyEntity(const QByteArray &localId, qint64 revision, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject, const QByteArray &newResource = QByteArray(), bool remove = false); void deleteEntity(const QByteArray &localId, qint64 revision, const QByteArray &bufferType); /** @@ -109,7 +109,7 @@ protected: // template // void create(const DomainType &entity); template - void modify(const DomainType &entity); + void modify(const DomainType &entity, const QByteArray &newResource = QByteArray(), bool remove = false); // template // void remove(const DomainType &entity); QByteArrayList resolveFilter(const QueryBase::Comparator &filter); diff --git a/examples/dummyresource/resourcefactory.cpp b/examples/dummyresource/resourcefactory.cpp index 26faf67..d230ea3 100644 --- a/examples/dummyresource/resourcefactory.cpp +++ b/examples/dummyresource/resourcefactory.cpp @@ -35,6 +35,7 @@ #include "synchronizer.h" #include "inspector.h" #include "mailpreprocessor.h" +#include "specialpurposepreprocessor.h" #include #include @@ -125,7 +126,6 @@ class DummySynchronizer : public Sink::Synchronizer { synchronize(ENTITY_TYPE_FOLDER, DummyStore::instance().folders(), [this](const QByteArray &ridBuffer, const QMap &data) { return createFolder(ridBuffer, data); }); - SinkLog() << "Done Synchronizing"; }); } @@ -164,7 +164,7 @@ DummyResource::DummyResource(const Sink::ResourceContext &resourceContext, const setupSynchronizer(QSharedPointer::create(resourceContext)); setupInspector(QSharedPointer::create(resourceContext)); setupPreprocessors(ENTITY_TYPE_MAIL, - QVector() << new MailPropertyExtractor); + QVector() << new MailPropertyExtractor << new MimeMessageMover << new SpecialPurposeProcessor{resourceContext.resourceType, resourceContext.instanceId()}); setupPreprocessors(ENTITY_TYPE_FOLDER, QVector()); setupPreprocessors(ENTITY_TYPE_EVENT, diff --git a/examples/mailtransportresource/mailtransportresource.cpp b/examples/mailtransportresource/mailtransportresource.cpp index 524b411..08a8748 100644 --- a/examples/mailtransportresource/mailtransportresource.cpp +++ b/examples/mailtransportresource/mailtransportresource.cpp @@ -23,6 +23,7 @@ #include "resourceconfig.h" #include "definitions.h" #include "inspector.h" +#include "store.h" #include #include #include @@ -81,10 +82,9 @@ public: KAsync::Job synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE { - SinkLog() << " Synchronizing"; return KAsync::start([this](KAsync::Future future) { QList toSend; - SinkLog() << " Looking for mail"; + SinkLog() << "Looking for mails to send."; store().readAll([&](const ApplicationDomain::Mail &mail) -> bool { SinkTrace() << "Found mail: " << mail.identifier(); if (!mail.getSent()) { @@ -92,13 +92,25 @@ public: } return true; }); + SinkLog() << "Found " << toSend.size() << " mails to send"; auto job = KAsync::null(); for (const auto &m : toSend) { - job = job.then(send(m, mSettings)).syncThen([this, m] { + job = job.then(send(m, mSettings)) + .then([this, m] { auto modifiedMail = ApplicationDomain::Mail(mResourceInstanceIdentifier, m.identifier(), m.revision(), QSharedPointer::create()); modifiedMail.setSent(true); - modify(modifiedMail); - //TODO copy to a sent mail folder as well + + auto resource = Store::readOne(Query{}.filter(mResourceInstanceIdentifier).request()); + //Then copy the mail to the target resource + Query query; + query.containsFilter(ApplicationDomain::ResourceCapabilities::Mail::sent); + query.filter(resource.getAccount()); + return Store::fetchOne(query) + .then([this, modifiedMail](const ApplicationDomain::SinkResource &resource) -> KAsync::Job { + //First modify the mail to have the sent property set to true + modify(modifiedMail, resource.identifier(), true); + return KAsync::null(); + }); }); } job = job.syncThen([&future](const KAsync::Error &) { @@ -108,6 +120,11 @@ public: }); } + bool canReplay(const QByteArray &type, const QByteArray &key, const QByteArray &value) Q_DECL_OVERRIDE + { + return false; + } + KAsync::Job replay(const ApplicationDomain::Mail &mail, Sink::Operation operation, const QByteArray &oldRemoteId, const QList &changedProperties) Q_DECL_OVERRIDE { if (operation == Sink::Operation_Creation) { diff --git a/examples/mailtransportresource/tests/mailtransporttest.cpp b/examples/mailtransportresource/tests/mailtransporttest.cpp index 410e17b..cb78603 100644 --- a/examples/mailtransportresource/tests/mailtransporttest.cpp +++ b/examples/mailtransportresource/tests/mailtransporttest.cpp @@ -27,6 +27,7 @@ class MailtransportTest : public QObject return resource; } QByteArray mResourceInstanceIdentifier; + QByteArray mStorageResource; private slots: @@ -37,6 +38,11 @@ private slots: QVERIFY(!resource.identifier().isEmpty()); VERIFYEXEC(Store::create(resource)); mResourceInstanceIdentifier = resource.identifier(); + + auto dummyResource = ApplicationDomain::DummyResource::create("account1"); + VERIFYEXEC(Store::create(dummyResource)); + mStorageResource = dummyResource.identifier(); + QVERIFY(!mStorageResource.isEmpty()); } void cleanup() @@ -61,11 +67,12 @@ private slots: VERIFYEXEC(Store::create(mail)); VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier)); VERIFYEXEC(Store::synchronize(Query().resourceFilter(mResourceInstanceIdentifier))); - VERIFYEXEC(ResourceControl::inspect(ResourceControl::Inspection::ExistenceInspection(mail, true))); - - auto sentMail = Store::readOne(Query(mail).request().request()); - QVERIFY(sentMail.getSent()); - QVERIFY(!sentMail.getSubject().isEmpty()); + QTest::qWait(100); + VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mStorageResource)); + auto mailInSentMailFolder = Store::readOne(Query().resourceFilter(mStorageResource).filter(true).request().request().request().request()); + //Check that the mail has been moved to the sent mail folder + QVERIFY(mailInSentMailFolder.getSent()); + QVERIFY(!mailInSentMailFolder.getSubject().isEmpty()); } //TODO test mail that fails to be sent. add a special header to the mail and have the resource fail sending. Ensure we can modify the mail to fix sending of the message. -- cgit v1.2.3