You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
5.2 KiB
170 lines
5.2 KiB
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 ====="
|
|
|