Переглянути джерело

feat: implement atomic symlink switching for frontend builds

unknown 3 місяців тому
батько
коміт
29971ed928
5 змінених файлів з 53 додано та 9 видалено
  1. 1 1
      backend/config.py
  2. 7 2
      backend/routers/files.py
  3. 21 5
      build_frontend.sh
  4. 23 1
      server_update.sh
  5. 1 0
      src/main.ts

+ 1 - 1
backend/config.py

@@ -12,7 +12,7 @@ DEBUG = os.getenv("RADIONICA_DEBUG", "True").lower() == "true"
 
 # Slicer Settings
 # If True, triggers synchronous slicing upon file upload (slower upload, exact metrics on UI)
-SYNC_SLICING_ON_UPLOAD = os.getenv("SYNC_SLICING", "True").lower() == "true"
+SYNC_SLICING_ON_UPLOAD = os.getenv("SYNC_SLICING", "False").lower() == "true"
 IS_WINDOWS = platform.system() == "Windows"
 
 if IS_WINDOWS:

+ 7 - 2
backend/routers/files.py

@@ -1,16 +1,17 @@
 import os
 import uuid
 import hashlib
-from fastapi import APIRouter, UploadFile, File
+from fastapi import APIRouter, UploadFile, File, BackgroundTasks
 from typing import List
 import db
 import config
 import preview_utils
+from services import order_processing
 
 router = APIRouter(prefix="/files", tags=["files"])
 
 @router.post("/upload")
-async def upload_files(files: List[UploadFile] = File(...)):
+async def upload_files(background_tasks: BackgroundTasks, files: List[UploadFile] = File(...)):
     if not files: return {"uploaded": []}
     uploaded_data = []
     for file in files:
@@ -58,6 +59,10 @@ async def upload_files(files: List[UploadFile] = File(...)):
         query = "INSERT INTO order_files (order_id, filename, file_path, file_size, quantity, file_hash, print_time, filament_g, preview_path) VALUES (NULL, %s, %s, %s, 1, %s, %s, %s, %s)"
         f_id = db.execute_commit(query, (file.filename, db_file_path, file.size, file_hash, print_time, filament_g, db_preview_path))
         
+        # If preview/slicing didn't happen (not cached and not sync), run in background
+        if not print_time or not db_preview_path:
+             background_tasks.add_task(order_processing.process_single_file_async, f_id)
+
         uploaded_data.append({
             "id": f_id, "filename": file.filename, "size": file.size,
             "print_time": print_time, "filament_g": filament_g, "preview_path": db_preview_path

+ 21 - 5
build_frontend.sh

@@ -23,10 +23,26 @@ npm run i18n:generate && npx vue-tsc --noEmit
 echo "🔨 Сборка проекта (Vite / Vue 3)..."
 npm run build
 
+# Сохраняем сборку в директорию с таймштампом и переключаем симлинк
+TIMESTAMP=$(date +%Y%m%d_%H%M%S)
+NEW_DIST_DIR="dist_$TIMESTAMP"
+echo "Success! Moving build to $NEW_DIST_DIR and switching symlink..."
+mv dist $NEW_DIST_DIR
+
+# Обработка перехода от папки к симлинку
+if [ -d "dist" ] && [ ! -L "dist" ]; then
+    echo "Found legacy dist directory, backing it up..."
+    mv dist dist_legacy_backup
+fi
+
+# Атомарное переключение
+ln -sfn $NEW_DIST_DIR dist_tmp
+mv -T dist_tmp dist
+
+# Удаляем старые сборки (оставляем 5 последних)
+ls -dt dist_* | grep -E '^dist_[0-9]{8}_[0-9]{6}$' | tail -n +6 | xargs -r rm -rf || true
+
 echo "--------------------------------------------------"
-echo "✅ Готово! Продакшен-файлы лежат в директории: ./dist"
+echo "✅ Готово! Продакшен-файлы переключены на: $NEW_DIST_DIR"
+echo "Симлинк ./dist теперь указывает на свежую сборку."
 echo "--------------------------------------------------"
-echo "Дальнейшие шаги:"
-echo "1. Скопируйте содержимое ./dist на сервер в /var/www/radionica3d/html"
-echo "2. Настройте Nginx, используя файл nginx.conf"
-echo "3. Подробности в PRODUCTION_SETUP.md"

+ 23 - 1
server_update.sh

@@ -1,5 +1,7 @@
 #!/bin/bash
 # Скрипт автоматического обновления сайта
+set -e # Останавливаемся при любой ошибке
+
 PROJECT_DIR="/var/www/radionica3d"
 
 echo "==== DEPLOY STARTING: $(date) ===="
@@ -20,9 +22,29 @@ npm run i18n:generate
 
 # 4. Собираем фронтенд
 echo "building frontend..."
-rm -rf dist/ # Clean old build
+# Если dist это симлинк, npm run build (vite) может его удалить и создать папку, что нам и нужно.
+# Если это папка, он её очистит.
 npm run build
 
+# Сохраняем сборку в директорию с таймштампом и переключаем симлинк
+TIMESTAMP=$(date +%Y%m%d_%H%M%S)
+NEW_DIST_DIR="dist_$TIMESTAMP"
+echo "Moving build to $NEW_DIST_DIR and switching symlink..."
+mv dist $NEW_DIST_DIR
+
+# Обработка перехода от папки к симлинку
+if [ -d "dist" ] && [ ! -L "dist" ]; then
+    echo "Found legacy dist directory, backing it up..."
+    mv dist dist_legacy_backup
+fi
+
+# Атомарно переключаем симлинк 'dist' на новую папку
+ln -sfn $NEW_DIST_DIR dist_tmp
+mv -T dist_tmp dist
+
+# Удаляем старые сборки (оставляем 5 последних)
+ls -dt dist_* | grep -E '^dist_[0-9]{8}_[0-9]{6}$' | tail -n +6 | xargs -r rm -rf || true
+
 # 5. Обновляем бэкенд
 echo "updating backend..."
 ./backend/venv/bin/pip install -r backend/requirements.txt

+ 1 - 0
src/main.ts

@@ -17,6 +17,7 @@ const app = createApp(App);
 
 app.use(createPinia());
 app.use(createHead());
+
 app.use(MotionPlugin);
 app.use(router);
 app.use(i18n);