Cleanup finished compat sessions after 30 days
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n DELETE FROM oauth2_consents\n WHERE oauth2_client_id = $1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "036e9e2cb7271782e48700fecd3fdd80f596ed433f37f2528c7edbdc88b13646"
|
||||
}
|
||||
30
crates/storage-pg/.sqlx/query-494ca16f0f00f977a3031924a15318aa7346917e5c8a37bb0f5b2b3067588009.json
generated
Normal file
30
crates/storage-pg/.sqlx/query-494ca16f0f00f977a3031924a15318aa7346917e5c8a37bb0f5b2b3067588009.json
generated
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n WITH\n to_delete AS (\n SELECT compat_session_id, finished_at\n FROM compat_sessions\n WHERE finished_at IS NOT NULL\n AND ($1::timestamptz IS NULL OR finished_at >= $1)\n AND finished_at < $2\n ORDER BY finished_at ASC\n LIMIT $3\n FOR UPDATE\n ),\n\n -- Delete refresh tokens first because they reference access tokens\n deleted_refresh_tokens AS (\n DELETE FROM compat_refresh_tokens\n USING to_delete\n WHERE compat_refresh_tokens.compat_session_id = to_delete.compat_session_id\n ),\n\n deleted_access_tokens AS (\n DELETE FROM compat_access_tokens\n USING to_delete\n WHERE compat_access_tokens.compat_session_id = to_delete.compat_session_id\n ),\n\n deleted_sso_logins AS (\n DELETE FROM compat_sso_logins\n USING to_delete\n WHERE compat_sso_logins.compat_session_id = to_delete.compat_session_id\n ),\n\n deleted_sessions AS (\n DELETE FROM compat_sessions\n USING to_delete\n WHERE compat_sessions.compat_session_id = to_delete.compat_session_id\n RETURNING compat_sessions.finished_at\n )\n\n SELECT\n COUNT(*) as \"count!\",\n MAX(finished_at) as last_finished_at\n FROM deleted_sessions\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "count!",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "last_finished_at",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Timestamptz",
|
||||
"Timestamptz",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null,
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "494ca16f0f00f977a3031924a15318aa7346917e5c8a37bb0f5b2b3067588009"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
-- no-transaction
|
||||
-- Copyright 2026 Element Creations Ltd.
|
||||
--
|
||||
-- SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
-- Please see LICENSE files in the repository root for full details.
|
||||
|
||||
-- Index to efficiently query finished compat sessions for cleanup
|
||||
-- Only includes non-null finished_at values since we filter on finished_at IS NOT NULL
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "compat_sessions_finished_at_idx"
|
||||
ON "compat_sessions" ("finished_at")
|
||||
WHERE "finished_at" IS NOT NULL;
|
||||
@@ -1,3 +1,4 @@
|
||||
// Copyright 2025, 2026 Element Creations Ltd.
|
||||
// Copyright 2024, 2025 New Vector Ltd.
|
||||
// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
@@ -684,4 +685,77 @@ impl CompatSessionRepository for PgCompatSessionRepository<'_> {
|
||||
|
||||
Ok(compat_session)
|
||||
}
|
||||
|
||||
#[tracing::instrument(
|
||||
name = "db.compat_session.cleanup_finished",
|
||||
skip_all,
|
||||
fields(
|
||||
db.query.text,
|
||||
),
|
||||
err,
|
||||
)]
|
||||
async fn cleanup_finished(
|
||||
&mut self,
|
||||
since: Option<DateTime<Utc>>,
|
||||
until: DateTime<Utc>,
|
||||
limit: usize,
|
||||
) -> Result<(usize, Option<DateTime<Utc>>), Self::Error> {
|
||||
let res = sqlx::query!(
|
||||
r#"
|
||||
WITH
|
||||
to_delete AS (
|
||||
SELECT compat_session_id, finished_at
|
||||
FROM compat_sessions
|
||||
WHERE finished_at IS NOT NULL
|
||||
AND ($1::timestamptz IS NULL OR finished_at >= $1)
|
||||
AND finished_at < $2
|
||||
ORDER BY finished_at ASC
|
||||
LIMIT $3
|
||||
FOR UPDATE
|
||||
),
|
||||
|
||||
-- Delete refresh tokens first because they reference access tokens
|
||||
deleted_refresh_tokens AS (
|
||||
DELETE FROM compat_refresh_tokens
|
||||
USING to_delete
|
||||
WHERE compat_refresh_tokens.compat_session_id = to_delete.compat_session_id
|
||||
),
|
||||
|
||||
deleted_access_tokens AS (
|
||||
DELETE FROM compat_access_tokens
|
||||
USING to_delete
|
||||
WHERE compat_access_tokens.compat_session_id = to_delete.compat_session_id
|
||||
),
|
||||
|
||||
deleted_sso_logins AS (
|
||||
DELETE FROM compat_sso_logins
|
||||
USING to_delete
|
||||
WHERE compat_sso_logins.compat_session_id = to_delete.compat_session_id
|
||||
),
|
||||
|
||||
deleted_sessions AS (
|
||||
DELETE FROM compat_sessions
|
||||
USING to_delete
|
||||
WHERE compat_sessions.compat_session_id = to_delete.compat_session_id
|
||||
RETURNING compat_sessions.finished_at
|
||||
)
|
||||
|
||||
SELECT
|
||||
COUNT(*) as "count!",
|
||||
MAX(finished_at) as last_finished_at
|
||||
FROM deleted_sessions
|
||||
"#,
|
||||
since,
|
||||
until,
|
||||
i64::try_from(limit).unwrap_or(i64::MAX),
|
||||
)
|
||||
.traced()
|
||||
.fetch_one(&mut *self.conn)
|
||||
.await?;
|
||||
|
||||
Ok((
|
||||
res.count.try_into().unwrap_or(usize::MAX),
|
||||
res.last_finished_at,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user