Factorizer/Cluster ERP WikiCluster ERP Türkçe
Home / Operations

Reference

Scheduled jobs and retention

The cron table of a Linux node, the background loops inside the server, their leader lock, and the retention passes over logs, records, and the control plane.

Cluster ERP runs periodic work in two places: the cron table deploy/cluster-erp.cron of the service user, and background loops that every server worker starts in src/cluster_erp/server/app.py. This page lists both, the lock that keeps a loop to one worker, and the retention passes in app.py and src/cluster_erp/server/control_retention.py. The admin-configured record retention window is explained on the records module page.

Scope and source

  • Defined in: deploy/cluster-erp.cron, src/cluster_erp/server/app.py (lifespan, _leader, and the _*_loop functions), src/cluster_erp/server/control_retention.py (sweep_control_plane), src/cluster_erp/server/membership.py.
  • Count: four cron entries (two active, two commented), counted from the file; four background loops and one one-off background task, counted from the asyncio.create_task calls in lifespan (src/cluster_erp/server/app.py:164-194).

Exact cron times of a node are deployment data; the table gives the frequency only.

Cron entries

Entry Frequency Command State Source
Fleet backup daily python -m cluster_erp.server.backup_tenants active deploy/cluster-erp.cron:4-7
Membership sweep daily, after the backup python -m cluster_erp.server.membership sweep active deploy/cluster-erp.cron:9-11
Cold CSV export daily scripts/backup/pg_cold_storage_export.sh commented deploy/cluster-erp.cron:13-19
Base backup weekly pg_basebackup with the backup role commented deploy/cluster-erp.cron:21-25

install.sh installs the file as the service user's cron table on every run (deploy/install.sh:210). The cron comment calls the membership sweep a second line of defence next to the in-process loop (deploy/cluster-erp.cron:9-10).

Background loops

Loop Interval Leader lock name Databases Work Source
_retention_purge_loop 24 hours retention_purge default and every tenant, suspended included Log retention, then purge_expired with the record retention window, then the RetentionSweep event src/cluster_erp/server/app.py:404-458
_subscription_sweep_loop 24 hours subscription_sweep active tenants Advances, renews, or expires subscriptions; events after commit src/cluster_erp/server/app.py:504-544
_analytics_summary_loop analytics_summary_refresh_seconds; 0 turns it off analytics_summary active tenants Refreshes analytics summary cells src/cluster_erp/server/app.py:461-501
_membership_expiry_loop 24 hours, multi-tenant only membership_expiry on the control plane control plane Suspends expired memberships, then runs the control-plane retention src/cluster_erp/server/app.py:372-401
_audit_redaction_backfill once, at start-up none default and every tenant Redacts the older audit_log backlog in batches src/cluster_erp/server/app.py:314-334

Each 24-hour loop sleeps first, so it never runs at start-up; the start-up runs its own catch-up passes instead (src/cluster_erp/server/app.py:158-193). One database that fails is logged, and the loop continues with the next database (src/cluster_erp/server/app.py:452-454, src/cluster_erp/server/app.py:538-540).

Start-up passes

Pass Source
Log retention on the default database and every tenant src/cluster_erp/server/app.py:158-160
Erasure ledger replay src/cluster_erp/server/app.py:165-168
Membership expiry sweep, multi-tenant only src/cluster_erp/server/app.py:180-185
Control-plane retention, multi-tenant only src/cluster_erp/server/app.py:186-193

Leader lock

_leader takes pg_try_advisory_lock on the database the pass serves, with a key derived by CRC-32 from cluster_erp:<name>. The worker that gets the lock runs the pass; the others skip it. The lock is released at the end of the pass, so a crashed worker never blocks the next one (src/cluster_erp/server/app.py:357-369).

Log retention

_daily_log_retention runs on the default database and on every tenant, suspended tenants included (src/cluster_erp/server/app.py:1267-1284). On each database it:

  1. deletes expired rows of the token blacklist (src/cluster_erp/server/app.py:1168-1193);
  2. deletes activity_log rows older than activity_log_retention_days and error_log rows older than error_log_retention_days, in batches of log_purge_batch_rows (src/cluster_erp/server/app.py:1196-1245);
  3. writes an evidence row of kind logs, even when nothing was removed (src/cluster_erp/server/app.py:1246-1263).

Control-plane retention

sweep_control_plane runs at start-up and daily on a multi-tenant node, and on demand with python -m cluster_erp.server.membership retention (src/cluster_erp/server/membership.py:137-142). Every pass writes one row to control_retention_runs (src/cluster_erp/server/control_retention.py:170-171).

Step Window setting Effect Source
Rate-limit rows control_rate_limit_retention_hours Deletes rows of control_rate_limits older than the window. src/cluster_erp/server/control_retention.py:85-93
Abandoned and cancelled signups signup_verify_ttl_hours plus control_signup_retention_days Deletes unverified queued memberships past the link lifetime plus the window, and cancelled ones past the window. src/cluster_erp/server/control_retention.py:95-110
Orphaned registrations none Soft-deletes a tenant row in provisioning state that has no membership left. src/cluster_erp/server/control_retention.py:112-122
Retired registrations control_signup_retention_days Replaces name and mail domains of soft-deleted tenant rows past the window. src/cluster_erp/server/control_retention.py:124-135
Operator actions control_actions_retention_years Deletes operator action records older than the window. src/cluster_erp/server/control_retention.py:137-145
Inactive operators control_actions_retention_years Replaces username, password hash, and second-factor secret of long-inactive operator accounts. src/cluster_erp/server/control_retention.py:147-160
Spooled mails signup_mail_spool_retention_days Deletes spooled verification mail files, only with the spool transport. src/cluster_erp/server/control_retention.py:162-168

Active or suspended customers, their memberships, and provisioned tenants are not touched by this pass (src/cluster_erp/server/control_retention.py:30-31).

Discrepancies

Terms introduced

Term Code identifier Definition Turkish term Source
leader lock _leader A per-pass advisory lock that lets one worker run a periodic pass while the others skip it. lider kilidi src/cluster_erp/server/app.py:357-369
control-plane retention sweep_control_plane The daily deletion and anonymisation pass over the control-plane tables. kontrol düzlemi saklama geçişi src/cluster_erp/server/control_retention.py:77-175
retention evidence row record_run The row that records what a retention pass removed. saklama kanıt satırı src/cluster_erp/modules/records/retention/services.py:20-26

Verified against commit 92f8051 on 2026-11-13.

Verified against commit 92f8051 · 2026-11-13