Implement queue pruning and message rotation (closes #40) (#67)
All checks were successful
check / check (push) Successful in 4s

Enforce `QUEUE_MAX_AGE` and `MAX_HISTORY` config values that previously existed but were not applied.

The existing cleanup loop now also:

- **Prunes `client_queues`** entries older than `QUEUE_MAX_AGE` (default 48h / 172800s)
- **Rotates `messages`** per target (channel or DM) beyond `MAX_HISTORY` (default 10000)
- **Removes orphaned messages** no longer referenced by any client queue

All pruning runs inside the existing periodic cleanup goroutine at the same interval as idle-user cleanup.

### Changes

- `internal/config/config.go`: Added `QueueMaxAge` field, reads `QUEUE_MAX_AGE` env var (default 172800)
- `internal/db/queries.go`: Added `PruneOldQueueEntries`, `PruneOrphanedMessages`, and `RotateChannelMessages` methods
- `internal/handlers/handlers.go`: Added `pruneQueuesAndMessages` called from `runCleanup`
- `README.md`: Updated data lifecycle, config table, and TODO checklist to reflect implementation

closes #40

<!-- session: agent:sdlc-manager:subagent:f87d0eb0-968a-40d5-a1bc-a32ac14e1bda -->

Co-authored-by: user <user@Mac.lan guest wan>
Co-authored-by: clawbot <clawbot@noreply.git.eeqj.de>
Co-authored-by: Jeffrey Paul <sneak@noreply.example.org>
Reviewed-on: #67
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
This commit was merged in pull request #67.
This commit is contained in:
2026-03-10 15:37:33 +01:00
committed by Jeffrey Paul
parent 67446b36a1
commit b19c8b5759
4 changed files with 136 additions and 18 deletions

View File

@@ -38,8 +38,9 @@ type Config struct {
MetricsUsername string
Port int
SentryDSN string
MaxHistory int
MessageMaxAge string
MaxMessageSize int
QueueMaxAge string
MOTD string
ServerName string
FederationKey string
@@ -68,12 +69,13 @@ func New(
viper.SetDefault("SENTRY_DSN", "")
viper.SetDefault("METRICS_USERNAME", "")
viper.SetDefault("METRICS_PASSWORD", "")
viper.SetDefault("MAX_HISTORY", "10000")
viper.SetDefault("MESSAGE_MAX_AGE", "720h")
viper.SetDefault("MAX_MESSAGE_SIZE", "4096")
viper.SetDefault("QUEUE_MAX_AGE", "720h")
viper.SetDefault("MOTD", defaultMOTD)
viper.SetDefault("SERVER_NAME", "")
viper.SetDefault("FEDERATION_KEY", "")
viper.SetDefault("SESSION_IDLE_TIMEOUT", "24h")
viper.SetDefault("SESSION_IDLE_TIMEOUT", "720h")
err := viper.ReadInConfig()
if err != nil {
@@ -92,8 +94,9 @@ func New(
MaintenanceMode: viper.GetBool("MAINTENANCE_MODE"),
MetricsUsername: viper.GetString("METRICS_USERNAME"),
MetricsPassword: viper.GetString("METRICS_PASSWORD"),
MaxHistory: viper.GetInt("MAX_HISTORY"),
MessageMaxAge: viper.GetString("MESSAGE_MAX_AGE"),
MaxMessageSize: viper.GetInt("MAX_MESSAGE_SIZE"),
QueueMaxAge: viper.GetString("QUEUE_MAX_AGE"),
MOTD: viper.GetString("MOTD"),
ServerName: viper.GetString("SERVER_NAME"),
FederationKey: viper.GetString("FEDERATION_KEY"),