Class: Maintenance::EdiCommunicationLogMaintenance

Inherits:
BaseService
  • Object
show all
Defined in:
app/services/maintenance/edi_communication_log_maintenance.rb

Overview

Retention for EdiCommunicationLog. Modelled on
WebhookMaintenance, which does the same job for webhook_logs.

Two operations, run daily:

  1. Archives settled entries older than ARCHIVE_AGE
  2. Destroys entries archived more than DELETE_AGE ago

Until this existed the table had NO retention at all: 489k rows / 3.3 GB, the
oldest from 2026-02, nothing ever removing any of it.

Examples:

Manual invocation

Maintenance::EdiCommunicationLogMaintenance.new.process

Via ServiceRunner (scheduled)

ServiceRunner.perform_async('Maintenance::EdiCommunicationLogMaintenance')

Constant Summary collapse

ARCHIVE_AGE =

How settled an entry must be before it is archived.

2.weeks
DELETE_AGE =

How long an entry stays archived before it is destroyed. Measured from when
it was ARCHIVED, not created — so nothing is destroyed until it has been
archived (and therefore out of the default CRM view) for a full quarter.

3.months
ARCHIVABLE_STATES =

States EdiCommunicationLog's archive event accepts. processing and
retry are deliberately absent: those are in-flight, and the sweep
(EdiStalledFeedSweep) is what notices when they stop moving.

%w[ready processed exception].freeze
ARCHIVE_LIMIT =

Ceilings per run. The archive backlog is ~440k rows on first run; batching
converges it over a couple of weeks instead of one enormous statement, and
steady state (~2.7k/day) clears in a single pass.

25_000
DELETE_LIMIT =

Destroy is far smaller per row but cascades — see #destroy_expired.

2_000

Instance Attribute Summary

Attributes inherited from BaseService

#options

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BaseService

#initialize, #log_debug, #log_error, #log_info, #log_warning, #logger, #tagged_logger

Constructor Details

This class inherits a constructor from BaseService

Class Method Details

.destroy_enabled?Boolean

Destruction is OPT-IN, and archival is not.

Archival is reversible (reprocess returns a row to ready) and touches
one column. Destruction is neither: it removes the log, its edi_documents
and its uploads, including the attachments those uploads hold in object
storage. Enabling it is a decision someone should make on purpose, with the
counts in front of them, rather than one that rides in on a deploy.

It also is NOT a clean slate on day one, which is easy to assume from
"3 months": 171 rows were archived by hand before this service existed and
their updated_at is already past DELETE_AGE, so they and their 5,788
documents / 92 uploads qualify on the first run. That is the number to weigh
when flipping this on, not the steady-state trickle.

Flip with EDI_LOG_DESTROY_ENABLED=1 (kamal env push + restart, no deploy).

Returns:

  • (Boolean)


53
# File 'app/services/maintenance/edi_communication_log_maintenance.rb', line 53

def self.destroy_enabled? = ENV['EDI_LOG_DESTROY_ENABLED'].to_b

Instance Method Details

#processHash{Symbol => Integer}

Returns archived and destroyed counts.

Returns:

  • (Hash{Symbol => Integer})

    archived and destroyed counts



56
57
58
59
60
61
# File 'app/services/maintenance/edi_communication_log_maintenance.rb', line 56

def process
  stats = { archived: archive_settled, destroyed: destroy_expired }

  log_info "EDI communication log maintenance complete — #{stats.inspect}"
  stats
end