diff --git a/src/database/Database.h b/src/database/Database.h index 3c6d35e..d4107eb 100644 --- a/src/database/Database.h +++ b/src/database/Database.h @@ -178,6 +178,7 @@ namespace openmittsu { virtual void setContactAccountStatusBatch(ContactToAccountStatusMap const& status) = 0; virtual void setContactFeatureLevelBatch(ContactToFeatureLevelMap const& featureLevels) = 0; virtual GroupToTitleMap getKnownGroupsContainingMember(openmittsu::protocol::ContactId const& identity) const = 0; + virtual openmittsu::protocol::MessageTime getGroupLastSyncRequestTime(openmittsu::protocol::GroupId const& group) = 0; // Deleting Messages virtual void deleteContactMessageByUuid(openmittsu::protocol::ContactId const& contact, QString const& uuid) = 0; diff --git a/src/database/DatabaseWrapper.cpp b/src/database/DatabaseWrapper.cpp index e397402..fe9bcf6 100644 --- a/src/database/DatabaseWrapper.cpp +++ b/src/database/DatabaseWrapper.cpp @@ -453,6 +453,10 @@ namespace openmittsu { OPENMITTSU_DATABASEWRAPPER_WRAP_RETURN(getKnownGroupsContainingMember, GroupToTitleMap, Q_ARG(openmittsu::protocol::ContactId const&, identity)); } + openmittsu::protocol::MessageTime DatabaseWrapper::getGroupLastSyncRequestTime(openmittsu::protocol::GroupId const& group) { + OPENMITTSU_DATABASEWRAPPER_WRAP_RETURN(getGroupLastSyncRequestTime, openmittsu::protocol::MessageTime, Q_ARG(openmittsu::protocol::GroupId const&, group)); + } + void DatabaseWrapper::deleteContactMessageByUuid(openmittsu::protocol::ContactId const& contact, QString const& uuid) { OPENMITTSU_DATABASEWRAPPER_WRAP_VOID(deleteContactMessageByUuid, Q_ARG(openmittsu::protocol::ContactId const&, contact), Q_ARG(QString const&, uuid)); } diff --git a/src/database/DatabaseWrapper.h b/src/database/DatabaseWrapper.h index 2887ab1..fc71c23 100644 --- a/src/database/DatabaseWrapper.h +++ b/src/database/DatabaseWrapper.h @@ -137,6 +137,7 @@ namespace openmittsu { virtual void setContactAccountStatusBatch(ContactToAccountStatusMap const& status) override; virtual void setContactFeatureLevelBatch(ContactToFeatureLevelMap const& featureLevels) override; virtual GroupToTitleMap getKnownGroupsContainingMember(openmittsu::protocol::ContactId const& identity) const override; + virtual openmittsu::protocol::MessageTime getGroupLastSyncRequestTime(openmittsu::protocol::GroupId const& group) override; // Deleting Messages virtual void deleteContactMessageByUuid(openmittsu::protocol::ContactId const& contact, QString const& uuid) override; virtual void deleteContactMessagesByAge(openmittsu::protocol::ContactId const& contact, bool olderThanOrNewerThan, openmittsu::protocol::MessageTime const& timePoint) override; diff --git a/src/database/SimpleDatabase.cpp b/src/database/SimpleDatabase.cpp index 2169ddd..aec2fca 100644 --- a/src/database/SimpleDatabase.cpp +++ b/src/database/SimpleDatabase.cpp @@ -1408,6 +1408,10 @@ namespace openmittsu { return m_contactAndGroupDataProvider.getKnownGroupsContainingMember(identity); } + openmittsu::protocol::MessageTime SimpleDatabase::getGroupLastSyncRequestTime(openmittsu::protocol::GroupId const& group) { + return internal::DatabaseGroupMessageCursor::getLastSyncRequestTimeByUs(this, group); + } + internal::DatabaseContactMessageCursor SimpleDatabase::getMessageCursor(openmittsu::protocol::ContactId const& contact) { if (!hasContact(contact)) { throw openmittsu::exceptions::InternalErrorException() << "Could not create message cursor because the given contact " << contact.toString() << " is unknown!"; diff --git a/src/database/SimpleDatabase.h b/src/database/SimpleDatabase.h index 77b0f43..c71f66a 100644 --- a/src/database/SimpleDatabase.h +++ b/src/database/SimpleDatabase.h @@ -146,6 +146,7 @@ namespace openmittsu { virtual QSet getContactsRequiringFeatureLevelCheck(int maximalAgeInSeconds) const override; virtual QSet getContactsRequiringAccountStatusCheck(int maximalAgeInSeconds) const override; virtual GroupToTitleMap getKnownGroupsContainingMember(openmittsu::protocol::ContactId const& identity) const override; + virtual openmittsu::protocol::MessageTime getGroupLastSyncRequestTime(openmittsu::protocol::GroupId const& group) override; virtual std::shared_ptr getBackup() const override; diff --git a/src/database/internal/DatabaseGroupMessageCursor.cpp b/src/database/internal/DatabaseGroupMessageCursor.cpp index 865d3ae..70c7178 100644 --- a/src/database/internal/DatabaseGroupMessageCursor.cpp +++ b/src/database/internal/DatabaseGroupMessageCursor.cpp @@ -184,6 +184,30 @@ namespace openmittsu { } } + openmittsu::protocol::MessageTime DatabaseGroupMessageCursor::getLastSyncRequestTimeByUs(InternalDatabaseInterface* database, openmittsu::protocol::GroupId const& group) { + QString const selectQuery = QStringLiteral("SELECT `uid`, `sort_by` FROM `group_messages` WHERE `group_id` = :groupId AND `is_outbox` = 1 AND `group_message_type` = :groupMessageType ORDER BY `sort_by` DESC LIMIT 1"); + { + QSqlQuery query(database->getQueryObject()); + if (!query.prepare(selectQuery)) { + throw openmittsu::exceptions::InternalErrorException() << "Could not prepare group message enumeration query. SQL error: " << query.lastError().text().toStdString(); + } + query.bindValue(QStringLiteral(":groupId"), QVariant(group.groupIdWithoutOwnerToQString())); + query.bindValue(QStringLiteral(":groupMessageType"), QVariant(GroupMessageTypeHelper::toQString(GroupMessageType::SYNC_REQUEST))); + if (query.exec() && query.isSelect()) { + if (query.next()) { + QString const uuid(query.value(QStringLiteral("uid")).toString()); + qint64 const messageTime = query.value(QStringLiteral("sort_by")).toLongLong(); + return openmittsu::protocol::MessageTime::fromDatabase(messageTime); + } else { + LOGGER_DEBUG("Failed to find an outgoing group sync request for group {}.", group.toString()); + return openmittsu::protocol::MessageTime::fromDatabase(-1); // This creates a "null" MessageTime + } + } else { + throw openmittsu::exceptions::InternalErrorException() << "Could not execute group message enumeration query for table group_messages. Query error: " << query.lastError().text().toStdString(); + } + } + } + } } } diff --git a/src/database/internal/DatabaseGroupMessageCursor.h b/src/database/internal/DatabaseGroupMessageCursor.h index 1515e20..2b33517 100644 --- a/src/database/internal/DatabaseGroupMessageCursor.h +++ b/src/database/internal/DatabaseGroupMessageCursor.h @@ -29,6 +29,7 @@ namespace openmittsu { static void deleteMessagesByAge(InternalDatabaseInterface* database, openmittsu::protocol::GroupId const& group, bool olderThanOrNewerThan, openmittsu::protocol::MessageTime const& timePoint); static void deleteMessagesByCount(InternalDatabaseInterface* database, openmittsu::protocol::GroupId const& group, bool oldestOrNewest, int count); + static openmittsu::protocol::MessageTime getLastSyncRequestTimeByUs(InternalDatabaseInterface* database, openmittsu::protocol::GroupId const& group); protected: virtual QString getWhereString() const override; virtual void bindWhereStringValues(QSqlQuery& query) const override; diff --git a/src/dataproviders/SimpleMessageCenter.cpp b/src/dataproviders/SimpleMessageCenter.cpp index aa4897f..96887af 100644 --- a/src/dataproviders/SimpleMessageCenter.cpp +++ b/src/dataproviders/SimpleMessageCenter.cpp @@ -1238,7 +1238,22 @@ namespace openmittsu { void SimpleMessageCenter::requestSyncForGroupIfApplicable(openmittsu::protocol::GroupId const& group) { if (!m_messageQueue.hasMessageForGroup(group)) { - this->sendSyncRequest(group); + openmittsu::protocol::MessageTime const lastSyncRequestTime = this->m_storage.getGroupLastSyncRequestTime(group); + bool isLastSyncRequestLongEnoughInThePast = false; + if (lastSyncRequestTime.isNull()) { + LOGGER_DEBUG("Last sync request time for group {} is null!", group.toString()); + isLastSyncRequestLongEnoughInThePast = true; + } else if (lastSyncRequestTime.getTime().addSecs(5 * 60) < QDateTime::currentDateTime()) { // At least 5 minutes since the last sync request + LOGGER_DEBUG("Last sync request time for group {} is {}!", group.toString(), lastSyncRequestTime.getTime().toString().toStdString()); + isLastSyncRequestLongEnoughInThePast = true; + } + + if (isLastSyncRequestLongEnoughInThePast) { + LOGGER_DEBUG("requestSyncForGroupIfApplicable for group {} will send sync request.", group.toString()); + this->sendSyncRequest(group); + } + } else { + LOGGER_DEBUG("requestSyncForGroupIfApplicable for group {} will NOT send sync request, messageQueue has waiting messages for group.", group.toString()); } }