|
10 | 10 | import time |
11 | 11 | from collections.abc import Iterable, Sequence |
12 | 12 | from dataclasses import dataclass |
13 | | -from datetime import timedelta |
| 13 | +from datetime import datetime, timedelta |
14 | 14 | from logging import Logger |
15 | 15 | from pathlib import Path |
16 | 16 | from typing import Final, Literal |
17 | 17 |
|
| 18 | +from cmk.utils.log import VERBOSE |
| 19 | + |
18 | 20 | from .config import Config |
19 | 21 | from .event import Event |
20 | 22 | from .history import History, HistoryWhat |
@@ -267,23 +269,44 @@ def housekeeping(self) -> None: |
267 | 269 | And performs a vacuum to shrink the database file. |
268 | 270 | """ |
269 | 271 | now = time.time() |
270 | | - if now - self._last_housekeeping > self._config["sqlite_housekeeping_interval"]: |
271 | | - delta = now - timedelta(days=self._config["history_lifetime"]).total_seconds() |
272 | | - with self.conn as connection: |
273 | | - cur = connection.cursor() |
274 | | - cur.execute("DELETE FROM history WHERE time <= ?;", (delta,)) |
275 | | - # should be executed outside of the transaction |
276 | | - self._vacuum() |
277 | | - self._last_housekeeping = now |
| 272 | + if now - self._last_housekeeping <= self._config["sqlite_housekeeping_interval"]: |
| 273 | + return |
| 274 | + delta = now - timedelta(days=self._config["history_lifetime"]).total_seconds() |
| 275 | + self._logger.log( |
| 276 | + VERBOSE, |
| 277 | + "SQLite history housekeeping: deleting events before %s", |
| 278 | + datetime.fromtimestamp(delta).isoformat(), |
| 279 | + ) |
| 280 | + with self.conn as connection: |
| 281 | + cur = connection.cursor() |
| 282 | + cur.execute("DELETE FROM history WHERE time <= ?;", (delta,)) |
| 283 | + # should be executed outside of the transaction |
| 284 | + self._vacuum() |
| 285 | + self._last_housekeeping = now |
278 | 286 |
|
279 | 287 | def _vacuum(self) -> None: |
280 | | - """Run VACUUM command only if the free pages in DB are greater than 50 Mb.""" |
| 288 | + """Run VACUUM command only if the free pages in DB are greater than the configured limit""" |
281 | 289 | with self.conn as connection: |
282 | 290 | freelist_count = connection.execute("PRAGMA freelist_count").fetchone()[0] |
283 | 291 | freelist_size = freelist_count * self._page_size |
284 | 292 |
|
285 | | - if freelist_size > self._config["sqlite_freelist_size"]: |
286 | | - self.conn.execute("VACUUM;") |
| 293 | + max_freelist_size = self._config["sqlite_freelist_size"] |
| 294 | + if freelist_size <= max_freelist_size: |
| 295 | + return |
| 296 | + self._logger.log( |
| 297 | + VERBOSE, |
| 298 | + "SQLite's freelist size of %d bytes is larger than the configured limit of %d bytes, cleanup needed", |
| 299 | + freelist_size, |
| 300 | + max_freelist_size, |
| 301 | + ) |
| 302 | + self._logger.log( |
| 303 | + VERBOSE, |
| 304 | + "running VACUUM on event console history %s", |
| 305 | + f"at {self._settings.database}" |
| 306 | + if isinstance(self._settings.database, Path) |
| 307 | + else "in-memory DB", |
| 308 | + ) |
| 309 | + self.conn.execute("VACUUM;") |
287 | 310 |
|
288 | 311 | def close(self) -> None: |
289 | 312 | """Explicitly close the connection to the sqlite database. |
|
0 commit comments