cd /opt/otb_cloud || exit 1 echo "===== backups =====" STAMP=$(date +%Y%m%d-%H%M%S) cp app/models/schema.sql /home/def/backuphere/schema.sql.$STAMP.bak cp app/auth/utils.py /home/def/backuphere/utils.py.$STAMP.bak cp VERSION /home/def/backuphere/VERSION.$STAMP.bak 2>/dev/null || true cp PROJECT_STATE.md /home/def/backuphere/PROJECT_STATE.md.$STAMP.bak 2>/dev/null || true cp README.md /home/def/backuphere/README.md.$STAMP.bak 2>/dev/null || true echo "===== extend schema =====" cat >> app/models/schema.sql <<'EOF' -- =============================== -- v1.1.0-alpha1 VIDEO JOB SYSTEM -- =============================== CREATE TABLE IF NOT EXISTS video_jobs ( id BIGINT AUTO_INCREMENT PRIMARY KEY, tenant_id INT NOT NULL, device_id INT NOT NULL, source_file_id BIGINT NULL, source_relative_path VARCHAR(1000) NOT NULL, source_original_filename VARCHAR(255) NOT NULL, requested_profile VARCHAR(50) NOT NULL, requested_gpu_preference VARCHAR(20) NOT NULL DEFAULT 'auto', assigned_processor VARCHAR(20) NULL, status VARCHAR(50) NOT NULL DEFAULT 'queued', progress_percent INT NOT NULL DEFAULT 0, output_relative_path VARCHAR(1000) NULL, output_file_id BIGINT NULL, log_excerpt LONGTEXT NULL, error_message LONGTEXT NULL, gpu_seconds INT NOT NULL DEFAULT 0, started_at DATETIME NULL, completed_at DATETIME NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, created_by_user_id INT NULL, CONSTRAINT fk_video_jobs_tenant FOREIGN KEY (tenant_id) REFERENCES tenants(id), CONSTRAINT fk_video_jobs_device FOREIGN KEY (device_id) REFERENCES devices(id) ); CREATE TABLE IF NOT EXISTS tenant_usage_metrics ( id BIGINT AUTO_INCREMENT PRIMARY KEY, tenant_id INT NOT NULL, storage_bytes_originals BIGINT NOT NULL DEFAULT 0, storage_bytes_video BIGINT NOT NULL DEFAULT 0, storage_bytes_archive BIGINT NOT NULL DEFAULT 0, storage_bytes_lts BIGINT NOT NULL DEFAULT 0, storage_bytes_total BIGINT NOT NULL DEFAULT 0, gpu_seconds_intel BIGINT NOT NULL DEFAULT 0, gpu_seconds_amd BIGINT NOT NULL DEFAULT 0, gpu_seconds_cpu BIGINT NOT NULL DEFAULT 0, completed_jobs INT NOT NULL DEFAULT 0, failed_jobs INT NOT NULL DEFAULT 0, accrued_storage_cost DECIMAL(12,2) NOT NULL DEFAULT 0.00, accrued_gpu_cost DECIMAL(12,2) NOT NULL DEFAULT 0.00, calculated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_metrics_tenant FOREIGN KEY (tenant_id) REFERENCES tenants(id) ); EOF echo "===== update device directory structure =====" python3 <<'PY' from pathlib import Path p = Path("app/auth/utils.py") txt = p.read_text() old = """for subdir in ["originals", "derived", "exports", "deleted", "tmp"]:""" new = """for subdir in ["originals", "video", "video-workshop", "archive", "lts", "derived", "exports", "deleted", "tmp"]:""" if old not in txt: raise SystemExit("PATCH FAIL: device dir block not found") txt = txt.replace(old, new) p.write_text(txt) print("device directory structure updated") PY echo "===== create service scaffolding =====" mkdir -p app/services cat > app/services/video_jobs.py <<'EOF' def create_job(db, tenant_id, device_id, source_path, filename, profile): return { "tenant_id": tenant_id, "device_id": device_id, "source_path": source_path, "filename": filename, "profile": profile, "status": "queued" } EOF cat > app/services/video_metrics.py <<'EOF' def recalc_metrics(db, tenant_id): # placeholder for v1.1.0 return {"ok": True} EOF cat > app/services/gpu_select.py <<'EOF' def select_processor(): # v1.1.0 logic placeholder return "intel" EOF cat > app/services/video_profiles.py <<'EOF' PROFILES = { "portrait_web": "portrait web encode", "landscape_web": "landscape web encode", "high_quality_cpu": "cpu encode", "archive_only": "no processing" } EOF cat > app/services/video_paths.py <<'EOF' def device_paths(base): return { "originals": f"{base}/originals", "video": f"{base}/video", "video_workshop": f"{base}/video-workshop", "archive": f"{base}/archive", "lts": f"{base}/lts" } EOF echo "===== create worker scaffold =====" cat > app/services/video_worker.py <<'EOF' import time def run_worker(): print("video worker starting (stub)") while True: time.sleep(10) EOF echo "===== bump version =====" echo "v1.1.0-alpha1" > VERSION echo "===== update PROJECT_STATE.md =====" cat >> PROJECT_STATE.md <<'EOF' ## v1.1.0-alpha1 — Video System Foundation - Added video_jobs table (processing queue) - Added tenant_usage_metrics table (dashboard metrics) - Added video service scaffolding (jobs, metrics, gpu select, profiles) - Extended device structure to include: - video - video-workshop - archive - lts - Prepared system for background worker architecture Next step: - Build video worker processing engine EOF echo "===== update README.md =====" sed -i '1i\ ## v1.1.0-alpha1 — Video System Foundation\n- Introduced video job queue system\n- Introduced tenant usage metrics\n- Added video processing scaffolding\n- Prepared for GPU worker processing\n' README.md echo "===== verify =====" python3 -m py_compile app/auth/utils.py echo "===== done ====="