Skip to content

Commit cf283ca

Browse files
committed
feat: add notification auto cleanup and timeout handling
1. Add fetchFirstEntity method to data accessor interfaces for retrieving earliest notifications 2. Implement notification auto-cleanup feature that removes processed notifications older than configured days 3. Add Timeout processed type for handling expired notifications 4. Add configuration option for notification cleanup days with default value of 7 days 5. Implement cleanup timer that runs every second to check for expired notifications 6. Update notification processing to handle timeout closures properly feat: 添加通知自动清理和超时处理功能 1. 在数据访问器接口中添加 fetchFirstEntity 方法用于获取最早的通知 2. 实现通知自动清理功能,删除超过配置天数的已处理通知 3. 添加 Timeout 处理类型用于处理过期通知 4. 添加通知清理天数的配置选项,默认值为7天 5. 实现清理定时器,每秒检查一次过期通知 6. 更新通知处理逻辑以正确处理超时关闭 PMS: BUG-284979
1 parent bee9a40 commit cf283ca

File tree

11 files changed

+96
-0
lines changed

11 files changed

+96
-0
lines changed

panels/notification/common/dataaccessor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class DataAccessor
3535
virtual int fetchEntityCount(const QString &appName, int processedType) const { Q_UNUSED(appName); Q_UNUSED(processedType); return 0; }
3636
virtual NotifyEntity fetchLastEntity(const QString &appName, int processedType) { Q_UNUSED(appName); Q_UNUSED(processedType); return {}; }
3737
virtual NotifyEntity fetchLastEntity(uint notifyId) { Q_UNUSED(notifyId); return {}; }
38+
virtual NotifyEntity fetchFirstEntity(int processedType) { Q_UNUSED(processedType); return {}; }
3839
virtual QList<NotifyEntity> fetchEntities(const QString &appName, int processedType, int maxCount)
3940
{
4041
Q_UNUSED(appName)

panels/notification/common/dataaccessorproxy.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@ NotifyEntity DataAccessorProxy::fetchLastEntity(uint notifyId)
116116
return m_source->fetchLastEntity(notifyId);
117117
}
118118

119+
NotifyEntity DataAccessorProxy::fetchFirstEntity(int processedType)
120+
{
121+
if (processedType == NotifyEntity::NotProcessed) {
122+
return m_impl->fetchFirstEntity(processedType);
123+
} else {
124+
return m_source->fetchFirstEntity(processedType);
125+
}
126+
}
127+
119128
QList<NotifyEntity> DataAccessorProxy::fetchEntities(const QString &appName, int processedType, int maxCount)
120129
{
121130
if (processedType == NotifyEntity::NotProcessed) {

panels/notification/common/dataaccessorproxy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class DataAccessorProxy : public DataAccessor
3131
virtual int fetchEntityCount(const QString &appName, int processedType) const override;
3232
virtual NotifyEntity fetchLastEntity(const QString &appName, int processedType) override;
3333
virtual NotifyEntity fetchLastEntity(uint notifyId) override;
34+
virtual NotifyEntity fetchFirstEntity(int processedType) override;
3435
virtual QList<NotifyEntity> fetchEntities(const QString &appName, int processedType, int maxCount) override;
3536
virtual QList<QString> fetchApps(int maxCount) const override;
3637

panels/notification/common/dbaccessor.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,29 @@ NotifyEntity DBAccessor::fetchLastEntity(uint notifyId)
443443
return {};
444444
}
445445

446+
NotifyEntity DBAccessor::fetchFirstEntity(int processedType)
447+
{
448+
BENCHMARK();
449+
450+
QMutexLocker locker(&m_mutex);
451+
QSqlQuery query(m_connection);
452+
453+
QString cmd = QString("SELECT %1 FROM notifications2 WHERE (ProcessedType = :processedType OR ProcessedType IS NULL) ORDER BY CTime ASC LIMIT 1").arg(EntityFields.join(","));
454+
query.prepare(cmd);
455+
query.bindValue(":processedType", processedType);
456+
457+
if (!query.exec()) {
458+
qWarning(notifyDBLog) << "Query execution error:" << query.lastError().text();
459+
return {};
460+
}
461+
462+
if (query.next()) {
463+
auto entity = parseEntity(query);
464+
return entity;
465+
}
466+
return {};
467+
}
468+
446469
QList<QString> DBAccessor::fetchApps(int maxCount) const
447470
{
448471
BENCHMARK();

panels/notification/common/dbaccessor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class DBAccessor : public DataAccessor
3737
NotifyEntity fetchLastEntity(const QString &appName, int processedType) override;
3838
QList<NotifyEntity> fetchEntities(const QString &appName, int processedType, int maxCount) override;
3939
NotifyEntity fetchLastEntity(uint notifyId) override;
40+
NotifyEntity fetchFirstEntity(int processedType) override;
4041
QList<QString> fetchApps(int maxCount) const override;
4142

4243
void removeEntity(qint64 id) override;

panels/notification/common/memoryaccessor.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "memoryaccessor.h"
66
#include <QDebug>
7+
#include <limits>
78

89
namespace notification
910
{
@@ -102,6 +103,22 @@ NotifyEntity MemoryAccessor::fetchLastEntity(uint notifyId)
102103
return {};
103104
}
104105

106+
NotifyEntity MemoryAccessor::fetchFirstEntity(int processedType)
107+
{
108+
QMutexLocker locker(&m_mutex);
109+
NotifyEntity firstEntity;
110+
qint64 earliestTime = std::numeric_limits<qint64>::max();
111+
112+
for (const auto &entity : m_entities) {
113+
if (entity.processedType() == processedType && entity.cTime() < earliestTime) {
114+
earliestTime = entity.cTime();
115+
firstEntity = entity;
116+
}
117+
}
118+
119+
return firstEntity.isValid() ? firstEntity : NotifyEntity{};
120+
}
121+
105122
QList<NotifyEntity> MemoryAccessor::fetchEntities(const QString &appName, int processedType, int maxCount)
106123
{
107124
QMutexLocker locker(&m_mutex);

panels/notification/common/memoryaccessor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class MemoryAccessor : public DataAccessor
2727
virtual int fetchEntityCount(const QString &appName, int processedType) const override;
2828
virtual NotifyEntity fetchLastEntity(const QString &appName, int processedType) override;
2929
virtual NotifyEntity fetchLastEntity(uint notifyId) override;
30+
virtual NotifyEntity fetchFirstEntity(int processedType) override;
3031
virtual QList<NotifyEntity> fetchEntities(const QString &appName, int processedType, int maxCount) override;
3132
virtual QList<QString> fetchApps(int maxCount) const override;
3233

panels/notification/common/notifyentity.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class NotifyEntity
3030
Dismissed = 2,
3131
Closed = 3,
3232
Unknown = 4,
33+
Timeout = 5,
3334
};
3435

3536
NotifyEntity();

panels/notification/server/configs/org.deepin.dde.shell.notification.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,17 @@
144144
"description[zh_CN]": "应用名称映射",
145145
"permissions": "readwrite",
146146
"visibility": "private"
147+
},
148+
"notificationCleanupDays": {
149+
"value": 7,
150+
"serial": 0,
151+
"flags": [],
152+
"name": "notification cleanup days",
153+
"name[zh_CN]": "通知清理天数",
154+
"description": "Number of days after which notifications will be automatically cleaned up",
155+
"description[zh_CN]": "通知自动清理的天数,超过此天数的通知将被自动删除",
156+
"permissions": "readwrite",
157+
"visibility": "public"
147158
}
148159
}
149160
}

