Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-01 09:34:21

0001 """Remove the superseded counter-form errors component from snap history.
0002 
0003 The errors component's first day recorded running counters (version 1);
0004 the interval-entries record (version 2, docs/SNAPPER_ERRORS.md) and its
0005 backfill supersede that span completely. This script removes the
0006 counter-form errors member from epicprod snap history:
0007 
0008 - A snap whose only changed component was errors is deleted — its
0009   other-component state duplicates the preceding snap.
0010 - A snap that also carried other components' changes (or a baseline
0011   copy) keeps its row; the errors member is stripped from the state
0012   and the envelope vectors, and the composed state hash is cleared as
0013   no longer computed.
0014 
0015 Rows written by the entries backfill (capture policy
0016 backfill-errors-v1) and version-2 entries snaps are never touched. A
0017 row referenced by a capture cursor is stripped rather than deleted.
0018 Idempotent; dry-run default.
0019 
0020 Run under the venv with the swf-monitor project on the path:
0021 
0022     cd <swf-monitor>/src && source <venv>/bin/activate && source ~/.env
0023     python <swf-monitor>/scripts/cleanup-errors-counter-era.py [--apply]
0024 """
0025 
0026 import argparse
0027 import os
0028 import sys
0029 
0030 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'swf_monitor_project.settings')
0031 
0032 import django  # noqa: E402
0033 
0034 django.setup()
0035 
0036 from snapper_ai.models import CaptureCursor, SystemSnap  # noqa: E402
0037 
0038 BACKFILL_POLICY = 'backfill-errors-v1'
0039 
0040 
0041 def main():
0042     parser = argparse.ArgumentParser(
0043         description='Remove the counter-form errors component from '
0044                     'epicprod snap history.')
0045     parser.add_argument('--apply', action='store_true',
0046                         help='write the changes (dry run without)')
0047     args = parser.parse_args()
0048 
0049     protected = set(
0050         CaptureCursor.objects
0051         .filter(latest_snap__isnull=False)
0052         .values_list('latest_snap_id', flat=True))
0053 
0054     rows = (SystemSnap.objects
0055             .filter(scope='epicprod',
0056                     state__components__has_key='errors')
0057             .exclude(capture_policy=BACKFILL_POLICY)
0058             .order_by('snap_time'))
0059 
0060     deletions = []
0061     strips = []
0062     for snap in rows.iterator():
0063         errors = (snap.state.get('components') or {}).get('errors') or {}
0064         if 'entries' in (errors.get('data') or {}):
0065             continue
0066         changed = list(snap.changed_components or [])
0067         if changed == ['errors'] and snap.id not in protected:
0068             deletions.append(snap)
0069         else:
0070             strips.append(snap)
0071 
0072     print(f'counter-form errors members found: '
0073           f'{len(deletions) + len(strips)}')
0074     print(f'  rows to delete (errors-only change): {len(deletions)}')
0075     print(f'  rows to strip (other components kept): {len(strips)}')
0076     for snap in (deletions + strips)[:3]:
0077         print(f'  e.g. {snap.snap_time.isoformat()} '
0078               f'changed={snap.changed_components}')
0079 
0080     if not args.apply:
0081         print('\ndry run — nothing written; --apply performs the cleanup')
0082         return 0
0083 
0084     deleted = 0
0085     for snap in deletions:
0086         snap.delete()
0087         deleted += 1
0088     stripped = 0
0089     for snap in strips:
0090         snap.state.get('components', {}).pop('errors', None)
0091         snap.changed_components = [
0092             name for name in (snap.changed_components or [])
0093             if name != 'errors']
0094         for field in ('component_revisions', 'registration_versions',
0095                       'component_hashes'):
0096             mapping = getattr(snap, field) or {}
0097             mapping.pop('errors', None)
0098             setattr(snap, field, mapping)
0099         snap.state_hash = ''
0100         snap.save(update_fields=[
0101             'state', 'changed_components', 'component_revisions',
0102             'registration_versions', 'component_hashes', 'state_hash'])
0103         stripped += 1
0104     print(f'\napplied: deleted {deleted}, stripped {stripped}')
0105     return 0
0106 
0107 
0108 if __name__ == '__main__':
0109     sys.exit(main())