Tasks¶
The Housekeeping scheduled job purges data that CiviCRM creates but never removes. It runs daily and calls the HousekeepingTask.run APIv4 action.
It replaces the core Clean-up Temporary Data and Files job (Job.cleanup): every option of that job is available here as a task, so running both only duplicates work. The first time Housekeeping runs it disables the core job for you, and remembers that it did so - if you disable this extension, the core job is switched back on.
Tasks¶
Each task is one policy: one thing that gets purged, one way of purging it. The descriptions below also appear on the admin screen.
Things CiviCRM never cleans up¶
| Task | Type | Default | Retention | What it does |
|---|---|---|---|---|
logFiles |
logfile | On | -3 month |
Deletes rotated log files (CiviCRM.1.<hash>.log.202601011200). CiviCRM renames the log when it passes CIVICRM_LOG_ROTATESIZE or rolls into a new month, but never deletes the renamed files. The live log is never touched. |
sqlTriggerFiles |
file | On | -3 month |
Deletes the trigger SQL files (CiviCRM.trigger<id><hash>.sql) written when logging_no_trigger_permission is on. Every rebuild leaves another one. Anything newer than the retention is kept, in case it holds statements nobody has run yet. |
liveLogFile |
logfile | Off | -1 month |
Rotates the log currently being written to when nothing has been written to it for longer than the retention. Core only rotates on write, so a quiet site keeps the same file indefinitely. logFiles then removes the result once it is old enough. |
systemLog |
table | On | -1 year |
Deletes rows from civicrm_system_log, which records every incoming payment notification and assorted system events. Nothing in core removes them. |
mailingSpool |
table | On | -1 month |
Deletes rows from civicrm_mailing_spool - retained copies of outbound mail on sites that spool. |
queueItems |
table | On | -3 month |
Deletes items in civicrm_queue_item whose queue no longer exists, so nothing can ever run them. Items belonging to a queue that still exists are never touched, however old. |
civicrmLog |
table | Off | -1 year |
Deletes rows from civicrm_log, the change log behind the contact Change Log tab. Off by default because the history is often wanted. |
mailingEvents |
table | Off | -1 year |
Deletes per-recipient delivery, open, click, bounce and unsubscribe rows for mailings that finished before the retention - usually the largest tables on a site that mails. Off by default: this permanently destroys the statistics and reports for those mailings. Opt-in and opt-out records (civicrm_mailing_event_subscribe and _confirm) are never touched, and neither is civicrm_mailing_recipients - that is what "include/exclude recipients of prior mailings" reads, so purging it would change who a future mailing goes to. Leave this off if you use the archivemailing extension, which records each mailing's statistics before deleting the same rows: whichever runs first wins, and a mailing this task reached first is archived showing zeros. |
detailedLogging |
table | Off | -1 year |
Deletes rows from the log_civicrm_* tables written when Detailed Logging is enabled. Off by default: on some sites that permanent audit trail is the whole point, and there may be a legal requirement to keep it. Does nothing if Detailed Logging is off. |
trashedContacts |
table | Off | -1 year |
Permanently deletes contacts that have been in the trash since before the retention. Off by default: this is real data rather than housekeeping debris, and the deletion cannot be undone. Contacts CiviCRM refuses to delete permanently - those with a live contribution, those a membership type belongs to, and those linked to a site user - are always left alone. At most 500 contacts per run, so a large trash is worked through over successive days. There is no "trashed on" column, so age comes from modified_date: a contact edited after being trashed counts as trashed then. |
Ported from core's Job.cleanup¶
Enabling this job replaces the core Clean-up Temporary Data and Files job, so every option of that job is available here. These delegate to the same core methods.
| Task | Type | Default | Core option | What it does |
|---|---|---|---|---|
sessions |
cache | On | session |
Expired sessions. |
tempTables |
cache | On | tempTables |
Temporary tables older than 2 days. |
prevNextCache |
cache | On | prevNext |
The search (prevnext) cache. |
expiredDbCache |
cache | On | expiredDbCache |
Expired database cache entries. |
jobLog |
table | On | jobLog |
Scheduled job log, keeping the newest 1000 rows plus the last 30 days. |
tempFiles |
file | On | tempFiles |
Empties the upload directory. There is no age check, so an import file a user has uploaded but not yet processed is discarded too. |
tplCache |
file | Off | tplCache |
Empties templates_c. Every compiled template is rebuilt on the next page load. |
dbCache |
cache | Off | dbCache |
Rebuilds database caches. A flush rather than a purge. |
memCache |
cache | Off | memCache |
Rebuilds the system cache. |
wordReplacements |
cache | Off | wordRplc |
Rebuilds the word replacement cache. |
Rows are deleted in batches of 5000 so a large table cannot lock the database for long enough to take the site down.
Managing tasks¶
Administer > System Settings > Housekeeping Tasks lists every task with its current state:
Filter the list by typing part of a task's name or description, or by type, policy and whether it is enabled.
| Column | Meaning |
|---|---|
| Task / Name | The human readable name, and the machine name to use in the tasks parameter. |
| Description | What the task removes. |
| Type / Policy | What is purged (cache, table, log file, file) and how (delete old, truncate, rotate, flush). |
| Enabled | Whether the task runs. Click to change. |
| Retention | How long this task keeps things for, as a strtotime interval in the past, eg. -3 month or -90 days. Click to change. Shows n/a for tasks with no age component. |
| Last Run / Removed / Bytes Reclaimed / Last Result | What happened the last time the task ran. |
Retention is per task, so the rotated logs can be kept for three months while the trigger SQL goes after one, without needing a second scheduled job.
A retention that resolves to a date in the future (3 month - note the missing minus sign) is rejected rather than acted on, because it would match every file. Clearing a retention switches the task off; so does unticking Enabled, which is the clearer control.
Task, Description, Type and Policy come from the task class, and are refreshed on each run, so editing one in code reaches sites where someone has already used this screen.
Tasks come from Civi\Housekeeping\Registry and their records are managed entities, so a task added to the registry appears in this list on the next flush, and a task removed from it takes its row away. Disabling the extension deletes the records - re-enabling it recreates them at their defaults, discarding any changes made here.
If an enabled task stops running - it errors every night, or the job stops firing - a system check reports it once it has missed two of the job's intervals.
Running it by hand¶
cv api4 HousekeepingTask.run '{"dryRun": true}'
dryRun reports what each task would remove, and lists the files the logFiles task would delete, without removing anything.
cv api4 HousekeepingTask.run '{"tasks": ["logFiles"], "retention": "-7 day"}'
tasks limits the run to the named tasks, and runs them whether or not they are enabled. retention overrides every task's configured retention for this run only.
Adding a task¶
Implement Civi\Housekeeping\CleanupTaskInterface (usually by extending AbstractCleanupTask) and add the class to Civi\Housekeeping\Registry. isEnabledByDefault() and getDefaultRetention() seed the task's record when it is first created; after that the record owns both.
getType(), getPolicy() and getRetention() deliberately mirror the fields proposed for a core "HouseKeeping" entity in dev/core#5347, so these tasks can become managed entity records if that lands.