| """ |
| Backfill persistent identifiers: DocID™ + ARK for items missing them. |
| |
| ARKs are minted deterministically from the item's DocID hash, so re-running |
| is idempotent. No network access needed. |
| |
| Usage: |
| python scripts/backfill_pids.py # DRY RUN |
| python scripts/backfill_pids.py --apply |
| """ |
|
|
| import argparse |
| import os |
| import sys |
| from datetime import datetime |
|
|
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
|
|
| from uraas.database import Item, SessionLocal |
| from uraas.utils.ark_generator import ark_generator |
| from uraas.utils.docid_generator import docid_generator |
|
|
|
|
| def main(): |
| parser = argparse.ArgumentParser(description=__doc__) |
| parser.add_argument("--apply", action="store_true", help="Write changes (default: dry run)") |
| args = parser.parse_args() |
|
|
| session = SessionLocal() |
| try: |
| need_docid = session.query(Item).filter(Item.docid.is_(None)).count() |
| need_ark = session.query(Item).filter(Item.ark.is_(None)).count() |
| print("=" * 64) |
| print(f"Items missing DocID: {need_docid} missing ARK: {need_ark}") |
| print("=" * 64) |
| if not args.apply: |
| print("[DRY RUN] No writes. Re-run with --apply.") |
| return 0 |
|
|
| minted_docid = minted_ark = 0 |
| now = datetime.utcnow() |
| for it in session.query(Item).filter( |
| (Item.docid.is_(None)) | (Item.ark.is_(None)) |
| ): |
| if not it.docid: |
| it.docid = docid_generator.generate_docid( |
| title=it.title or "", |
| doi=it.doi, |
| institution=it.institution or "Unknown", |
| timestamp=it.publication_date, |
| ) |
| it.docid_assigned_at = now |
| minted_docid += 1 |
| if not it.ark: |
| it.ark = ark_generator.mint(it.docid) |
| it.ark_assigned_at = now |
| minted_ark += 1 |
| session.commit() |
|
|
| print(f"DONE. DocIDs minted: {minted_docid} ARKs minted: {minted_ark}") |
| sample = session.query(Item.ark).filter(Item.ark.isnot(None)).first() |
| if sample: |
| print(f"Sample ARK: {sample[0]} (valid: {ark_generator.validate(sample[0])})") |
| return 0 |
| finally: |
| session.close() |
|
|
|
|
| if __name__ == "__main__": |
| sys.exit(main()) |
|
|