File indexing completed on 2026-11-09 10:47:22
0001
0002 """front-cycle.py — one decision cycle of the pressure front: for each
0003 regulated queue, the census, the gates and the ready backlog decide
0004 feed or hold with a reason, recorded on the action stream
0005 (swf-epicprod docs/CONTINUOUS_PRODUCTION.md, The dispatcher; logic in
0006 swf_epicprod/front.py).
0007
0008 The prod-ops agent's doer for ``front_cycle``, every five minutes by
0009 cron enqueue. In shadow mode (SysConfig ``front.mode``) it submits
0010 nothing and records what it would have done. Django-bootstrap
0011 standalone script, also usable by hand::
0012
0013 cd /data/wenauseic/github/swf-monitor/src
0014 source ../../swf-testbed/.venv/bin/activate && source ~/.env
0015 python ../scripts/front-cycle.py [--dry-run] [--created-by NAME]
0016
0017 ``--dry-run`` prints every queue's decision and writes no record.
0018 Prints one ``SUMMARY`` JSON line; exit 1 on failure.
0019 """
0020 import argparse
0021 import json
0022 import os
0023 import sys
0024
0025 THIS_DIR = os.path.dirname(os.path.abspath(__file__))
0026 sys.path.insert(0, os.path.join(THIS_DIR, '..', 'src'))
0027 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'swf_monitor_project.settings')
0028
0029 import django
0030 django.setup()
0031
0032 from swf_epicprod.front import run_cycle
0033
0034
0035 def main():
0036 ap = argparse.ArgumentParser(description=__doc__.split('\n\n')[0])
0037 ap.add_argument('--dry-run', action='store_true',
0038 help='decide and print, record nothing')
0039 ap.add_argument('--created-by', default='front',
0040 help='who runs the cycle (the records carry it)')
0041 args = ap.parse_args()
0042 try:
0043 decisions, summary = run_cycle(dry_run=args.dry_run,
0044 created_by=args.created_by)
0045 except Exception as exc:
0046 print(f'ERROR: {type(exc).__name__}: {exc}', file=sys.stderr)
0047 return 1
0048 for d in decisions:
0049 depth = d['committed_h'] if d['committed_h'] is not None else 'n/a'
0050 print(f"{d['queue']}: {d['state']} ({d['reason']}) committed {depth} h "
0051 f"of {d['h_low']}-{d['h_high']}; ready {d['ready_eligible']}/{d['ready_total']}"
0052 f"{' recorded' if d['recorded'] and not args.dry_run else ''}")
0053 print('SUMMARY ' + json.dumps(summary, default=str))
0054 return 0
0055
0056
0057 if __name__ == '__main__':
0058 sys.exit(main())