data_sync.sh 4.0 KB

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