File size: 4,258 Bytes
d21d361
 
 
62b22d6
 
 
 
 
 
 
7bccdc7
d21d361
62b22d6
 
d21d361
 
 
7bccdc7
 
ac21efd
62b22d6
7bccdc7
 
62b22d6
7bccdc7
 
 
 
 
ac21efd
62b22d6
7bccdc7
 
62b22d6
 
 
 
 
 
 
 
 
 
 
 
d21d361
7bccdc7
 
 
 
 
62b22d6
7bccdc7
 
 
 
62b22d6
7bccdc7
 
 
 
 
 
d21d361
7bccdc7
 
 
62b22d6
7bccdc7
62b22d6
 
7bccdc7
 
62b22d6
7bccdc7
 
62b22d6
7bccdc7
 
62b22d6
d21d361
7bccdc7
 
62b22d6
d21d361
 
 
 
62b22d6
7bccdc7
 
62b22d6
ac21efd
7bccdc7
ac21efd
7bccdc7
 
 
62b22d6
7bccdc7
62b22d6
7bccdc7
 
 
 
 
 
 
62b22d6
7bccdc7
ac21efd
7bccdc7
ac21efd
7bccdc7
 
 
 
 
 
 
62b22d6
7bccdc7
 
 
62b22d6
7bccdc7
 
 
62b22d6
7bccdc7
62b22d6
7bccdc7
 
 
 
 
62b22d6
7bccdc7
 
 
 
62b22d6
ac21efd
62b22d6
ac21efd
62b22d6
ac21efd
 
62b22d6
 
 
7bccdc7
62b22d6
d21d361
7bccdc7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/usr/bin/env bash
set -e

log() {
  echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] $*"
}

log "======================================"
log "PostgreSQL General HF Space starting"
log "======================================"

if [ -z "$POSTGRES_PASSWORD" ]; then
  log "ERROR: POSTGRES_PASSWORD is not set."
  log "Please set POSTGRES_PASSWORD in Hugging Face Space Secrets."
  exit 1
fi

export POSTGRES_USER="${POSTGRES_USER:-admin}"
export POSTGRES_DB="${POSTGRES_DB:-appdb}"

# PostgreSQL runtime data directory: use Space local disk.
export PGDATA="${PGDATA:-/home/user/pgdata}"

# Mounted storage bucket directories.
export DATA_DIR="${DATA_DIR:-/data}"
export BACKUP_DIR="${BACKUP_DIR:-/data/backups}"
export USER_FILE_DIR="${USER_FILE_DIR:-/data/files}"
export EXPORT_DIR="${EXPORT_DIR:-/data/exports}"
export GENERATED_DIR="${GENERATED_DIR:-/data/generated}"

# Automatic backup interval, default: 1 hour.
export BACKUP_INTERVAL_SECONDS="${BACKUP_INTERVAL_SECONDS:-3600}"

log "Runtime configuration:"
log "POSTGRES_USER=$POSTGRES_USER"
log "POSTGRES_DB=$POSTGRES_DB"
log "PGDATA=$PGDATA"
log "DATA_DIR=$DATA_DIR"
log "BACKUP_DIR=$BACKUP_DIR"
log "USER_FILE_DIR=$USER_FILE_DIR"
log "EXPORT_DIR=$EXPORT_DIR"
log "GENERATED_DIR=$GENERATED_DIR"
log "BACKUP_INTERVAL_SECONDS=$BACKUP_INTERVAL_SECONDS"

log "Creating directories..."
mkdir -p "$PGDATA"
mkdir -p "$BACKUP_DIR"
mkdir -p "$USER_FILE_DIR"
mkdir -p "$EXPORT_DIR"
mkdir -p "$GENERATED_DIR"

# PostgreSQL needs a private data directory. Allow permission changes to fail on restricted runtimes.
chown -R postgres:postgres "$PGDATA" || true
chmod 700 "$PGDATA" || true
chmod -R 755 "$DATA_DIR" || true

log "Directory status:"
ls -ld "$PGDATA" || true
ls -ld "$DATA_DIR" || true
ls -ld "$BACKUP_DIR" || true
ls -ld "$USER_FILE_DIR" || true
ls -ld "$EXPORT_DIR" || true
ls -ld "$GENERATED_DIR" || true

RESTORE_BACKUP=0

if [ ! -s "$PGDATA/PG_VERSION" ]; then
  log "No existing PostgreSQL data directory found."
  if [ -f "$BACKUP_DIR/latest.sql" ]; then
    log "Backup file found: $BACKUP_DIR/latest.sql"
    log "Database will be restored after PostgreSQL initialization."
    RESTORE_BACKUP=1
  else
    log "No backup file found. A new database will be initialized."
  fi
else
  log "Existing PostgreSQL data directory found."
fi

log "Starting PostgreSQL..."
docker-entrypoint.sh postgres &
POSTGRES_PID=$!

log "Waiting for PostgreSQL to become ready..."
until pg_isready -h 127.0.0.1 -p 5432 -U "$POSTGRES_USER"; do
  sleep 2
done

log "PostgreSQL is ready."

if [ "$RESTORE_BACKUP" = "1" ]; then
  log "Restoring database from $BACKUP_DIR/latest.sql ..."
  PGPASSWORD="$POSTGRES_PASSWORD" psql \
    -h 127.0.0.1 \
    -p 5432 \
    -U "$POSTGRES_USER" \
    -d "$POSTGRES_DB" \
    < "$BACKUP_DIR/latest.sql" || {
      log "WARNING: Restore failed. Please check backup file."
    }
  log "Restore process finished."
fi

create_backup() {
  TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
  BACKUP_FILE="$BACKUP_DIR/backup_${POSTGRES_DB}_${TIMESTAMP}.sql"
  LATEST_FILE="$BACKUP_DIR/latest.sql"

  log "Creating backup: $BACKUP_FILE"

  PGPASSWORD="$POSTGRES_PASSWORD" pg_dump \
    -h 127.0.0.1 \
    -p 5432 \
    -U "$POSTGRES_USER" \
    -d "$POSTGRES_DB" \
    > "$BACKUP_FILE.tmp"

  mv "$BACKUP_FILE.tmp" "$BACKUP_FILE"
  cp "$BACKUP_FILE" "$LATEST_FILE"

  log "Backup saved: $BACKUP_FILE and $LATEST_FILE"
}

backup_loop() {
  log "Backup loop started. Interval: ${BACKUP_INTERVAL_SECONDS}s"
  while true; do
    sleep "$BACKUP_INTERVAL_SECONDS"
    if pg_isready -h 127.0.0.1 -p 5432 -U "$POSTGRES_USER"; then
      create_backup || log "WARNING: Backup failed."
    else
      log "WARNING: PostgreSQL is not ready. Backup skipped."
    fi
  done
}

if pg_isready -h 127.0.0.1 -p 5432 -U "$POSTGRES_USER"; then
  create_backup || log "WARNING: Initial backup failed."
fi

backup_loop &

log "Checking PHP PostgreSQL extension for optional Adminer usage..."
if php -m | grep -Ei "pgsql|pdo_pgsql" > /dev/null; then
  log "PHP PostgreSQL extension loaded."
else
  log "WARNING: PHP PostgreSQL extension is not loaded. Adminer may not work."
fi

log "Starting FastAPI on port 7860..."
log "API docs: /docs"
log "Health: /api/health"

uvicorn api:app --host 0.0.0.0 --port 7860

wait "$POSTGRES_PID"