panels/notification/server/notificationmanager.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,14 @@ NotificationManager::NotificationManager(QObject *parent)
4949
, m_persistence(DataAccessorProxy::instance())
5050
, m_setting(new NotificationSetting(this))
5151
, m_pendingTimeout(new QTimer(this))
52+
, m_cleanupTimer(new QTimer(this))
5253
{
5354
m_pendingTimeout->setSingleShot(true);
5455
connect(m_pendingTimeout, &QTimer::timeout, this, &NotificationManager::onHandingPendingEntities);
56+
57+
m_cleanupTimer->setInterval(1000);
58+
connect(m_cleanupTimer, &QTimer::timeout, this, &NotificationManager::onCleanupExpiredNotifications);
59+
m_cleanupTimer->start();
5560

5661
DataAccessorProxy::instance()->setSource(DBAccessor::instance());
5762

@@ -77,6 +82,7 @@ NotificationManager::NotificationManager(QObject *parent)
7782
m_systemApps = config->value("systemApps").toStringList();
7883
// TODO temporary fix for AppNamesMap
7984
m_appNamesMap = config->value("AppNamesMap").toMap();
85+
m_cleanupDays = config->value("notificationCleanupDays", 7).toInt();
8086

8187
if (QStringLiteral("wayland") != QGuiApplication::platformName()) {
8288
initScreenLockedState();
@@ -457,6 +463,8 @@ void NotificationManager::updateEntityProcessed(qint64 id, uint reason)
457463
if (entity.isValid()) {
458464
if ((reason == NotifyEntity::Closed || reason == NotifyEntity::Dismissed) && entity.processedType() == NotifyEntity::NotProcessed) {
459465
entity.setProcessedType(NotifyEntity::Removed);
466+
} else if (reason == NotifyEntity::Timeout) {
467+
entity.setProcessedType(NotifyEntity::Removed);
460468
} else {
461469
entity.setProcessedType(NotifyEntity::Processed);
462470
}
@@ -675,4 +683,24 @@ void NotificationManager::onScreenLockedChanged(bool screenLocked)
675683
m_screenLocked = screenLocked;
676684
}
677685

686+
void NotificationManager::onCleanupExpiredNotifications()
687+
{
688+
const qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
689+
const qint64 cleanupDaysInMs = m_cleanupDays * 24 * 60 * 60 * 1000;
690+
const qint64 cutoffTime = currentTime - cleanupDaysInMs;
691+
692+
while (true) {
693+
auto firstEntity = m_persistence->fetchFirstEntity(NotifyEntity::Processed);
694+
695+
if (!firstEntity.isValid()) {
696+
break;
697+
}
698+
699+
if (firstEntity.cTime() > cutoffTime) {
700+
break;
701+
}
702+
notificationClosed(firstEntity.id(), firstEntity.bubbleId(), NotifyEntity::Timeout);
703+
}
704+
}
705+
678706
} // notification

0 commit comments

Comments
 (0)