mirror of
https://github.com/thelounge/thelounge.git
synced 2026-03-14 14:35:50 +01:00
sqlite: implement deleteMessages
This is laying the foundation to build a cleaning task that's sort of database agnostic. All calls are done by acting on a "DeletionRequest" so interpretation of the config will go through a single point
This commit is contained in:
parent
aec8d0b033
commit
14d9ff247d
3 changed files with 155 additions and 3 deletions
|
|
@ -7,7 +7,7 @@ import Config from "../../config";
|
|||
import Msg, {Message} from "../../models/msg";
|
||||
import Chan, {Channel} from "../../models/chan";
|
||||
import Helper from "../../helper";
|
||||
import type {SearchResponse, SearchQuery, SearchableMessageStorage} from "./types";
|
||||
import type {SearchResponse, SearchQuery, SearchableMessageStorage, DeletionRequest} from "./types";
|
||||
import Network from "../../models/network";
|
||||
|
||||
// TODO; type
|
||||
|
|
@ -234,6 +234,11 @@ class SqliteMessageStorage implements SearchableMessageStorage {
|
|||
await this.serialize_run("VACUUM");
|
||||
}
|
||||
|
||||
// helper method that vacuums the db, meant to be used by migration related cli commands
|
||||
async vacuum() {
|
||||
await this.serialize_run("VACUUM");
|
||||
}
|
||||
|
||||
async close() {
|
||||
if (!this.isEnabled) {
|
||||
return;
|
||||
|
|
@ -481,6 +486,33 @@ class SqliteMessageStorage implements SearchableMessageStorage {
|
|||
};
|
||||
}
|
||||
|
||||
async deleteMessages(req: DeletionRequest): Promise<number> {
|
||||
await this.initDone.promise;
|
||||
let sql = "delete from messages where id in (select id from messages where\n";
|
||||
|
||||
// We roughly get a timestamp from N days before.
|
||||
// We don't adjust for daylight savings time or other weird time jumps
|
||||
const millisecondsInDay = 24 * 60 * 60 * 1000;
|
||||
const deleteBefore = Date.now() - req.olderThanDays * millisecondsInDay;
|
||||
sql += `time <= ${deleteBefore}\n`;
|
||||
|
||||
let typeClause = "";
|
||||
|
||||
if (req.messageTypes !== null) {
|
||||
typeClause = `type in (${req.messageTypes.map((type) => `'${type}'`).join(",")})\n`;
|
||||
}
|
||||
|
||||
if (typeClause) {
|
||||
sql += `and ${typeClause}`;
|
||||
}
|
||||
|
||||
sql += "order by time asc\n";
|
||||
sql += `limit ${req.limit}\n`;
|
||||
sql += ")";
|
||||
|
||||
return this.serialize_run(sql);
|
||||
}
|
||||
|
||||
canProvideMessages() {
|
||||
return this.isEnabled;
|
||||
}
|
||||
|
|
@ -488,13 +520,13 @@ class SqliteMessageStorage implements SearchableMessageStorage {
|
|||
private serialize_run(stmt: string, ...params: any[]): Promise<number> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.database.serialize(() => {
|
||||
this.database.run(stmt, params, (err) => {
|
||||
this.database.run(stmt, params, function (err) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve();
|
||||
resolve(this.changes); // number of affected rows, `this` is re-bound by sqlite3
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
7
server/plugins/messageStorage/types.d.ts
vendored
7
server/plugins/messageStorage/types.d.ts
vendored
|
|
@ -4,6 +4,13 @@ import {Channel} from "../../models/channel";
|
|||
import {Message} from "../../models/message";
|
||||
import {Network} from "../../models/network";
|
||||
import Client from "../../client";
|
||||
import type {MessageType} from "../../models/msg";
|
||||
|
||||
export type DeletionRequest = {
|
||||
olderThanDays: number;
|
||||
messageTypes: MessageType[] | null; // null means no restriction
|
||||
limit: number; // -1 means unlimited
|
||||
};
|
||||
|
||||
interface MessageStorage {
|
||||
isEnabled: boolean;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue