service/MailSelectionMutationService.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include "data/MailSelectionMutation.h" | ||
| 4 | #include "data/MutationJournal.h" | ||
| 5 | #include <QObject> | ||
| 6 | #include <QThreadPool> | ||
| 7 | #include <functional> | ||
| 8 | |||
| 9 | // Accepted intents survive consumer destruction. One worker owns writes; | ||
| 10 | // unlike selection reads, newer input never cancels an earlier user action. | ||
| 11 | class MailSelectionMutationService final : public QObject { | ||
| 12 | public: | ||
| 13 | struct FlagResult { | ||
| 14 | bool journaled = false; | ||
| 15 | quint32 flags = 0; | ||
| 16 | MutationRecord record; | ||
| 17 | QString error; | ||
| 18 | }; | ||
| 19 | struct MoveJournalResult { | ||
| 20 | bool journaled = false; | ||
| 21 | QList<qint64> tokens; // same order as the submitted records | ||
| 22 | QString error; | ||
| 23 | }; | ||
| 24 | using Callback = std::function<void(MailSelectionMoveResult)>; | ||
| 25 | using MoveJournalCallback = std::function<void(MoveJournalResult)>; | ||
| 26 | using CancelCallback = std::function<void(MailSelectionCancelResult)>; | ||
| 27 | using FlagCallback = std::function<void(FlagResult)>; | ||
| 28 | static constexpr int MaximumRequests = 4; | ||
| 29 | explicit MailSelectionMutationService(QObject *parent = nullptr); | ||
| 30 | ~MailSelectionMutationService() override; | ||
| 31 | static MailSelectionMutationService *shared(); | ||
| 32 | void move(QObject *owner, QString databasePath, | ||
| 33 | std::shared_ptr<const MailSelectionSnapshot> selection, | ||
| 34 | QString targetFolder, Callback callback); | ||
| 35 | void cancelQueuedMove(QObject *owner, QString databasePath, | ||
| 36 | MailSelectionMoveResult action, CancelCallback callback); | ||
| 37 | void setFlag(QObject *owner, QString databasePath, MailId mailId, | ||
| 38 | MutationKind kind, bool desiredState, FlagCallback callback); | ||
| 39 | // Label (IMAP keyword) desired state on the same serial durable writer: | ||
| 40 | // journal and mail_labels row commit together; FlagResult.flags is unused. | ||
| 41 | void setKeyword(QObject *owner, QString databasePath, MailId mailId, | ||
| 42 | QString keyword, bool desiredState, FlagCallback callback); | ||
| 43 | // Journals already validated Move records (one atomic transaction) on the | ||
| 44 | // same serial durable writer as setFlag, so flag and move intents keep | ||
| 45 | // their submission order. The GUI thread never waits for the write lock. | ||
| 46 | void enqueueMoves(QObject *owner, QString databasePath, | ||
| 47 | QList<MutationRecord> records, MoveJournalCallback callback); | ||
| 48 | // MAIL-SELECTION-ACTIONS: one desired state for every message of a | ||
| 49 | // selection (MailCache::enqueueSelectionState) on the same serial durable | ||
| 50 | // writer, so it keeps its order with single flag, label and move intents. | ||
| 51 | using StateCallback = std::function<void(MailSelectionStateResult)>; | ||
| 52 | void setSelectionState(QObject *owner, QString databasePath, | ||
| 53 | MailSelectionStateRequest request, StateCallback callback); | ||
| 54 | 11 | int pendingCount() const { return m_pendingCount; } | |
| 55 | // Flag and label writes queued or running on the (single, FIFO) flag worker. | ||
| 56 | 6 | int flagPendingCount() const { return m_flagPendingCount; } | |
| 57 | private: | ||
| 58 | void stop(); | ||
| 59 | // Registered with qAddPostRoutine by shared(); see the .cpp. | ||
| 60 | static void stopSharedBeforeApplicationTeardown(); | ||
| 61 | QThreadPool m_pool; | ||
| 62 | QThreadPool m_flagPool; | ||
| 63 | int m_pendingCount = 0; | ||
| 64 | int m_flagPendingCount = 0; | ||
| 65 | bool m_stopping = false; | ||
| 66 | }; | ||
| 67 |