File size: 2,853 Bytes
cdf9dc5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
db492e1
 
cdf9dc5
db492e1
 
cdf9dc5
db492e1
cdf9dc5
 
 
db492e1
 
cdf9dc5
db492e1
 
cdf9dc5
db492e1
cdf9dc5
 
 
 
 
 
 
 
 
 
db492e1
cdf9dc5
 
 
db492e1
cdf9dc5
 
 
db492e1
 
 
 
 
 
 
 
cdf9dc5
 
 
db492e1
 
cdf9dc5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
db492e1
cdf9dc5
 
db492e1
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
#!/usr/bin/env bash
set -euo pipefail

DATA_ROOT="${DATA_ROOT:-/data/root}"
SYNC_INTERVAL="${SYNC_INTERVAL:-300}"
CONFIG_PATH=".openclaw/openclaw.json"

EXCLUDES=(
  "--exclude=.cache"
  "--exclude=.npm/_cacache"
  "--exclude=.npm/_update-notifier-last-checked*"
  "--exclude=.pnpm-store"
  "--exclude=node_modules"
  "--exclude=.next"
  "--exclude=dist"
  "--exclude=build"
  "--exclude=coverage"
  "--exclude=tmp"
)

data_available() {
  [ -d /data ] || mkdir -p /data 2>/dev/null || return 1
  mkdir -p "$DATA_ROOT" 2>/dev/null || return 1
}

# /root → /data  (--update: hanya file lebih baru di root yg masuk data)
persist_root() {
  if data_available; then
    echo "Syncing /root → $DATA_ROOT (update: root wins if newer)..."
    rsync -rlptD --no-specials --no-devices --update --delete "${EXCLUDES[@]}" /root/ "$DATA_ROOT/" || true
  else
    echo "Persistent /data is not available; skipping persist."
  fi
}

# /data → /root  (FORCE: data selalu menang, tanpa --update)
restore_root() {
  if data_available; then
    echo "Restoring $DATA_ROOT → /root (force: data always wins)..."
    rsync -rlptD --no-specials --no-devices "${EXCLUDES[@]}" "$DATA_ROOT/" /root/ || true
  else
    echo "Persistent /data is not available; skipping restore."
  fi
}

sync_config_newer() {
  local root_config="/root/$CONFIG_PATH"
  local data_config="$DATA_ROOT/$CONFIG_PATH"

  if [ -f "$data_config" ] && { [ ! -f "$root_config" ] || [ "$data_config" -nt "$root_config" ]; }; then
    mkdir -p "$(dirname "$root_config")"
    cp -p "$data_config" "$root_config" || true
    echo "Pulled newer OpenClaw config: $data_config$root_config"
  elif [ -f "$root_config" ] && { [ ! -f "$data_config" ] || [ "$root_config" -nt "$data_config" ]; }; then
    mkdir -p "$(dirname "$data_config")"
    cp -p "$root_config" "$data_config" || true
    echo "Persisted newer OpenClaw config: $root_config$data_config"
  fi
}

# Urutan penting:
#   1. persist  → /root → /data  (--update, perubahan root masuk data dulu)
#   2. config   → two-way reconcile openclaw.json
#   3. restore  → /data → /root  (force, data selalu menang sebagai sumber kebenaran)
#
# Efeknya:
#   - Root berubah  → masuk data di step 1, restore step 3 no-op (sudah sama) ✓
#   - Data berubah  → step 1 tidak tumpuk data (--update), step 3 force ke root   ✓
reconcile_root_data() {
  if data_available; then
    persist_root
    sync_config_newer
    restore_root
  else
    echo "Persistent /data is not available; skipping two-way sync."
  fi
}

case "${1:-loop}" in
  restore)
    restore_root
    ;;
  persist)
    persist_root
    ;;
  reconcile)
    reconcile_root_data
    ;;
  loop)
    while true; do
      reconcile_root_data
      sleep "$SYNC_INTERVAL"
    done
    ;;
  *)
    echo "Usage: $0 {restore|persist|reconcile|loop}"
    exit 2
    ;;
esac