replaced inotify with a polling loop

This commit is contained in:
2026-03-05 09:03:18 -05:00
parent 32f52f3faf
commit 0c39445d71
3 changed files with 53 additions and 35 deletions

View File

@@ -1,13 +1,14 @@
#!/usr/bin/env bash
# watch-imports.sh - Watch for new CSV files, flip sign on 4th column for
# watch-imports.sh - Poll for new CSV files, flip sign on 4th column for
# specific accounts, then stage them in the imports/ directory.
#
# Uses polling — compatible with NFS and other network filesystems.
#
# Usage:
# ./watch-imports.sh # watch continuously (requires inotify-tools)
# ./watch-imports.sh # poll continuously
# ./watch-imports.sh --once # process existing files in INCOMING_DIR and exit
#
# Requires: inotify-tools (sudo apt-get install inotify-tools)
# python3 (standard on Ubuntu)
# Requires: python3 (standard on Ubuntu)
set -euo pipefail
@@ -35,6 +36,8 @@ fi
INCOMING_DIR="${INCOMING_DIR:-$SCRIPT_DIR/incoming}"
IMPORT_DIR="${IMPORT_DIR:-$SCRIPT_DIR/imports}"
AUTO_IMPORT="${AUTO_IMPORT:-false}"
POLL_INTERVAL="${POLL_INTERVAL:-10}" # seconds between directory scans
FILE_STABLE_AGE="${FILE_STABLE_AGE:-3}" # seconds a file must be unmodified before processing
# Files whose 4th column values should have their sign flipped
FLIP_FILES=(
@@ -62,6 +65,17 @@ needs_flip() {
return 1
}
# Returns true if the file hasn't been modified in the last FILE_STABLE_AGE seconds.
# Prevents processing a file that's still being uploaded over the network.
is_stable() {
local filepath="$1"
local mtime now age
mtime=$(stat -c%Y "$filepath" 2>/dev/null) || return 1
now=$(date +%s)
age=$(( now - mtime ))
[[ "$age" -ge "$FILE_STABLE_AGE" ]]
}
# Flip the sign of all numeric values in the 4th column using python3.
# Handles quoted CSV fields correctly.
flip_fourth_column() {
@@ -124,35 +138,29 @@ process_csv() {
fi
}
poll_once() {
while IFS= read -r filepath; do
if ! is_stable "$filepath"; then
info "Still writing: $(basename "$filepath") — will retry next poll"
continue
fi
process_csv "$filepath"
done < <(find "$INCOMING_DIR" -maxdepth 1 -name '*.csv' 2>/dev/null | sort)
}
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
mkdir -p "$INCOMING_DIR" "$IMPORT_DIR"
if $ONCE_MODE; then
mapfile -t existing < <(find "$INCOMING_DIR" -maxdepth 1 -name '*.csv' | sort)
if [[ ${#existing[@]} -eq 0 ]]; then
info "No CSV files found in $INCOMING_DIR"
exit 0
fi
for f in "${existing[@]}"; do
process_csv "$f"
done
poll_once
exit 0
fi
# Continuous watch mode
if ! command -v inotifywait &>/dev/null; then
echo "inotify-tools not found. Install with:"
echo " sudo apt-get install inotify-tools"
exit 1
fi
info "Polling $INCOMING_DIR every ${POLL_INTERVAL}s... (Ctrl+C to stop)"
info "Watching $INCOMING_DIR for new CSV files... (Ctrl+C to stop)"
inotifywait -m -e close_write -e moved_to --format '%f' "$INCOMING_DIR" \
| while IFS= read -r filename; do
if [[ "$filename" == *.csv ]]; then
process_csv "$INCOMING_DIR/$filename"
fi
done
while true; do
poll_once
sleep "$POLL_INTERVAL"
done