summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2016-12-06 19:31:31 +0100
committerChristian Mollekopf <chrigi_1@fastmail.fm>2016-12-06 19:31:31 +0100
commit20b76fc1fd539bf95b8cb0d0ea7044718ec99972 (patch)
tree03da4339c8879e4d45e0c5a903b6bfb410c4bf31
parent62c7b07c0d62f8f03e22556bf62ed90d267c6d2e (diff)
downloadsink-20b76fc1fd539bf95b8cb0d0ea7044718ec99972.tar.gz
sink-20b76fc1fd539bf95b8cb0d0ea7044718ec99972.zip
Move mail to sent folder after sending it
-rw-r--r--common/pipeline.cpp2
-rw-r--r--common/synchronizer.cpp22
-rw-r--r--common/synchronizer.h4
-rw-r--r--examples/dummyresource/resourcefactory.cpp4
-rw-r--r--examples/mailtransportresource/mailtransportresource.cpp27
-rw-r--r--examples/mailtransportresource/tests/mailtransporttest.cpp17
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<qint64> Pipeline::modifiedEntity(void const *command, size_t size)
258 return KAsync::error<qint64>(0); 258 return KAsync::error<qint64>(0);
259 } 259 }
260 260
261 auto newEntity = *ApplicationDomain::ApplicationDomainType::getInMemoryRepresentation<ApplicationDomain::ApplicationDomainType>(current, current.availableProperties()); 261 auto newEntity = *ApplicationDomain::ApplicationDomainType::getInMemoryCopy<ApplicationDomain::ApplicationDomainType>(current, current.availableProperties());
262 262
263 // Apply diff 263 // Apply diff
264 for (const auto &property : changeset) { 264 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
82 flatbuffers::FlatBufferBuilder entityFbb; 82 flatbuffers::FlatBufferBuilder entityFbb;
83 mResourceContext.adaptorFactory(bufferType).createBuffer(domainObject, entityFbb); 83 mResourceContext.adaptorFactory(bufferType).createBuffer(domainObject, entityFbb);
84 flatbuffers::FlatBufferBuilder fbb; 84 flatbuffers::FlatBufferBuilder fbb;
85 // This is the resource type and not the domain type
86 auto entityId = fbb.CreateString(sinkId.toStdString()); 85 auto entityId = fbb.CreateString(sinkId.toStdString());
87 auto type = fbb.CreateString(bufferType.toStdString()); 86 auto type = fbb.CreateString(bufferType.toStdString());
88 auto delta = Sink::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); 87 auto delta = Sink::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize());
@@ -91,7 +90,7 @@ void Synchronizer::createEntity(const QByteArray &sinkId, const QByteArray &buff
91 enqueueCommand(Sink::Commands::CreateEntityCommand, BufferUtils::extractBuffer(fbb)); 90 enqueueCommand(Sink::Commands::CreateEntityCommand, BufferUtils::extractBuffer(fbb));
92} 91}
93 92
94void Synchronizer::modifyEntity(const QByteArray &sinkId, qint64 revision, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject) 93void Synchronizer::modifyEntity(const QByteArray &sinkId, qint64 revision, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject, const QByteArray &newResource, bool remove)
95{ 94{
96 // FIXME removals 95 // FIXME removals
97 QByteArrayList deletedProperties; 96 QByteArrayList deletedProperties;
@@ -103,10 +102,10 @@ void Synchronizer::modifyEntity(const QByteArray &sinkId, qint64 revision, const
103 auto entityId = fbb.CreateString(sinkId.toStdString()); 102 auto entityId = fbb.CreateString(sinkId.toStdString());
104 auto modifiedProperties = BufferUtils::toVector(fbb, domainObject.changedProperties()); 103 auto modifiedProperties = BufferUtils::toVector(fbb, domainObject.changedProperties());
105 auto deletions = BufferUtils::toVector(fbb, deletedProperties); 104 auto deletions = BufferUtils::toVector(fbb, deletedProperties);
106 // This is the resource type and not the domain type
107 auto type = fbb.CreateString(bufferType.toStdString()); 105 auto type = fbb.CreateString(bufferType.toStdString());
108 auto delta = Sink::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); 106 auto delta = Sink::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize());
109 auto location = Sink::Commands::CreateModifyEntity(fbb, revision, entityId, deletions, type, delta, replayToSource, modifiedProperties); 107 auto resource = newResource.isEmpty() ? 0 : fbb.CreateString(newResource.constData());
108 auto location = Sink::Commands::CreateModifyEntity(fbb, revision, entityId, deletions, type, delta, replayToSource, modifiedProperties, resource, remove);
110 Sink::Commands::FinishModifyEntityBuffer(fbb, location); 109 Sink::Commands::FinishModifyEntityBuffer(fbb, location);
111 enqueueCommand(Sink::Commands::ModifyEntityCommand, BufferUtils::extractBuffer(fbb)); 110 enqueueCommand(Sink::Commands::ModifyEntityCommand, BufferUtils::extractBuffer(fbb));
112} 111}
@@ -247,9 +246,9 @@ QByteArrayList Synchronizer::resolveFilter(const QueryBase::Comparator &filter)
247} 246}
248 247
249template<typename DomainType> 248template<typename DomainType>
250void Synchronizer::modify(const DomainType &entity) 249void Synchronizer::modify(const DomainType &entity, const QByteArray &newResource, bool remove)
251{ 250{
252 modifyEntity(entity.identifier(), entity.revision(), ApplicationDomain::getTypeName<DomainType>(), entity); 251 modifyEntity(entity.identifier(), entity.revision(), ApplicationDomain::getTypeName<DomainType>(), entity, newResource, remove);
253} 252}
254 253
255QList<Synchronizer::SyncRequest> Synchronizer::getSyncRequests(const Sink::QueryBase &query) 254QList<Synchronizer::SyncRequest> Synchronizer::getSyncRequests(const Sink::QueryBase &query)
@@ -483,9 +482,12 @@ bool Synchronizer::allChangesReplayed()
483 482
484#define REGISTER_TYPE(T) \ 483#define REGISTER_TYPE(T) \
485 template void Synchronizer::createOrModify(const QByteArray &bufferType, const QByteArray &remoteId, const T &entity, const QHash<QByteArray, Sink::Query::Comparator> &mergeCriteria); \ 484 template void Synchronizer::createOrModify(const QByteArray &bufferType, const QByteArray &remoteId, const T &entity, const QHash<QByteArray, Sink::Query::Comparator> &mergeCriteria); \
486 template void Synchronizer::modify(const T &entity); 485 template void Synchronizer::modify(const T &entity, const QByteArray &newResource, bool remove);
486
487#define SINK_REGISTER_TYPES() \
488 REGISTER_TYPE(ApplicationDomain::Event); \
489 REGISTER_TYPE(ApplicationDomain::Mail); \
490 REGISTER_TYPE(ApplicationDomain::Folder); \
487 491
488REGISTER_TYPE(ApplicationDomain::Event); 492SINK_REGISTER_TYPES()
489REGISTER_TYPE(ApplicationDomain::Mail);
490REGISTER_TYPE(ApplicationDomain::Folder);
491 493
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:
79 void enqueueCommand(int commandId, const QByteArray &data); 79 void enqueueCommand(int commandId, const QByteArray &data);
80 80
81 void createEntity(const QByteArray &localId, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject); 81 void createEntity(const QByteArray &localId, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject);
82 void modifyEntity(const QByteArray &localId, qint64 revision, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject); 82 void modifyEntity(const QByteArray &localId, qint64 revision, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject, const QByteArray &newResource = QByteArray(), bool remove = false);
83 void deleteEntity(const QByteArray &localId, qint64 revision, const QByteArray &bufferType); 83 void deleteEntity(const QByteArray &localId, qint64 revision, const QByteArray &bufferType);
84 84
85 /** 85 /**
@@ -109,7 +109,7 @@ protected:
109 // template <typename DomainType> 109 // template <typename DomainType>
110 // void create(const DomainType &entity); 110 // void create(const DomainType &entity);
111 template <typename DomainType> 111 template <typename DomainType>
112 void modify(const DomainType &entity); 112 void modify(const DomainType &entity, const QByteArray &newResource = QByteArray(), bool remove = false);
113 // template <typename DomainType> 113 // template <typename DomainType>
114 // void remove(const DomainType &entity); 114 // void remove(const DomainType &entity);
115 QByteArrayList resolveFilter(const QueryBase::Comparator &filter); 115 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 @@
35#include "synchronizer.h" 35#include "synchronizer.h"
36#include "inspector.h" 36#include "inspector.h"
37#include "mailpreprocessor.h" 37#include "mailpreprocessor.h"
38#include "specialpurposepreprocessor.h"
38#include <QDate> 39#include <QDate>
39#include <QUuid> 40#include <QUuid>
40 41
@@ -125,7 +126,6 @@ class DummySynchronizer : public Sink::Synchronizer {
125 synchronize(ENTITY_TYPE_FOLDER, DummyStore::instance().folders(), [this](const QByteArray &ridBuffer, const QMap<QString, QVariant> &data) { 126 synchronize(ENTITY_TYPE_FOLDER, DummyStore::instance().folders(), [this](const QByteArray &ridBuffer, const QMap<QString, QVariant> &data) {
126 return createFolder(ridBuffer, data); 127 return createFolder(ridBuffer, data);
127 }); 128 });
128 SinkLog() << "Done Synchronizing";
129 }); 129 });
130 } 130 }
131 131
@@ -164,7 +164,7 @@ DummyResource::DummyResource(const Sink::ResourceContext &resourceContext, const
164 setupSynchronizer(QSharedPointer<DummySynchronizer>::create(resourceContext)); 164 setupSynchronizer(QSharedPointer<DummySynchronizer>::create(resourceContext));
165 setupInspector(QSharedPointer<DummyInspector>::create(resourceContext)); 165 setupInspector(QSharedPointer<DummyInspector>::create(resourceContext));
166 setupPreprocessors(ENTITY_TYPE_MAIL, 166 setupPreprocessors(ENTITY_TYPE_MAIL,
167 QVector<Sink::Preprocessor*>() << new MailPropertyExtractor); 167 QVector<Sink::Preprocessor*>() << new MailPropertyExtractor << new MimeMessageMover << new SpecialPurposeProcessor{resourceContext.resourceType, resourceContext.instanceId()});
168 setupPreprocessors(ENTITY_TYPE_FOLDER, 168 setupPreprocessors(ENTITY_TYPE_FOLDER,
169 QVector<Sink::Preprocessor*>()); 169 QVector<Sink::Preprocessor*>());
170 setupPreprocessors(ENTITY_TYPE_EVENT, 170 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 @@
23#include "resourceconfig.h" 23#include "resourceconfig.h"
24#include "definitions.h" 24#include "definitions.h"
25#include "inspector.h" 25#include "inspector.h"
26#include "store.h"
26#include <QDir> 27#include <QDir>
27#include <QFileInfo> 28#include <QFileInfo>
28#include <QSettings> 29#include <QSettings>
@@ -81,10 +82,9 @@ public:
81 82
82 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE 83 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE
83 { 84 {
84 SinkLog() << " Synchronizing";
85 return KAsync::start<void>([this](KAsync::Future<void> future) { 85 return KAsync::start<void>([this](KAsync::Future<void> future) {
86 QList<ApplicationDomain::Mail> toSend; 86 QList<ApplicationDomain::Mail> toSend;
87 SinkLog() << " Looking for mail"; 87 SinkLog() << "Looking for mails to send.";
88 store().readAll<ApplicationDomain::Mail>([&](const ApplicationDomain::Mail &mail) -> bool { 88 store().readAll<ApplicationDomain::Mail>([&](const ApplicationDomain::Mail &mail) -> bool {
89 SinkTrace() << "Found mail: " << mail.identifier(); 89 SinkTrace() << "Found mail: " << mail.identifier();
90 if (!mail.getSent()) { 90 if (!mail.getSent()) {
@@ -92,13 +92,25 @@ public:
92 } 92 }
93 return true; 93 return true;
94 }); 94 });
95 SinkLog() << "Found " << toSend.size() << " mails to send";
95 auto job = KAsync::null<void>(); 96 auto job = KAsync::null<void>();
96 for (const auto &m : toSend) { 97 for (const auto &m : toSend) {
97 job = job.then(send(m, mSettings)).syncThen<void>([this, m] { 98 job = job.then(send(m, mSettings))
99 .then<void>([this, m] {
98 auto modifiedMail = ApplicationDomain::Mail(mResourceInstanceIdentifier, m.identifier(), m.revision(), QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); 100 auto modifiedMail = ApplicationDomain::Mail(mResourceInstanceIdentifier, m.identifier(), m.revision(), QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create());
99 modifiedMail.setSent(true); 101 modifiedMail.setSent(true);
100 modify(modifiedMail); 102
101 //TODO copy to a sent mail folder as well 103 auto resource = Store::readOne<ApplicationDomain::SinkResource>(Query{}.filter(mResourceInstanceIdentifier).request<ApplicationDomain::SinkResource::Account>());
104 //Then copy the mail to the target resource
105 Query query;
106 query.containsFilter<ApplicationDomain::SinkResource::Capabilities>(ApplicationDomain::ResourceCapabilities::Mail::sent);
107 query.filter<ApplicationDomain::SinkResource::Account>(resource.getAccount());
108 return Store::fetchOne<ApplicationDomain::SinkResource>(query)
109 .then<void, ApplicationDomain::SinkResource>([this, modifiedMail](const ApplicationDomain::SinkResource &resource) -> KAsync::Job<void> {
110 //First modify the mail to have the sent property set to true
111 modify(modifiedMail, resource.identifier(), true);
112 return KAsync::null<void>();
113 });
102 }); 114 });
103 } 115 }
104 job = job.syncThen<void>([&future](const KAsync::Error &) { 116 job = job.syncThen<void>([&future](const KAsync::Error &) {
@@ -108,6 +120,11 @@ public:
108 }); 120 });
109 } 121 }
110 122
123 bool canReplay(const QByteArray &type, const QByteArray &key, const QByteArray &value) Q_DECL_OVERRIDE
124 {
125 return false;
126 }
127
111 KAsync::Job<QByteArray> replay(const ApplicationDomain::Mail &mail, Sink::Operation operation, const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE 128 KAsync::Job<QByteArray> replay(const ApplicationDomain::Mail &mail, Sink::Operation operation, const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE
112 { 129 {
113 if (operation == Sink::Operation_Creation) { 130 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
27 return resource; 27 return resource;
28 } 28 }
29 QByteArray mResourceInstanceIdentifier; 29 QByteArray mResourceInstanceIdentifier;
30 QByteArray mStorageResource;
30 31
31private slots: 32private slots:
32 33
@@ -37,6 +38,11 @@ private slots:
37 QVERIFY(!resource.identifier().isEmpty()); 38 QVERIFY(!resource.identifier().isEmpty());
38 VERIFYEXEC(Store::create(resource)); 39 VERIFYEXEC(Store::create(resource));
39 mResourceInstanceIdentifier = resource.identifier(); 40 mResourceInstanceIdentifier = resource.identifier();
41
42 auto dummyResource = ApplicationDomain::DummyResource::create("account1");
43 VERIFYEXEC(Store::create(dummyResource));
44 mStorageResource = dummyResource.identifier();
45 QVERIFY(!mStorageResource.isEmpty());
40 } 46 }
41 47
42 void cleanup() 48 void cleanup()
@@ -61,11 +67,12 @@ private slots:
61 VERIFYEXEC(Store::create(mail)); 67 VERIFYEXEC(Store::create(mail));
62 VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier)); 68 VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier));
63 VERIFYEXEC(Store::synchronize(Query().resourceFilter(mResourceInstanceIdentifier))); 69 VERIFYEXEC(Store::synchronize(Query().resourceFilter(mResourceInstanceIdentifier)));
64 VERIFYEXEC(ResourceControl::inspect<ApplicationDomain::Mail>(ResourceControl::Inspection::ExistenceInspection(mail, true))); 70 QTest::qWait(100);
65 71 VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mStorageResource));
66 auto sentMail = Store::readOne<ApplicationDomain::Mail>(Query(mail).request<Mail::Sent>().request<Mail::Subject>()); 72 auto mailInSentMailFolder = Store::readOne<ApplicationDomain::Mail>(Query().resourceFilter(mStorageResource).filter<Mail::Sent>(true).request<Mail::Subject>().request<Mail::Folder>().request<Mail::MimeMessage>().request<Mail::Sent>());
67 QVERIFY(sentMail.getSent()); 73 //Check that the mail has been moved to the sent mail folder
68 QVERIFY(!sentMail.getSubject().isEmpty()); 74 QVERIFY(mailInSentMailFolder.getSent());
75 QVERIFY(!mailInSentMailFolder.getSubject().isEmpty());
69 } 76 }
70 77
71 //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. 78 //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.