manage-industry-tasks.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. """Prepare and coordinate local evidence audits. Does not call VOC or issue collection requests."""
  2. import argparse
  3. import json
  4. from pathlib import Path
  5. import sys
  6. sys.path.insert(0, str(Path(__file__).resolve().parents[1] / 'server/voc-library'))
  7. from industry_monitor import load, Monitor
  8. from monitoring_store import need
  9. from monitoring_tasks import seed, claim, release, finish, reconcile, read_tasks
  10. def json_arg(value):
  11. return json.loads(Path(value[1:]).read_text('utf-8-sig') if value.startswith('@') else value)
  12. def main():
  13. p = argparse.ArgumentParser(description=__doc__)
  14. p.add_argument('command', choices=['seed', 'list', 'claim', 'release', 'receipt', 'reconcile'])
  15. p.add_argument('--store', required=True)
  16. p.add_argument('--snapshot')
  17. p.add_argument('--registry')
  18. p.add_argument('--db')
  19. p.add_argument('--generation', required=True)
  20. p.add_argument('--filters', default='{}', help='JSON or @file')
  21. p.add_argument('--kinds', default='listings,reviews,rankings')
  22. p.add_argument('--task-id')
  23. p.add_argument('--owner')
  24. p.add_argument('--lease', type=int, default=1800)
  25. p.add_argument('--lease-file', help='Private local claim JSON; token is never accepted through HTTP')
  26. p.add_argument('--receipt', help='JSON or @file')
  27. p.add_argument('--page', type=int, default=1)
  28. p.add_argument('--state')
  29. p.add_argument('--kind')
  30. args = p.parse_args()
  31. try:
  32. data = load({k: getattr(args, k) for k in ('snapshot', 'registry', 'db') if getattr(args, k)})
  33. need(data['generation'] == args.generation, 'LIBRARY_VERSION_CHANGED')
  34. monitor, filters = Monitor(data), json_arg(args.filters)
  35. products = monitor.selected(filters)
  36. if args.command == 'seed':
  37. result = seed(args.store, monitor, filters, args.kinds.split(','))
  38. elif args.command == 'list':
  39. result = {'ok': True, **read_tasks(args.store, args.generation, filters, {p['record_id'] for p in products}, args.state, args.kind, args.page)}
  40. elif args.command == 'reconcile':
  41. result = reconcile(args.store, args.generation)
  42. elif args.command == 'claim':
  43. need(args.task_id and args.owner, 'TASK_AND_OWNER_REQUIRED')
  44. result = claim(args.store, args.task_id, args.owner, args.generation, args.lease)
  45. else:
  46. need(args.lease_file, 'PRIVATE_LEASE_FILE_REQUIRED')
  47. lease = json.loads(Path(args.lease_file).read_text('utf-8-sig'))
  48. need(not args.task_id or args.task_id == lease['taskId'], 'TASK_LEASE_MISMATCH')
  49. arguments = [args.store, lease['taskId'], lease['owner'], lease['leaseToken'], args.generation]
  50. if args.command == 'release':
  51. result = release(*arguments)
  52. else:
  53. need(args.receipt, 'TASK_RECEIPT_REQUIRED')
  54. result = finish(*arguments, json_arg(args.receipt))
  55. print(json.dumps(result, ensure_ascii=False))
  56. except Exception as error:
  57. print(json.dumps({'ok': False, 'error': str(error) if isinstance(error, ValueError) else 'TASK_OPERATION_FAILED'}, ensure_ascii=False))
  58. sys.exit(1)
  59. if __name__ == '__main__':
  60. main()