bd6c1cf34f
* Storage: harden reconcile for concurrent writes and fix board transfer Reconcile now uses two-cursor approach: captures cursor before and after the storage scan, aborting if they differ (entries added during scan). Job retries 3x with 1-minute waits and limits concurrency to 1 per owner. Board transfer now correctly moves storage for card description embeds and comment embeds, not just direct attachments. Uses batched queries to handle cards with thousands of comments efficiently. Also fixes N+1 queries in attachment grouping via lookup maps. * Storage: fix per-attachment reconcile and enforce no blob reuse The storage ledger tracks per-attachment (not per-blob) as a business abstraction for quotas. This fixes reconcile to match that model and adds enforcement to prevent blob reuse in tracked contexts. * Reconcile now uses joins(:blob).sum() for per-attachment counting * New validation prevents reusing blobs across tracked attachments * Race-safe storage_total creation with create_or_find_by * Job efficiency: skip find_by when object already available * Backfill script checks per-attachment, not just per-blob
19 lines
732 B
Ruby
19 lines
732 B
Ruby
module Storage
|
|
def self.table_name_prefix
|
|
"storage_"
|
|
end
|
|
|
|
# Record types that participate in storage tracking (ledger entries created on attach).
|
|
# The no-reuse validation uses this to scope its check.
|
|
#
|
|
# IMPORTANT: Update this constant when adding tracked attachments to new models.
|
|
# If you add a direct attachment (not via RichText embeds) to Comment, Board, or
|
|
# another model with Storage::Tracked, you must add its record_type here or the
|
|
# no-reuse validation won't protect it.
|
|
TRACKED_RECORD_TYPES = %w[Card ActionText::RichText].freeze
|
|
|
|
# Account ID for template/demo blobs that can be reused cross-tenant.
|
|
# Set to nil to disable the whitelist (no exemptions).
|
|
TEMPLATE_ACCOUNT_ID = nil
|
|
end
|