1
0

data_sync.sh 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #!/bin/bash
  2. #ident "@(#)$Format:LocalFoodAI:app.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
  3. # data_sync.sh - Automated Data Freshness Pipeline
  4. LOG_DIR="./logs"
  5. mkdir -p "$LOG_DIR"
  6. LOG_FILE="$LOG_DIR/data_sync.log"
  7. # --- Auto-Detach & Sudo Auth Block ---
  8. if [ "$1" = "--detached" ]; then
  9. shift # Remove --detached from arguments for normal parsing
  10. else
  11. echo "Preparing to run ingestion in the background to survive SSH disconnections."
  12. nohup sudo "$0" --detached "$@" > "$LOG_FILE" 2>&1 < /dev/null &
  13. echo "Process successfully detached! You can now safely close your SSH connection."
  14. echo "To monitor progress at any time, type: tail -f $LOG_FILE"
  15. exit 0
  16. fi
  17. # -------------------------------------
  18. if [ -f "./.env" ]; then
  19. source ./.env
  20. fi
  21. ONLINE_MODE=0
  22. DATA_DIR="./data"
  23. INGEST_FILE="en.openfoodfacts.org.products.csv"
  24. URL="https://static.openfoodfacts.org/data/en.openfoodfacts.org.products.csv"
  25. # Parse arguments
  26. while [[ "$#" -gt 0 ]]; do
  27. case $1 in
  28. --online) ONLINE_MODE=1 ;;
  29. *) echo "Unknown parameter: $1"; exit 1 ;;
  30. esac
  31. shift
  32. done
  33. echo "Starting Data Freshness Sync at $(date)..."
  34. mkdir -p "$DATA_DIR"
  35. if [ "$ONLINE_MODE" -eq 1 ]; then
  36. echo "Online mode enabled. Checking for latest OpenFoodFacts database..."
  37. if ping -c 1 google.com &> /dev/null; then
  38. echo "Internet connection verified. Downloading latest dataset..."
  39. # Download strictly over HTTP to avoid certificate issues on some embedded devices
  40. wget -q -N -P "$DATA_DIR" "$URL"
  41. if [ $? -eq 0 ]; then
  42. echo "Download check complete."
  43. else
  44. echo "Failed to download dataset."
  45. fi
  46. else
  47. echo "No internet access detected. Falling back to offline mode."
  48. fi
  49. else
  50. echo "Offline mode. Checking $DATA_DIR for manually dropped files..."
  51. fi
  52. # Check if file exists to trigger ingestion
  53. if [ -f "$DATA_DIR/$INGEST_FILE" ]; then
  54. echo "Found dataset: $DATA_DIR/$INGEST_FILE"
  55. SHOULD_INGEST=0
  56. # 1. Checksum Validation
  57. NEW_CHECKSUM=$(md5sum "$DATA_DIR/$INGEST_FILE" | awk '{ print $1 }')
  58. OLD_CHECKSUM=""
  59. if [ -f "$DATA_DIR/checksum.md5" ]; then
  60. OLD_CHECKSUM=$(cat "$DATA_DIR/checksum.md5")
  61. fi
  62. if [ "$NEW_CHECKSUM" != "$OLD_CHECKSUM" ]; then
  63. echo "Checksum mismatch: File is new or modified. Ingestion required."
  64. SHOULD_INGEST=1
  65. else
  66. echo "Checksum matches previously processed file."
  67. fi
  68. # 2. Database Row Count Validation
  69. # Detect MySQL container name dynamically (e.g. food-mysql-1 or food_project-mysql-1)
  70. DB_CONTAINER=""
  71. if sudo docker ps --format '{{.Names}}' | grep -q "^food-mysql-1$"; then
  72. DB_CONTAINER="food-mysql-1"
  73. elif sudo docker ps --format '{{.Names}}' | grep -q "^food_project-mysql-1$"; then
  74. DB_CONTAINER="food_project-mysql-1"
  75. else
  76. DB_CONTAINER=$(sudo docker ps --format '{{.Names}}' | grep "mysql" | head -n 1)
  77. if [ -z "$DB_CONTAINER" ]; then
  78. DB_CONTAINER="food-mysql-1"
  79. fi
  80. fi
  81. DB_COUNT=$(sudo docker exec -e MYSQL_PWD="${MYSQL_ROOT_PASSWORD}" "$DB_CONTAINER" mysql -u root -N -B -e "SELECT COUNT(*) FROM food_db.products_core;" 2>/dev/null)
  82. CSV_COUNT=$(wc -l < "$DATA_DIR/$INGEST_FILE")
  83. CSV_COUNT=$((CSV_COUNT - 1)) # Ignore header
  84. if [ -z "$DB_COUNT" ]; then
  85. DB_COUNT=0
  86. fi
  87. echo "Rows in DB: $DB_COUNT | Rows in CSV: $CSV_COUNT"
  88. if [ "$DB_COUNT" -lt "$CSV_COUNT" ]; then
  89. echo "Database is missing rows. Ingestion required."
  90. SHOULD_INGEST=1
  91. fi
  92. if [ "$SHOULD_INGEST" -eq 1 ]; then
  93. echo "Triggering ingestion pipeline via Docker Compose..."
  94. sudo docker-compose run --rm ingest ./ingest_csv.py "data/$INGEST_FILE"
  95. if [ $? -eq 0 ]; then
  96. echo "$NEW_CHECKSUM" > "$DATA_DIR/checksum.md5"
  97. echo "Ingestion complete and checksum saved."
  98. else
  99. echo "Error: Ingestion failed!"
  100. fi
  101. else
  102. echo "Database is fully synchronized. Skipping ingestion."
  103. fi
  104. else
  105. echo "No dataset found in $DATA_DIR. Nothing to ingest."
  106. fi