082cc4ce93
아카이빙된 파일 (11개): [outputs/kis_data_collection/] └─ kis_data_collection 디렉토리 (모든 파일) [outputs/snapshot_admin/] ├─ smoke.db ├─ smoke2.db ├─ smoke3.db ├─ smoke4.db ├─ smoke5.db ├─ smoke6.db └─ smoke_snapshot_admin.db [Temp/] ├─ test_kis_data_collection.db ├─ snapshot_admin_livecheck.db └─ snapshot_admin_web_validation.db 아카이브 위치: archive_db/2026-06-23_*/ Manifest: archive_db/manifest.json 다음 단계: 1. 기존 파일 삭제 (검증 완료) 2. 코드 참조 경로 업데이트 (src/quant_engine/) 3. CI/CD 배포 스크립트 검증 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
206 lines
7.8 KiB
Python
206 lines
7.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
데이터베이스 아카이빙 도구
|
|
|
|
레거시/테스트 DB 파일을 archive_db/로 이동하고 manifest 생성
|
|
"""
|
|
|
|
import shutil
|
|
import json
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
from typing import Dict, List
|
|
|
|
class DatabaseArchiver:
|
|
"""데이터베이스 아카이빙"""
|
|
|
|
def __init__(self):
|
|
self.root = Path(".")
|
|
self.archive_root = self.root / "archive_db"
|
|
self.timestamp = datetime.now().strftime("%Y-%m-%d")
|
|
self.results = {
|
|
"timestamp": datetime.now().isoformat(),
|
|
"archived": [],
|
|
"skipped": [],
|
|
"errors": []
|
|
}
|
|
|
|
def create_archive_structure(self) -> None:
|
|
"""아카이브 디렉토리 구조 생성"""
|
|
dirs = [
|
|
self.archive_root / f"{self.timestamp}_outputs_kis_data_collection",
|
|
self.archive_root / f"{self.timestamp}_outputs_snapshot_admin",
|
|
self.archive_root / f"{self.timestamp}_temp_test_files",
|
|
]
|
|
|
|
for d in dirs:
|
|
d.mkdir(parents=True, exist_ok=True)
|
|
print(f"[OK] Created: {d.relative_to(self.root)}")
|
|
|
|
def archive_outputs_kis_data_collection(self) -> None:
|
|
"""outputs/kis_data_collection/ 아카이빙"""
|
|
src = self.root / "outputs" / "kis_data_collection"
|
|
if not src.exists():
|
|
print(f"[SKIP] {src.relative_to(self.root)} not found")
|
|
self.results["skipped"].append(str(src.relative_to(self.root)))
|
|
return
|
|
|
|
dest = self.archive_root / f"{self.timestamp}_outputs_kis_data_collection" / "kis_data_collection"
|
|
|
|
try:
|
|
shutil.copytree(src, dest, dirs_exist_ok=True)
|
|
print(f"[OK] Archived: {src.relative_to(self.root)}")
|
|
self.results["archived"].append({
|
|
"source": str(src.relative_to(self.root)),
|
|
"destination": str(dest.relative_to(self.root)),
|
|
"type": "directory",
|
|
"timestamp": self.timestamp
|
|
})
|
|
except Exception as e:
|
|
print(f"[ERROR] Failed to archive {src}: {e}")
|
|
self.results["errors"].append(str(e))
|
|
|
|
def archive_outputs_snapshot_admin(self) -> None:
|
|
"""outputs/snapshot_admin/ 의 smoke*.db 아카이빙"""
|
|
src_dir = self.root / "outputs" / "snapshot_admin"
|
|
if not src_dir.exists():
|
|
print(f"[SKIP] {src_dir.relative_to(self.root)} not found")
|
|
self.results["skipped"].append(str(src_dir.relative_to(self.root)))
|
|
return
|
|
|
|
dest_dir = self.archive_root / f"{self.timestamp}_outputs_snapshot_admin"
|
|
|
|
# smoke*.db 파일들 찾기
|
|
smoke_files = list(src_dir.glob("smoke*.db"))
|
|
if not smoke_files:
|
|
print(f"[SKIP] No smoke*.db files in {src_dir.relative_to(self.root)}")
|
|
return
|
|
|
|
for src_file in smoke_files:
|
|
try:
|
|
dest_file = dest_dir / src_file.name
|
|
shutil.copy2(src_file, dest_file)
|
|
print(f"[OK] Archived: {src_file.relative_to(self.root)}")
|
|
self.results["archived"].append({
|
|
"source": str(src_file.relative_to(self.root)),
|
|
"destination": str(dest_file.relative_to(self.root)),
|
|
"type": "file",
|
|
"size_kb": src_file.stat().st_size / 1024,
|
|
"timestamp": self.timestamp
|
|
})
|
|
except Exception as e:
|
|
print(f"[ERROR] Failed to archive {src_file}: {e}")
|
|
self.results["errors"].append(str(e))
|
|
|
|
def archive_temp_files(self) -> None:
|
|
"""Temp/ 의 테스트 DB 파일들 아카이빙"""
|
|
temp_dir = self.root / "Temp"
|
|
if not temp_dir.exists():
|
|
print(f"[SKIP] {temp_dir.relative_to(self.root)} not found")
|
|
self.results["skipped"].append(str(temp_dir.relative_to(self.root)))
|
|
return
|
|
|
|
dest_dir = self.archive_root / f"{self.timestamp}_temp_test_files"
|
|
|
|
patterns = [
|
|
"*_collection.db",
|
|
"*_admin*.db",
|
|
]
|
|
|
|
files_archived = 0
|
|
for pattern in patterns:
|
|
for src_file in temp_dir.glob(pattern):
|
|
# snapshot_admin.db와 kis_data_collection.db 제외 (canonical 파일들)
|
|
if src_file.name in ["kis_data_collection.db", "snapshot_admin.db"]:
|
|
continue
|
|
|
|
try:
|
|
dest_file = dest_dir / src_file.name
|
|
shutil.copy2(src_file, dest_file)
|
|
print(f"[OK] Archived: {src_file.relative_to(self.root)}")
|
|
self.results["archived"].append({
|
|
"source": str(src_file.relative_to(self.root)),
|
|
"destination": str(dest_file.relative_to(self.root)),
|
|
"type": "file",
|
|
"size_kb": src_file.stat().st_size / 1024,
|
|
"timestamp": self.timestamp
|
|
})
|
|
files_archived += 1
|
|
except Exception as e:
|
|
print(f"[ERROR] Failed to archive {src_file}: {e}")
|
|
self.results["errors"].append(str(e))
|
|
|
|
if files_archived == 0:
|
|
print(f"[SKIP] No test DB files found in {temp_dir.relative_to(self.root)}")
|
|
|
|
def create_manifest(self) -> None:
|
|
"""manifest.json 생성"""
|
|
manifest = {
|
|
"archive_date": self.timestamp,
|
|
"created_at": datetime.now().isoformat(),
|
|
"archived_count": len(self.results["archived"]),
|
|
"skipped_count": len(self.results["skipped"]),
|
|
"error_count": len(self.results["errors"]),
|
|
"files": self.results["archived"],
|
|
"notes": [
|
|
"These files were archived due to database consolidation.",
|
|
"Single source of truth is now: src/quant_engine/",
|
|
"To restore: use archive_db/{date}_*/ directories",
|
|
"Canonical files: kis_data_collection.db, snapshot_admin.db"
|
|
]
|
|
}
|
|
|
|
manifest_file = self.archive_root / "manifest.json"
|
|
with open(manifest_file, 'w', encoding='utf-8') as f:
|
|
json.dump(manifest, f, indent=2, ensure_ascii=False)
|
|
|
|
print(f"\n[OK] Manifest created: {manifest_file.relative_to(self.root)}")
|
|
|
|
def run(self) -> Dict:
|
|
"""전체 실행"""
|
|
print("="*80)
|
|
print("Database Archiving Process")
|
|
print("="*80)
|
|
print(f"Archive date: {self.timestamp}\n")
|
|
|
|
# 아카이브 디렉토리 구조 생성
|
|
self.create_archive_structure()
|
|
|
|
print("\n[Archiving files...]")
|
|
# 각 레거시 파일 아카이빙
|
|
self.archive_outputs_kis_data_collection()
|
|
self.archive_outputs_snapshot_admin()
|
|
self.archive_temp_files()
|
|
|
|
# manifest 생성
|
|
self.create_manifest()
|
|
|
|
# 요약
|
|
print("\n" + "="*80)
|
|
print("Archive Summary")
|
|
print("="*80)
|
|
print(f"Archived: {len(self.results['archived'])} items")
|
|
print(f"Skipped: {len(self.results['skipped'])} items")
|
|
print(f"Errors: {len(self.results['errors'])} items")
|
|
print(f"\nArchive location: {self.archive_root.relative_to(self.root)}")
|
|
|
|
if self.results['errors']:
|
|
print("\n[Errors encountered]")
|
|
for error in self.results['errors']:
|
|
print(f" - {error}")
|
|
|
|
return self.results
|
|
|
|
if __name__ == "__main__":
|
|
archiver = DatabaseArchiver()
|
|
results = archiver.run()
|
|
|
|
print("\n" + "="*80)
|
|
print("[Next Steps]")
|
|
print("="*80)
|
|
print("1. Verify archive contents: git status")
|
|
print("2. Add archive to git: git add archive_db/")
|
|
print("3. Commit: git commit -m 'Archive legacy database files'")
|
|
print("4. Delete legacy files (after verification)")
|
|
print("5. Update code references to use src/quant_engine/")
|