Davidtran99 commited on
Commit
3718c84
·
1 Parent(s): eef3d60

chore: sync with main repo

Browse files
Dockerfile CHANGED
@@ -54,11 +54,73 @@ fi
54
  echo "[Docker] Collecting static files..."
55
  python /app/hue_portal/manage.py collectstatic --noinput || echo "[Docker] Collectstatic failed, continuing..."
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  echo "[Docker] Starting gunicorn..."
58
- exec gunicorn -b 0.0.0.0:7860 --timeout 1800 --graceful-timeout 1800 --worker-class sync hue_portal.hue_portal.wsgi:application
 
 
 
59
  EOF
60
 
61
  RUN chmod +x /entrypoint.sh
62
 
63
  EXPOSE 7860
64
  CMD ["/entrypoint.sh"]
 
 
 
 
 
 
 
54
  echo "[Docker] Collecting static files..."
55
  python /app/hue_portal/manage.py collectstatic --noinput || echo "[Docker] Collectstatic failed, continuing..."
56
 
57
+ echo "[Docker] Preloading all models to avoid first-request timeout..."
58
+ python -c "
59
+ import os
60
+ import sys
61
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hue_portal.hue_portal.settings')
62
+ import django
63
+ django.setup()
64
+
65
+ print('[Docker] 🔄 Starting model preload...', flush=True)
66
+
67
+ # 1. Preload Embedding Model (BGE-M3)
68
+ try:
69
+ print('[Docker] 📦 Preloading embedding model (BGE-M3)...', flush=True)
70
+ from hue_portal.core.embeddings import get_embedding_model
71
+ embedding_model = get_embedding_model()
72
+ if embedding_model:
73
+ print('[Docker] ✅ Embedding model preloaded successfully', flush=True)
74
+ else:
75
+ print('[Docker] ⚠️ Embedding model not loaded', flush=True)
76
+ except Exception as e:
77
+ print(f'[Docker] ⚠️ Embedding model preload failed: {e}', flush=True)
78
+
79
+ # 2. Preload LLM Model (llama.cpp)
80
+ llm_provider = os.environ.get('DEFAULT_LLM_PROVIDER') or os.environ.get('LLM_PROVIDER', '')
81
+ if llm_provider.lower() == 'llama_cpp':
82
+ try:
83
+ print('[Docker] 📦 Preloading LLM model (llama.cpp)...', flush=True)
84
+ from hue_portal.chatbot.llm_integration import get_llm_generator
85
+ llm_gen = get_llm_generator()
86
+ if llm_gen and hasattr(llm_gen, 'llama_cpp') and llm_gen.llama_cpp:
87
+ print('[Docker] ✅ LLM model preloaded successfully', flush=True)
88
+ else:
89
+ print('[Docker] ⚠️ LLM model not loaded (may load on first request)', flush=True)
90
+ except Exception as e:
91
+ print(f'[Docker] ⚠️ LLM model preload failed: {e} (will load on first request)', flush=True)
92
+ else:
93
+ print(f'[Docker] ⏭️ Skipping LLM preload (provider is {llm_provider or \"not set\"}, not llama_cpp)', flush=True)
94
+
95
+ # 3. Preload Reranker Model
96
+ try:
97
+ print('[Docker] 📦 Preloading reranker model...', flush=True)
98
+ from hue_portal.core.reranker import get_reranker
99
+ reranker = get_reranker()
100
+ if reranker:
101
+ print('[Docker] ✅ Reranker model preloaded successfully', flush=True)
102
+ else:
103
+ print('[Docker] ⚠️ Reranker model not loaded (may load on first request)', flush=True)
104
+ except Exception as e:
105
+ print(f'[Docker] ⚠️ Reranker preload failed: {e} (will load on first request)', flush=True)
106
+
107
+ print('[Docker] ✅ Model preload completed', flush=True)
108
+ " || echo "[Docker] ⚠️ Model preload had errors (models will load on first request)"
109
+
110
  echo "[Docker] Starting gunicorn..."
111
+ # Reduce tokenizers parallelism warnings and risk of fork deadlocks
112
+ export TOKENIZERS_PARALLELISM=false
113
+ # Shorter timeouts to avoid long hangs; adjust if needed
114
+ cd /app/backend && export PYTHONPATH="/app/backend:${PYTHONPATH}" && exec gunicorn -b 0.0.0.0:7860 --timeout 600 --graceful-timeout 600 --worker-class sync --config python:hue_portal.hue_portal.gunicorn_app hue_portal.hue_portal.gunicorn_app:application
115
  EOF
116
 
117
  RUN chmod +x /entrypoint.sh
118
 
119
  EXPOSE 7860
120
  CMD ["/entrypoint.sh"]
121
+
122
+ EXPOSE 7860
123
+ CMD ["/entrypoint.sh"]
124
+
125
+ EXPOSE 7860
126
+ CMD ["/entrypoint.sh"]
HUONG_DAN_LAY_CLOUDFLARE_TUNNEL.md ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Hướng dẫn lấy Cloudflare Tunnel URL từ Unraid
2
+
3
+ ## Cách 1: Xem Logs của Container (Dễ nhất)
4
+
5
+ 1. **Vào Unraid Web UI**
6
+ - Mở trình duyệt, truy cập Unraid dashboard
7
+
8
+ 2. **Vào Docker tab**
9
+ - Click vào tab "Docker" ở menu trên
10
+
11
+ 3. **Tìm container "Hue-DB-Tunnel"**
12
+ - Scroll xuống tìm container có tên "Hue-DB-Tunnel"
13
+ - Hoặc tìm container có image `figro/unraid-cloudflared-tunnel` hoặc `cloudflare/cloudflared`
14
+
15
+ 4. **Click vào container → Logs**
16
+ - Click vào tên container
17
+ - Click tab "Logs" hoặc icon logs
18
+ - Tìm dòng có chứa:
19
+ - `https://` hoặc `tcp://`
20
+ - `trycloudflare.com` hoặc `cfargotunnel.com`
21
+ - Hoặc dòng có format: `Connection established: tcp://...`
22
+
23
+ 5. **Copy URL**
24
+ - URL thường có dạng:
25
+ - `xyz-abc-123.trycloudflare.com:5432`
26
+ - `xyz-abc-123.cfargotunnel.com:5432`
27
+ - Hoặc chỉ có hostname: `xyz-abc-123.trycloudflare.com`
28
+
29
+ ## Cách 2: Xem Config của Container
30
+
31
+ 1. **Vào container "Hue-DB-Tunnel"**
32
+ - Click vào container trong Docker tab
33
+
34
+ 2. **Xem "Edit" hoặc "Show more settings"**
35
+ - Tìm phần "Extra Parameters" hoặc "Post Arguments"
36
+ - Hoặc xem "Environment Variables"
37
+ - Tìm các biến như:
38
+ - `TUNNEL_URL`
39
+ - `TUNNEL_HOST`
40
+ - `TUNNEL_PORT`
41
+
42
+ ## Cách 3: SSH vào Unraid và xem logs
43
+
44
+ 1. **SSH vào Unraid**
45
+ ```bash
46
+ ssh root@192.168.1.212
47
+ ```
48
+
49
+ 2. **Xem logs của container**
50
+ ```bash
51
+ docker logs Hue-DB-Tunnel
52
+ # hoặc
53
+ docker logs 944286801b0d
54
+ ```
55
+
56
+ 3. **Tìm URL trong logs**
57
+ ```bash
58
+ docker logs Hue-DB-Tunnel | grep -E "trycloudflare|cfargotunnel|Connection established|tcp://"
59
+ ```
60
+
61
+ ## Cách 4: Kiểm tra qua Cloudflare Dashboard
62
+
63
+ 1. **Đăng nhập Cloudflare Dashboard**
64
+ - Vào https://dash.cloudflare.com
65
+ - Chọn account của bạn
66
+
67
+ 2. **Vào Zero Trust → Tunnels**
68
+ - Menu bên trái: "Zero Trust" → "Networks" → "Tunnels"
69
+ - Tìm tunnel có tên liên quan đến "Hue" hoặc "DB"
70
+
71
+ 3. **Xem Public Hostname**
72
+ - Click vào tunnel
73
+ - Xem phần "Public Hostname" hoặc "Private Network"
74
+ - Copy URL
75
+
76
+ ## Thông tin cần lấy
77
+
78
+ Sau khi có URL, bạn cần:
79
+
80
+ 1. **Hostname**: Ví dụ `xyz-abc-123.trycloudflare.com`
81
+ 2. **Port**: Thường là `5432` (PostgreSQL port)
82
+ 3. **Full URL**: `xyz-abc-123.trycloudflare.com:5432`
83
+
84
+ ## Test kết nối
85
+
86
+ Sau khi có URL, chạy script test:
87
+
88
+ ```bash
89
+ cd /Users/davidtran/Downloads/TryHarDemNayProject
90
+ python3 hue-portal-backend/test_cloudflare_tunnel.py
91
+ ```
92
+
93
+ Nhập:
94
+ - Host: `xyz-abc-123.trycloudflare.com`
95
+ - Port: `5432`
96
+ - User: `hue_remote`
97
+ - Password: `huepass123`
98
+ - Database: `hue_portal`
99
+
100
+ ## Lưu ý
101
+
102
+ - Cloudflare Tunnel URL có thể thay đổi mỗi lần restart container
103
+ - Nếu dùng Cloudflare Zero Trust (có account), URL sẽ ổn định hơn
104
+ - Nếu dùng `cloudflared` free (trycloudflare.com), URL sẽ thay đổi mỗi lần chạy
105
+
106
+
107
+
108
+
109
+
110
+
README_khoidongDB.md ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Script khởi động Database (khoidongDB.sh)
2
+
3
+ Script tự động khởi động PostgreSQL và ngrok tunnel với port và URL cố định.
4
+
5
+ ## Cách sử dụng
6
+
7
+ ```bash
8
+ cd hue-portal-backend
9
+ ./khoidongDB.sh
10
+ ```
11
+
12
+ ## Chức năng
13
+
14
+ 1. **Kiểm tra PostgreSQL**: Kiểm tra PostgreSQL có đang chạy trên port 5543 không
15
+ 2. **Khởi động ngrok**:
16
+ - Kiểm tra ngrok đã chạy chưa
17
+ - Nếu chưa, khởi động ngrok tunnel forward đến localhost:5543
18
+ 3. **Lưu thông tin tunnel**: Lưu ngrok URL vào `ops/.env.tunnel`
19
+ 4. **Cập nhật Hugging Face Space**: Tự động cập nhật DATABASE_URL lên Space
20
+
21
+ ## Cấu hình
22
+
23
+ Script sử dụng các biến môi trường sau (có thể set trong `.env`):
24
+
25
+ - `POSTGRES_PORT`: Port PostgreSQL (mặc định: 5543)
26
+ - `POSTGRES_USER`: PostgreSQL user (mặc định: hue_remote)
27
+ - `POSTGRES_PASSWORD`: PostgreSQL password (mặc định: huepass123)
28
+ - `POSTGRES_DB`: Database name (mặc định: hue_portal)
29
+ - `NGROK_REGION`: Ngrok region (mặc định: ap)
30
+ - `HF_SPACE_ID`: Hugging Face Space ID (mặc định: davidtran999/hue-portal-backend)
31
+
32
+ ## Output
33
+
34
+ Script sẽ:
35
+ - Hiển thị trạng thái PostgreSQL
36
+ - Hiển thị ngrok tunnel URL
37
+ - Lưu thông tin vào `ops/.env.tunnel`
38
+ - Cập nhật DATABASE_URL lên Hugging Face Space
39
+
40
+ ## Ví dụ output
41
+
42
+ ```
43
+ [DB-START] ============================================================
44
+ [DB-START] Khởi động PostgreSQL và ngrok tunnel
45
+ [DB-START] ============================================================
46
+ [DB-START] Kiểm tra PostgreSQL trên port 5543...
47
+ [DB-START] ✅ PostgreSQL đang chạy trên port 5543
48
+ [DB-START] Khởi động ngrok tunnel...
49
+ [DB-START] ✅ Ngrok đã chạy sẵn: tcp://0.tcp.ap.ngrok.io:15028
50
+ [DB-START] Lưu thông tin tunnel...
51
+ [DB-START] ✅ Đã lưu tunnel info vào ops/.env.tunnel
52
+ [DB-START] Cập nhật DATABASE_URL lên Hugging Face Space...
53
+ [DB-START] ============================================================
54
+ [DB-START] ✅ Hoàn tất!
55
+ [DB-START] PostgreSQL: localhost:5543
56
+ [DB-START] Ngrok tunnel: tcp://0.tcp.ap.ngrok.io:15028
57
+ [DB-START] DATABASE_URL: postgres://hue_remote:***@0.tcp.ap.ngrok.io:15028/hue_portal
58
+ [DB-START] ============================================================
59
+ ```
60
+
61
+ ## Lưu ý
62
+
63
+ - PostgreSQL phải đang chạy trước khi chạy script
64
+ - Ngrok phải được cài đặt và cấu hình (API key)
65
+ - Script sẽ tự động kill ngrok process cũ nếu có
66
+ - Thông tin tunnel được lưu vào `ops/.env.tunnel` để sử dụng sau
67
+
68
+ ## Troubleshooting
69
+
70
+ ### PostgreSQL không chạy
71
+ ```bash
72
+ # Kiểm tra PostgreSQL
73
+ psql -h localhost -p 5543 -U hue_remote -d hue_portal -c "SELECT 1;"
74
+ ```
75
+
76
+ ### Ngrok không khởi động được
77
+ ```bash
78
+ # Kiểm tra ngrok API
79
+ curl http://127.0.0.1:4040/api/tunnels
80
+
81
+ # Xem ngrok logs
82
+ cat ops/ngrok.log
83
+ ```
84
+
85
+ ### Không kết nối được qua ngrok
86
+ - Kiểm tra PostgreSQL có accept connection từ ngrok không
87
+ - Kiểm tra firewall/network settings
88
+ - Test kết nối từ local machine trước
89
+
README_ngrok_fix.md ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Fix Ngrok Tunnel với PostgreSQL
2
+
3
+ ## Vấn đề
4
+
5
+ Ngrok TCP tunnel không kết nối được PostgreSQL trong Docker container mặc dù:
6
+ - ✅ PostgreSQL đang listen trên `*` (tất cả interfaces)
7
+ - ✅ pg_hba.conf đã có rule cho `0.0.0.0/0`
8
+ - ✅ Docker port mapping đúng (`0.0.0.0:5543->5432`)
9
+ - ✅ Ngrok tunnel đang chạy và forward đến `localhost:5543`
10
+
11
+ ## Nguyên nhân có thể
12
+
13
+ 1. **Ngrok TCP tunnel không forward đúng PostgreSQL protocol handshake**
14
+ 2. **Docker network isolation** - PostgreSQL trong container không accept connection từ ngrok IP range
15
+ 3. **PostgreSQL trong Docker chỉ bind đến localhost bên trong container**
16
+
17
+ ## Giải pháp đã thử
18
+
19
+ ### 1. Fix PostgreSQL config
20
+ - ✅ Set `listen_addresses = '*'`
21
+ - ✅ Thêm rule vào `pg_hba.conf`: `host all all 0.0.0.0/0 md5`
22
+ - ✅ Restart PostgreSQL container
23
+
24
+ ### 2. Fix Docker config
25
+ - ✅ Set port mapping: `0.0.0.0:5543:5432`
26
+ - ✅ Thêm command: `postgres -c listen_addresses='*'`
27
+
28
+ ### 3. Scripts đã tạo
29
+ - ✅ `khoidongDB.sh` - Khởi động ngrok và update DATABASE_URL
30
+ - ✅ `fix_ngrok_postgres.sh` - Fix và test ngrok tunnel
31
+
32
+ ## Giải pháp thay thế
33
+
34
+ ### Option 1: SSH Tunnel (Khuyến nghị)
35
+ ```bash
36
+ # Trên server có PostgreSQL
37
+ ssh -N -L 5543:localhost:5543 user@your-server
38
+
39
+ # Hoặc reverse SSH tunnel
40
+ ssh -R 5543:localhost:5543 user@your-server
41
+ ```
42
+
43
+ ### Option 2: Cloudflare Tunnel
44
+ ```bash
45
+ # Cài đặt cloudflared
46
+ brew install cloudflared # macOS
47
+ # hoặc
48
+ sudo apt install cloudflared # Linux
49
+
50
+ # Tạo tunnel
51
+ cloudflared tunnel --url tcp://localhost:5543
52
+ ```
53
+
54
+ ### Option 3: Tailscale
55
+ ```bash
56
+ # Cài đặt Tailscale
57
+ # Tạo mesh network
58
+ # PostgreSQL sẽ accessible qua Tailscale IP
59
+ ```
60
+
61
+ ### Option 4: Docker network_mode: host
62
+ ```yaml
63
+ # docker-compose.yml
64
+ db:
65
+ network_mode: host
66
+ # ... config khác
67
+ ```
68
+
69
+ **Lưu ý:** `network_mode: host` chỉ hoạt động trên Linux, không hoạt động trên macOS/Windows.
70
+
71
+ ## Workaround hiện tại
72
+
73
+ Space đang dùng **SQLite fallback**:
74
+ - ✅ App chạy được
75
+ - ✅ Migration pass
76
+ - ✅ Chatbot hoạt động (không có data)
77
+ - ⚠️ Không có data để trả lời câu hỏi phức tạp
78
+
79
+ ## Next Steps
80
+
81
+ 1. **Test SSH tunnel** thay vì ngrok
82
+ 2. **Hoặc dùng Cloudflare Tunnel** (miễn phí, ổn định hơn)
83
+ 3. **Hoặc chấp nhận SQLite fallback** cho Space (chỉ để test)
84
+
85
+ ## Scripts
86
+
87
+ - `khoidongDB.sh` - Khởi động ngrok và update DATABASE_URL
88
+ - `fix_ngrok_postgres.sh` - Fix và test ngrok tunnel (chưa fix được)
89
+
90
+ ## Cách sử dụng
91
+
92
+ ```bash
93
+ # Khởi động ngrok và update DATABASE_URL
94
+ ./hue-portal-backend/khoidongDB.sh
95
+
96
+ # Fix và test ngrok tunnel
97
+ ./hue-portal-backend/fix_ngrok_postgres.sh
98
+ ```
99
+
SETUP_CLOUDFLARE_TUNNEL_POSTGRES.md ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Hướng dẫn Setup Cloudflare Tunnel cho PostgreSQL
2
+
3
+ ## Bước 1: Kiểm tra Cloudflare Tunnel hiện tại
4
+
5
+ Trên Unraid terminal:
6
+
7
+ ```bash
8
+ docker ps | grep -i cloudflare
9
+ docker ps | grep -i tunnel
10
+ ```
11
+
12
+ ## Bước 2: Setup Cloudflare Tunnel cho PostgreSQL
13
+
14
+ ### Option A: Thêm route vào tunnel hiện có (nếu có Cloudflare Zero Trust)
15
+
16
+ 1. **Vào Cloudflare Dashboard**
17
+ - https://dash.cloudflare.com
18
+ - Zero Trust → Networks → Tunnels
19
+
20
+ 2. **Chọn tunnel hiện có**
21
+ - Click vào tunnel name
22
+
23
+ 3. **Thêm Public Hostname**
24
+ - Click "Public Hostname" tab
25
+ - Click "Add a public hostname"
26
+ - Configure:
27
+ - **Subdomain**: `postgres` (hoặc tên bạn muốn)
28
+ - **Domain**: Chọn domain của bạn (ví dụ: `aliss.io.vn`)
29
+ - **Service Type**: `TCP`
30
+ - **URL**: `192.168.1.212:5432`
31
+ - Save
32
+
33
+ 4. **Lấy URL**
34
+ - URL sẽ là: `postgres.aliss.io.vn:5432` (hoặc domain bạn chọn)
35
+
36
+ ### Option B: Tạo tunnel mới với cloudflared (Free, URL thay đổi)
37
+
38
+ Trên Unraid terminal:
39
+
40
+ ```bash
41
+ # 1. Tạo tunnel mới
42
+ docker run -d \
43
+ --name cloudflare-postgres \
44
+ --network host \
45
+ cloudflare/cloudflared:latest \
46
+ tunnel --url tcp://192.168.1.212:5432
47
+
48
+ # 2. Đợi vài giây
49
+ sleep 5
50
+
51
+ # 3. Lấy URL từ logs
52
+ docker logs cloudflare-postgres | grep -oE "trycloudflare.com:[0-9]+" | head -1
53
+ ```
54
+
55
+ ## Bước 3: Test kết nối
56
+
57
+ Từ máy local:
58
+
59
+ ```bash
60
+ cd /Users/davidtran/Downloads/TryHarDemNayProject
61
+ ./hue-portal-backend/test_ngrok_simple.sh [CLOUDFLARE_HOST] [PORT]
62
+ ```
63
+
64
+ Hoặc:
65
+
66
+ ```bash
67
+ PGPASSWORD=huepass123 psql -h [CLOUDFLARE_HOST] -p [PORT] -U hue_remote -d hue_portal -c "SELECT 1;"
68
+ ```
69
+
70
+ ## Bước 4: Update DATABASE_URL
71
+
72
+ ```
73
+ postgres://hue_remote:huepass123@[CLOUDFLARE_HOST]:[PORT]/hue_portal
74
+ ```
75
+
76
+ Update trên Hugging Face Space:
77
+ - Settings → Variables → DATABASE_URL
78
+
79
+ ## Lưu ý
80
+
81
+ - **Cloudflare Zero Trust (paid)**: URL cố định, ổn định
82
+ - **cloudflared free (trycloudflare.com)**: URL thay đổi mỗi lần restart
83
+ - **Ngrok free**: Không tương thích tốt với PostgreSQL TCP
84
+
85
+
86
+
87
+
88
+
__pycache__/start_ngrok_and_set_db.cpython-310.pyc ADDED
Binary file (7.71 kB). View file
 
backend/hue_portal/chatbot/chatbot.py CHANGED
@@ -136,7 +136,7 @@ class Chatbot(CoreChatbot):
136
  # tránh trả lại các câu trả lời cũ không có options.
137
  cached_response = None
138
  if intent != "search_legal":
139
- cached_response = EXACT_MATCH_CACHE.get(query, intent)
140
  if cached_response:
141
  cached_response["_cache"] = "exact_match"
142
  cached_response["_source"] = cached_response.get("_source", "cache")
 
136
  # tránh trả lại các câu trả lời cũ không có options.
137
  cached_response = None
138
  if intent != "search_legal":
139
+ cached_response = EXACT_MATCH_CACHE.get(query, intent)
140
  if cached_response:
141
  cached_response["_cache"] = "exact_match"
142
  cached_response["_source"] = cached_response.get("_source", "cache")
backend/hue_portal/chatbot/tests/__pycache__/test_smoke.cpython-310.pyc ADDED
Binary file (1.71 kB). View file
 
backend/hue_portal/core/management/commands/__pycache__/retry_ingestion_job.cpython-310.pyc ADDED
Binary file (1.41 kB). View file
 
check_tunnel_unraid.sh ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ # Script để kiểm tra và fix Cloudflare Tunnel trên Unraid
4
+
5
+ echo "============================================================"
6
+ echo "🔍 Kiểm tra Cloudflare Tunnel cho PostgreSQL"
7
+ echo "============================================================"
8
+ echo ""
9
+
10
+ TUNNEL_NAME="mystifying_bassi"
11
+ POSTGRES_CONTAINER="postgres-hue"
12
+ POSTGRES_HOST="192.168.1.212"
13
+ POSTGRES_PORT="5432"
14
+
15
+ # 1. Check tunnel container
16
+ echo "1️⃣ Kiểm tra tunnel container..."
17
+ if docker ps | grep -q "$TUNNEL_NAME"; then
18
+ echo "✅ Tunnel container đang chạy"
19
+ docker ps | grep "$TUNNEL_NAME"
20
+ else
21
+ echo "❌ Tunnel container KHÔNG chạy!"
22
+ exit 1
23
+ fi
24
+
25
+ # 2. Check PostgreSQL container
26
+ echo ""
27
+ echo "2️⃣ Kiểm tra PostgreSQL container..."
28
+ if docker ps | grep -q "$POSTGRES_CONTAINER"; then
29
+ echo "✅ PostgreSQL container đang chạy"
30
+ docker ps | grep "$POSTGRES_CONTAINER"
31
+ else
32
+ echo "❌ PostgreSQL container KHÔNG chạy!"
33
+ exit 1
34
+ fi
35
+
36
+ # 3. Test PostgreSQL locally
37
+ echo ""
38
+ echo "3️⃣ Test PostgreSQL từ trong Unraid..."
39
+ if docker exec "$POSTGRES_CONTAINER" psql -U hue_remote -d hue_portal -c "SELECT 1;" > /dev/null 2>&1; then
40
+ echo "✅ PostgreSQL hoạt động OK"
41
+ else
42
+ echo "❌ PostgreSQL KHÔNG hoạt động!"
43
+ exit 1
44
+ fi
45
+
46
+ # 4. Check tunnel logs for postgres config
47
+ echo ""
48
+ echo "4️⃣ Kiểm tra tunnel config..."
49
+ if docker logs "$TUNNEL_NAME" --tail 50 | grep -q "postgres.aliss.io.vn.*tcp://$POSTGRES_HOST:$POSTGRES_PORT"; then
50
+ echo "✅ Tunnel config có postgres.aliss.io.vn → tcp://$POSTGRES_HOST:$POSTGRES_PORT"
51
+ else
52
+ echo "⚠️ KHÔNG tìm thấy config postgres trong logs"
53
+ echo " Xem logs:"
54
+ docker logs "$TUNNEL_NAME" --tail 10 | grep -i "postgres\|tcp\|5432"
55
+ fi
56
+
57
+ # 5. Check tunnel connection status
58
+ echo ""
59
+ echo "5️⃣ Kiểm tra tunnel connection status..."
60
+ if docker logs "$TUNNEL_NAME" --tail 20 | grep -q "Registered tunnel connection"; then
61
+ echo "✅ Tunnel đã connected"
62
+ docker logs "$TUNNEL_NAME" --tail 5 | grep "Registered tunnel connection"
63
+ else
64
+ echo "⚠️ Không thấy tunnel connection"
65
+ fi
66
+
67
+ # 6. Check for any connection attempts
68
+ echo ""
69
+ echo "6️⃣ Kiểm tra connection attempts (nếu có)..."
70
+ RECENT_LOGS=$(docker logs "$TUNNEL_NAME" --tail 100 | grep -i "request\|connection\|postgres\|5432" | tail -5)
71
+ if [ -n "$RECENT_LOGS" ]; then
72
+ echo "📋 Recent logs:"
73
+ echo "$RECENT_LOGS"
74
+ else
75
+ echo "⚠️ Không có connection attempts gần đây"
76
+ fi
77
+
78
+ # 7. Suggestions
79
+ echo ""
80
+ echo "============================================================"
81
+ echo "💡 Gợi ý:"
82
+ echo "============================================================"
83
+ echo ""
84
+ echo "Nếu kết nối vẫn không hoạt động:"
85
+ echo ""
86
+ echo "1. Restart tunnel:"
87
+ echo " docker restart $TUNNEL_NAME"
88
+ echo ""
89
+ echo "2. Đợi 30 giây và check logs:"
90
+ echo " sleep 30"
91
+ echo " docker logs $TUNNEL_NAME --tail 20"
92
+ echo ""
93
+ echo "3. Kiểm tra Cloudflare Dashboard:"
94
+ echo " https://dash.cloudflare.com → Zero Trust → Networks → Tunnels"
95
+ echo " - Xem tunnel status phải là 'Healthy'"
96
+ echo " - Xem config có postgres.aliss.io.vn → tcp://$POSTGRES_HOST:$POSTGRES_PORT"
97
+ echo ""
98
+ echo "4. Test từ máy local:"
99
+ echo " PGPASSWORD=huepass123 psql -h postgres.aliss.io.vn -p 5432 -U hue_remote -d hue_portal -c 'SELECT 1;'"
100
+ echo ""
101
+ echo "============================================================"
102
+
103
+
104
+
105
+
106
+
entrypoint.sh CHANGED
@@ -31,26 +31,61 @@ log "Ensuring cache table exists..."
31
  python hue_portal/manage.py createcachetable
32
  log "Cache table ready."
33
 
34
- log "Starting Gunicorn on port ${PORT:-7860}..."
35
- # Preload model if LLM provider is llama_cpp (to avoid timeout on first request)
36
- if [[ "${DEFAULT_LLM_PROVIDER:-}" == "llama_cpp" ]] || [[ "${LLM_PROVIDER:-}" == "llama_cpp" ]]; then
37
- log "Preloading llama.cpp model to avoid first-request timeout..."
38
- python -c "
39
  import os
 
40
  os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hue_portal.hue_portal.settings')
41
  import django
42
  django.setup()
43
- from hue_portal.chatbot.llm_integration import LLMGenerator
 
 
 
44
  try:
45
- gen = LLMGenerator()
46
- if gen.llama_cpp:
47
- print('[ENTRYPOINT] Model preloaded successfully')
 
 
48
  else:
49
- print('[ENTRYPOINT] ⚠️ Model not loaded (may load on first request)')
50
  except Exception as e:
51
- print(f'[ENTRYPOINT] ⚠️ Model preload failed: {e} (will load on first request)')
52
- " || log "Model preload skipped (will load on first request)"
53
- fi
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
  exec gunicorn hue_portal.hue_portal.wsgi:application \
56
  --bind 0.0.0.0:${PORT:-7860} \
 
31
  python hue_portal/manage.py createcachetable
32
  log "Cache table ready."
33
 
34
+ log "Preloading all models to avoid first-request timeout..."
35
+
36
+ python -c "
 
 
37
  import os
38
+ import sys
39
  os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hue_portal.hue_portal.settings')
40
  import django
41
  django.setup()
42
+
43
+ print('[ENTRYPOINT] 🔄 Starting model preload...', flush=True)
44
+
45
+ # 1. Preload Embedding Model (BGE-M3)
46
  try:
47
+ print('[ENTRYPOINT] 📦 Preloading embedding model (BGE-M3)...', flush=True)
48
+ from hue_portal.core.embeddings import get_embedding_model
49
+ embedding_model = get_embedding_model()
50
+ if embedding_model:
51
+ print('[ENTRYPOINT] ✅ Embedding model preloaded successfully', flush=True)
52
  else:
53
+ print('[ENTRYPOINT] ⚠️ Embedding model not loaded', flush=True)
54
  except Exception as e:
55
+ print(f'[ENTRYPOINT] ⚠️ Embedding model preload failed: {e}', flush=True)
56
+
57
+ # 2. Preload LLM Model (llama.cpp)
58
+ llm_provider = os.environ.get('DEFAULT_LLM_PROVIDER') or os.environ.get('LLM_PROVIDER', '')
59
+ if llm_provider.lower() == 'llama_cpp':
60
+ try:
61
+ print('[ENTRYPOINT] 📦 Preloading LLM model (llama.cpp)...', flush=True)
62
+ from hue_portal.chatbot.llm_integration import get_llm_generator
63
+ llm_gen = get_llm_generator()
64
+ if llm_gen and hasattr(llm_gen, 'llama_cpp') and llm_gen.llama_cpp:
65
+ print('[ENTRYPOINT] ✅ LLM model preloaded successfully', flush=True)
66
+ else:
67
+ print('[ENTRYPOINT] ⚠️ LLM model not loaded (may load on first request)', flush=True)
68
+ except Exception as e:
69
+ print(f'[ENTRYPOINT] ⚠️ LLM model preload failed: {e} (will load on first request)', flush=True)
70
+ else:
71
+ print(f'[ENTRYPOINT] ⏭️ Skipping LLM preload (provider is {llm_provider or \"not set\"}, not llama_cpp)', flush=True)
72
+
73
+ # 3. Preload Reranker Model (lazy, but trigger import)
74
+ try:
75
+ print('[ENTRYPOINT] 📦 Preloading reranker model...', flush=True)
76
+ from hue_portal.core.reranker import get_reranker
77
+ reranker = get_reranker()
78
+ if reranker:
79
+ print('[ENTRYPOINT] ✅ Reranker model preloaded successfully', flush=True)
80
+ else:
81
+ print('[ENTRYPOINT] ⚠️ Reranker model not loaded (may load on first request)', flush=True)
82
+ except Exception as e:
83
+ print(f'[ENTRYPOINT] ⚠️ Reranker preload failed: {e} (will load on first request)', flush=True)
84
+
85
+ print('[ENTRYPOINT] ✅ Model preload completed', flush=True) # v2.0-preload-all
86
+ " || log "⚠️ Model preload had errors (models will load on first request)"
87
+
88
+ log "Starting Gunicorn on port ${PORT:-7860}..."
89
 
90
  exec gunicorn hue_portal.hue_portal.wsgi:application \
91
  --bind 0.0.0.0:${PORT:-7860} \
fix_ngrok_postgres.sh ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Script để fix và test ngrok tunnel với PostgreSQL
3
+ # Sử dụng: ./fix_ngrok_postgres.sh
4
+
5
+ set -e
6
+
7
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
9
+ OPS_DIR="$PROJECT_ROOT/ops"
10
+ ENV_TUNNEL="$OPS_DIR/.env.tunnel"
11
+
12
+ # Colors
13
+ GREEN='\033[0;32m'
14
+ YELLOW='\033[1;33m'
15
+ RED='\033[0;31m'
16
+ NC='\033[0m'
17
+
18
+ log() {
19
+ echo -e "${GREEN}[FIX-NGROK]${NC} $1"
20
+ }
21
+
22
+ warn() {
23
+ echo -e "${YELLOW}[FIX-NGROK]${NC} $1"
24
+ }
25
+
26
+ error() {
27
+ echo -e "${RED}[FIX-NGROK]${NC} $1"
28
+ }
29
+
30
+ # Default values
31
+ POSTGRES_PORT=${POSTGRES_PORT:-5543}
32
+ POSTGRES_USER=${POSTGRES_USER:-hue_remote}
33
+ POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-huepass123}
34
+ POSTGRES_DB=${POSTGRES_DB:-hue_portal}
35
+ NGROK_REGION=${NGROK_REGION:-ap}
36
+
37
+ log "============================================================"
38
+ log "Fix và test ngrok tunnel với PostgreSQL"
39
+ log "============================================================"
40
+
41
+ # Step 1: Check PostgreSQL
42
+ log "Bước 1: Kiểm tra PostgreSQL..."
43
+ export PGPASSWORD="$POSTGRES_PASSWORD"
44
+ if psql -h localhost -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT 1;" &>/dev/null; then
45
+ log "✅ PostgreSQL đang chạy trên localhost:$POSTGRES_PORT"
46
+ else
47
+ error "❌ PostgreSQL không chạy trên localhost:$POSTGRES_PORT"
48
+ exit 1
49
+ fi
50
+
51
+ # Step 2: Check PostgreSQL listen addresses
52
+ log "Bước 2: Kiểm tra PostgreSQL config..."
53
+ LISTEN_ADDR=$(psql -h localhost -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -t -c "SHOW listen_addresses;" 2>/dev/null | xargs)
54
+ if [ "$LISTEN_ADDR" = "*" ]; then
55
+ log "✅ PostgreSQL đang listen trên tất cả interfaces (*)"
56
+ else
57
+ warn "⚠️ PostgreSQL listen trên: $LISTEN_ADDR (cần là *)"
58
+ fi
59
+
60
+ # Step 3: Check Docker container
61
+ log "Bước 3: Kiểm tra Docker container..."
62
+ if docker ps | grep -q "tryhardemnayproject-db-1\|postgres.*5543"; then
63
+ CONTAINER_NAME=$(docker ps | grep -E "tryhardemnayproject-db-1|postgres.*5543" | awk '{print $NF}' | head -1)
64
+ log "✅ Tìm thấy PostgreSQL container: $CONTAINER_NAME"
65
+
66
+ # Check pg_hba.conf
67
+ log "Bước 4: Kiểm tra pg_hba.conf..."
68
+ if docker exec "$CONTAINER_NAME" grep -q "0.0.0.0/0" /var/lib/postgresql/data/pg_hba.conf 2>/dev/null; then
69
+ log "✅ pg_hba.conf đã có rule cho 0.0.0.0/0"
70
+ else
71
+ warn "⚠️ pg_hba.conf chưa có rule cho 0.0.0.0/0, đang thêm..."
72
+ docker exec "$CONTAINER_NAME" bash -c "echo 'host all all 0.0.0.0/0 md5' >> /var/lib/postgresql/data/pg_hba.conf" 2>/dev/null || true
73
+ log "✅ Đã thêm rule vào pg_hba.conf (cần restart container để apply)"
74
+ fi
75
+ else
76
+ warn "⚠️ Không tìm thấy PostgreSQL container"
77
+ fi
78
+
79
+ # Step 5: Restart ngrok
80
+ log "Bước 5: Khởi động lại ngrok tunnel..."
81
+ pkill -f "ngrok tcp" 2>/dev/null || true
82
+ sleep 2
83
+
84
+ # Start ngrok
85
+ nohup ngrok tcp "$POSTGRES_PORT" --region "$NGROK_REGION" --log=stdout > "$OPS_DIR/ngrok.log" 2>&1 &
86
+ NGROK_PID=$!
87
+
88
+ # Wait for ngrok
89
+ for i in {1..10}; do
90
+ sleep 1
91
+ if curl -s http://127.0.0.1:4040/api/tunnels &>/dev/null; then
92
+ NGROK_URL=$(curl -s http://127.0.0.1:4040/api/tunnels | python3 -c "
93
+ import sys, json
94
+ try:
95
+ data = json.load(sys.stdin)
96
+ for tunnel in data.get('tunnels', []):
97
+ if tunnel.get('proto') == 'tcp':
98
+ print(tunnel.get('public_url', '').replace('tcp://', ''))
99
+ sys.exit(0)
100
+ except:
101
+ pass
102
+ " 2>/dev/null)
103
+ if [ -n "$NGROK_URL" ]; then
104
+ NGROK_HOST=$(echo "$NGROK_URL" | cut -d':' -f1)
105
+ NGROK_PORT=$(echo "$NGROK_URL" | cut -d':' -f2)
106
+ log "✅ Ngrok đã sẵn sàng: tcp://$NGROK_HOST:$NGROK_PORT"
107
+ break
108
+ fi
109
+ fi
110
+ done
111
+
112
+ if [ -z "$NGROK_HOST" ] || [ -z "$NGROK_PORT" ]; then
113
+ error "❌ Không thể khởi động ngrok"
114
+ exit 1
115
+ fi
116
+
117
+ # Step 6: Test connection
118
+ log "Bước 6: Test kết nối PostgreSQL qua ngrok..."
119
+ sleep 3
120
+
121
+ # Test với psql
122
+ if timeout 10 psql -h "$NGROK_HOST" -p "$NGROK_PORT" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT 1;" &>/dev/null; then
123
+ log "✅✅✅ KẾT NỐI THÀNH CÔNG QUA NGROK!"
124
+
125
+ # Get document count
126
+ DOC_COUNT=$(psql -h "$NGROK_HOST" -p "$NGROK_PORT" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -t -c "SELECT COUNT(*) FROM core_legaldocument;" 2>/dev/null | xargs)
127
+ log " Số lượng documents: $DOC_COUNT"
128
+
129
+ # Save tunnel info
130
+ log "Bước 7: Lưu thông tin tunnel..."
131
+ mkdir -p "$OPS_DIR"
132
+ cat > "$ENV_TUNNEL" << EOF
133
+ # Ngrok tunnel info - Generated by fix_ngrok_postgres.sh
134
+ # Last updated: $(date -u +"%Y-%m-%dT%H:%M:%S")
135
+
136
+ PG_TUNNEL_HOST=$NGROK_HOST
137
+ PG_TUNNEL_PORT=$NGROK_PORT
138
+ PG_TUNNEL_LOCAL_PORT=$POSTGRES_PORT
139
+ PG_TUNNEL_USER=$POSTGRES_USER
140
+ PG_TUNNEL_PASSWORD=$POSTGRES_PASSWORD
141
+ PG_TUNNEL_DB=$POSTGRES_DB
142
+ DATABASE_URL=postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@$NGROK_HOST:$NGROK_PORT/$POSTGRES_DB
143
+ HF_SPACE_ID=${HF_SPACE_ID:-davidtran999/hue-portal-backend}
144
+ POSTGRES_HOST=${POSTGRES_HOST:-localhost}
145
+ POSTGRES_PORT=$POSTGRES_PORT
146
+ POSTGRES_USER=$POSTGRES_USER
147
+ POSTGRES_PASSWORD=$POSTGRES_PASSWORD
148
+ POSTGRES_DB=$POSTGRES_DB
149
+ PG_TUNNEL_LAST_UPDATED=$(date -u +"%Y-%m-%dT%H:%M:%S")
150
+ EOF
151
+ log "✅ Đã lưu tunnel info vào $ENV_TUNNEL"
152
+
153
+ # Update Hugging Face Space
154
+ log "Bước 8: Cập nhật DATABASE_URL lên Hugging Face Space..."
155
+ if [ -f "$PROJECT_ROOT/backend/venv/bin/python" ]; then
156
+ "$PROJECT_ROOT/backend/venv/bin/python" "$SCRIPT_DIR/start_ngrok_and_set_db.py" 2>&1 | grep -E "(✅|❌|📌)" || true
157
+ fi
158
+
159
+ log "============================================================"
160
+ log "✅✅✅ HOÀN TẤT!"
161
+ log " PostgreSQL: localhost:$POSTGRES_PORT"
162
+ log " Ngrok tunnel: tcp://$NGROK_HOST:$NGROK_PORT"
163
+ log " DATABASE_URL: postgres://$POSTGRES_USER:***@$NGROK_HOST:$NGROK_PORT/$POSTGRES_DB"
164
+ log "============================================================"
165
+ else
166
+ error "❌ Vẫn không kết nối được qua ngrok"
167
+ error " Có thể cần:"
168
+ error " 1. Restart PostgreSQL container để apply pg_hba.conf"
169
+ error " 2. Hoặc dùng SSH tunnel thay vì ngrok"
170
+ error " 3. Hoặc expose PostgreSQL với network_mode: host"
171
+ exit 1
172
+ fi
173
+
khoidongDB.sh ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Script khởi động PostgreSQL và ngrok tunnel với port và URL cố định
3
+ # Sử dụng: ./khoidongDB.sh
4
+
5
+ set -e
6
+
7
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
9
+ OPS_DIR="$PROJECT_ROOT/ops"
10
+ ENV_TUNNEL="$OPS_DIR/.env.tunnel"
11
+
12
+ # Colors
13
+ GREEN='\033[0;32m'
14
+ YELLOW='\033[1;33m'
15
+ RED='\033[0;31m'
16
+ NC='\033[0m' # No Color
17
+
18
+ log() {
19
+ echo -e "${GREEN}[DB-START]${NC} $1"
20
+ }
21
+
22
+ warn() {
23
+ echo -e "${YELLOW}[DB-START]${NC} $1"
24
+ }
25
+
26
+ error() {
27
+ echo -e "${RED}[DB-START]${NC} $1"
28
+ }
29
+
30
+ # Load config
31
+ if [ -f "$PROJECT_ROOT/.env" ]; then
32
+ source "$PROJECT_ROOT/.env"
33
+ fi
34
+
35
+ # Default values
36
+ POSTGRES_PORT=${POSTGRES_PORT:-5543}
37
+ NGROK_REGION=${NGROK_REGION:-ap}
38
+ NGROK_API_URL="http://127.0.0.1:4040"
39
+
40
+ # Create ops directory if not exists
41
+ mkdir -p "$OPS_DIR"
42
+
43
+ # Function to check if PostgreSQL is running
44
+ check_postgres() {
45
+ log "Kiểm tra PostgreSQL trên port $POSTGRES_PORT..."
46
+
47
+ if command -v psql &> /dev/null; then
48
+ if PGPASSWORD="${POSTGRES_PASSWORD:-huepass123}" psql -h localhost -p "$POSTGRES_PORT" -U "${POSTGRES_USER:-hue_remote}" -d "${POSTGRES_DB:-hue_portal}" -c "SELECT 1;" &> /dev/null; then
49
+ log "✅ PostgreSQL đang chạy trên port $POSTGRES_PORT"
50
+ return 0
51
+ fi
52
+ fi
53
+
54
+ # Try Python connection
55
+ if [ -f "$PROJECT_ROOT/backend/venv/bin/python" ]; then
56
+ if "$PROJECT_ROOT/backend/venv/bin/python" -c "
57
+ import psycopg2
58
+ try:
59
+ conn = psycopg2.connect(
60
+ host='localhost',
61
+ port=$POSTGRES_PORT,
62
+ database='${POSTGRES_DB:-hue_portal}',
63
+ user='${POSTGRES_USER:-hue_remote}',
64
+ password='${POSTGRES_PASSWORD:-huepass123}',
65
+ connect_timeout=2
66
+ )
67
+ conn.close()
68
+ exit(0)
69
+ except:
70
+ exit(1)
71
+ " 2>/dev/null; then
72
+ log "✅ PostgreSQL đang chạy trên port $POSTGRES_PORT"
73
+ return 0
74
+ fi
75
+ fi
76
+
77
+ warn "⚠️ PostgreSQL không chạy trên port $POSTGRES_PORT"
78
+ return 1
79
+ }
80
+
81
+ # Function to get ngrok tunnel URL
82
+ get_ngrok_url() {
83
+ local host port
84
+ if command -v curl &> /dev/null && command -v python3 &> /dev/null; then
85
+ response=$(curl -s "$NGROK_API_URL/api/tunnels" 2>/dev/null || echo "")
86
+ if [ -n "$response" ]; then
87
+ # Use Python to parse JSON properly
88
+ ngrok_url=$(echo "$response" | python3 -c "
89
+ import sys, json
90
+ try:
91
+ data = json.load(sys.stdin)
92
+ for tunnel in data.get('tunnels', []):
93
+ if tunnel.get('proto') == 'tcp':
94
+ public_url = tunnel.get('public_url', '')
95
+ if public_url.startswith('tcp://'):
96
+ url = public_url.replace('tcp://', '')
97
+ print(url)
98
+ sys.exit(0)
99
+ except:
100
+ pass
101
+ " 2>/dev/null)
102
+ if [ -n "$ngrok_url" ]; then
103
+ echo "$ngrok_url"
104
+ return 0
105
+ fi
106
+ fi
107
+ fi
108
+ return 1
109
+ }
110
+
111
+ # Function to start ngrok
112
+ start_ngrok() {
113
+ log "Khởi động ngrok tunnel..." >&2
114
+
115
+ # Check if ngrok is already running
116
+ if curl -s "$NGROK_API_URL/api/tunnels" &> /dev/null; then
117
+ ngrok_url=$(get_ngrok_url)
118
+ if [ -n "$ngrok_url" ]; then
119
+ log "✅ Ngrok đã chạy sẵn: tcp://$ngrok_url" >&2
120
+ echo "$ngrok_url"
121
+ return 0
122
+ fi
123
+ fi
124
+
125
+ # Kill existing ngrok processes
126
+ pkill -f "ngrok tcp" 2>/dev/null || true
127
+ sleep 1
128
+
129
+ # Start ngrok
130
+ log "Đang start ngrok (ngrok tcp $POSTGRES_PORT --region $NGROK_REGION)..." >&2
131
+ nohup ngrok tcp "$POSTGRES_PORT" --region "$NGROK_REGION" --log=stdout > "$OPS_DIR/ngrok.log" 2>&1 &
132
+ NGROK_PID=$!
133
+
134
+ # Wait for ngrok to start
135
+ for i in {1..10}; do
136
+ sleep 1
137
+ if curl -s "$NGROK_API_URL/api/tunnels" &> /dev/null; then
138
+ ngrok_url=$(get_ngrok_url)
139
+ if [ -n "$ngrok_url" ]; then
140
+ log "✅ Ngrok đã sẵn sàng: tcp://$ngrok_url" >&2
141
+ echo "$ngrok_url"
142
+ return 0
143
+ fi
144
+ fi
145
+ done
146
+
147
+ error "❌ Không thể khởi động ngrok" >&2
148
+ return 1
149
+ }
150
+
151
+ # Function to update DATABASE_URL on Hugging Face Space
152
+ update_hf_space() {
153
+ local host=$1
154
+ local port=$2
155
+
156
+ if [ -z "$host" ] || [ -z "$port" ]; then
157
+ warn "⚠️ Không có ngrok URL, bỏ qua cập nhật HF Space"
158
+ return 1
159
+ fi
160
+
161
+ log "Cập nhật DATABASE_URL lên Hugging Face Space..."
162
+
163
+ if [ -f "$PROJECT_ROOT/backend/venv/bin/python" ]; then
164
+ "$PROJECT_ROOT/backend/venv/bin/python" "$SCRIPT_DIR/start_ngrok_and_set_db.py" 2>&1 | grep -E "(✅|❌|📌)" || true
165
+ else
166
+ warn "⚠️ Không tìm thấy Python venv, bỏ qua cập nhật HF Space"
167
+ fi
168
+ }
169
+
170
+ # Function to save tunnel info
171
+ save_tunnel_info() {
172
+ local host=$1
173
+ local port=$2
174
+
175
+ if [ -z "$host" ] || [ -z "$port" ]; then
176
+ return 1
177
+ fi
178
+
179
+ log "Lưu thông tin tunnel..."
180
+
181
+ cat > "$ENV_TUNNEL" << EOF
182
+ # Ngrok tunnel info - Generated by khoidongDB.sh
183
+ # Last updated: $(date -u +"%Y-%m-%dT%H:%M:%S")
184
+
185
+ PG_TUNNEL_HOST=$host
186
+ PG_TUNNEL_PORT=$port
187
+ PG_TUNNEL_LOCAL_PORT=$POSTGRES_PORT
188
+ PG_TUNNEL_USER=${POSTGRES_USER:-hue_remote}
189
+ PG_TUNNEL_PASSWORD=${POSTGRES_PASSWORD:-huepass123}
190
+ PG_TUNNEL_DB=${POSTGRES_DB:-hue_portal}
191
+ DATABASE_URL=postgres://${POSTGRES_USER:-hue_remote}:${POSTGRES_PASSWORD:-huepass123}@$host:$port/${POSTGRES_DB:-hue_portal}
192
+ HF_SPACE_ID=${HF_SPACE_ID:-davidtran999/hue-portal-backend}
193
+ POSTGRES_HOST=${POSTGRES_HOST:-localhost}
194
+ POSTGRES_PORT=$POSTGRES_PORT
195
+ POSTGRES_USER=${POSTGRES_USER:-hue_remote}
196
+ POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-huepass123}
197
+ POSTGRES_DB=${POSTGRES_DB:-hue_portal}
198
+ PG_TUNNEL_LAST_UPDATED=$(date -u +"%Y-%m-%dT%H:%M:%S")
199
+ EOF
200
+
201
+ log "✅ Đã lưu tunnel info vào $ENV_TUNNEL"
202
+ }
203
+
204
+ # Main execution
205
+ main() {
206
+ log "============================================================"
207
+ log "Khởi động PostgreSQL và ngrok tunnel"
208
+ log "============================================================"
209
+
210
+ # Check PostgreSQL
211
+ if ! check_postgres; then
212
+ error "❌ PostgreSQL không chạy trên port $POSTGRES_PORT"
213
+ error " Vui lòng khởi động PostgreSQL trước"
214
+ exit 1
215
+ fi
216
+
217
+ # Start ngrok
218
+ ngrok_url=$(start_ngrok)
219
+ if [ $? -ne 0 ] || [ -z "$ngrok_url" ]; then
220
+ error "❌ Không thể khởi động ngrok"
221
+ exit 1
222
+ fi
223
+
224
+ ngrok_host=$(echo "$ngrok_url" | cut -d':' -f1)
225
+ ngrok_port=$(echo "$ngrok_url" | cut -d':' -f2)
226
+
227
+ # Save tunnel info
228
+ save_tunnel_info "$ngrok_host" "$ngrok_port"
229
+
230
+ # Update Hugging Face Space
231
+ update_hf_space "$ngrok_host" "$ngrok_port"
232
+
233
+ log "============================================================"
234
+ log "✅ Hoàn tất!"
235
+ log " PostgreSQL: localhost:$POSTGRES_PORT"
236
+ log " Ngrok tunnel: tcp://$ngrok_host:$ngrok_port"
237
+ log " DATABASE_URL: postgres://${POSTGRES_USER:-hue_remote}:***@$ngrok_host:$ngrok_port/${POSTGRES_DB:-hue_portal}"
238
+ log "============================================================"
239
+ }
240
+
241
+ # Run main
242
+ main "$@"
243
+
monitor_space.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Utility script to monitor Hugging Face Space status + logs.
4
+
5
+ Features:
6
+ - Fetch latest build/runtime info using huggingface_hub
7
+ - Download logs via HF REST API and persist to logs/hf_space/
8
+ - Highlight errors (Traceback/SyntaxError) directly in console
9
+ - Optional --watch mode to poll every N seconds
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import argparse
15
+ import json
16
+ import os
17
+ import sys
18
+ import time
19
+ from datetime import datetime
20
+ from pathlib import Path
21
+ from typing import Any, Dict, Optional
22
+
23
+ import requests
24
+ from huggingface_hub import HfApi
25
+
26
+ DEFAULT_SPACE_ID = "davidtran999/hue-portal-backend"
27
+ LOG_ROOT = Path(__file__).resolve().parent / "logs" / "hf_space"
28
+
29
+
30
+ def get_hf_token() -> str:
31
+ """Return Hugging Face token from env or cached file."""
32
+ token = os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACE_HUB_TOKEN")
33
+ if token:
34
+ return token.strip()
35
+
36
+ cache_file = Path.home() / ".cache" / "huggingface" / "token"
37
+ if cache_file.exists():
38
+ return cache_file.read_text(encoding="utf-8").strip()
39
+ return ""
40
+
41
+
42
+ def fetch_space_logs(space_id: str, token: str, limit: int) -> str:
43
+ """Fetch the latest logs, trying both repo path and subdomain API."""
44
+ candidates = []
45
+ if "/" in space_id:
46
+ owner, name = space_id.split("/", 1)
47
+ candidates.append(f"https://huggingface.co/api/spaces/{owner}/{name}/logs?limit={limit}")
48
+ subdomain = f"{owner}-{name}"
49
+ else:
50
+ subdomain = space_id
51
+ candidates.append(f"https://huggingface.co/api/spaces/{subdomain}/logs?limit={limit}")
52
+
53
+ headers = {"Accept": "application/json"}
54
+ if token:
55
+ headers["Authorization"] = f"Bearer {token}"
56
+
57
+ last_error = None
58
+ for url in candidates:
59
+ try:
60
+ response = requests.get(url, headers=headers, timeout=30)
61
+ if response.status_code == 401:
62
+ raise RuntimeError("Không có quyền đọc logs. Hãy đặt HF_TOKEN với quyền write.")
63
+ if response.status_code == 404:
64
+ last_error = f"404 for {url}"
65
+ continue
66
+ response.raise_for_status()
67
+ data = response.json()
68
+ logs = data.get("logs") or data.get("log")
69
+ if isinstance(logs, list):
70
+ return "\n".join(logs)
71
+ if isinstance(logs, str):
72
+ return logs
73
+ return json.dumps(data, ensure_ascii=False)
74
+ except Exception as exc:
75
+ last_error = str(exc)
76
+ continue
77
+ raise RuntimeError(f"Không thể lấy logs. Nguyên nhân gần nhất: {last_error}")
78
+
79
+
80
+ def write_log(space_id: str, space_info: Dict[str, Any], logs: str) -> Path:
81
+ """Persist logs + status info to disk."""
82
+ LOG_ROOT.mkdir(parents=True, exist_ok=True)
83
+ timestamp = datetime.utcnow().strftime("%Y%m%d-%H%M%S")
84
+ safe_space = space_id.replace("/", "__")
85
+ log_path = LOG_ROOT / f"{safe_space}-{timestamp}.log"
86
+
87
+ with log_path.open("w", encoding="utf-8") as fp:
88
+ fp.write(f"# Space: {space_id}\n")
89
+ fp.write(f"# Timestamp: {timestamp} UTC\n")
90
+ fp.write(f"# Runtime: {space_info.get('runtime', {}).get('stage')}\n")
91
+ fp.write(f"# Hardware: {space_info.get('runtime', {}).get('hardware', 'unknown')}\n")
92
+ fp.write("# --- Logs ---\n")
93
+ fp.write(logs)
94
+
95
+ return log_path
96
+
97
+
98
+ def monitor(space_id: str, watch: bool, interval: int, limit: int) -> None:
99
+ token = get_hf_token()
100
+ if not token:
101
+ print("⚠️ Không tìm thấy HF token – chỉ có thể đọc log public.")
102
+
103
+ api = HfApi(token=token or None)
104
+
105
+ def _single_cycle() -> None:
106
+ info = api.space_info(space_id)
107
+ logs = fetch_space_logs(space_id, token, limit)
108
+ log_path = write_log(space_id, info, logs)
109
+
110
+ runtime = info.runtime if hasattr(info, "runtime") else getattr(info, "runtime", {})
111
+ stage = (runtime or {}).get("stage") if isinstance(runtime, dict) else runtime
112
+ hardware = (runtime or {}).get("hardware") if isinstance(runtime, dict) else "unknown"
113
+
114
+ print(f"\n📡 Space: {space_id}")
115
+ print(f" Stage: {stage}, Hardware: {hardware}")
116
+ print(f" Updated: {datetime.utcnow().isoformat()}Z")
117
+ print(f" Logs saved to: {log_path}")
118
+
119
+ alert_keywords = ["Traceback", "SyntaxError", "ModuleNotFoundError"]
120
+ if any(keyword in logs for keyword in alert_keywords):
121
+ print(" 🚨 Detected errors in log (Traceback/SyntaxError). Check file above.")
122
+ else:
123
+ print(" ✅ No critical errors detected in latest log.")
124
+
125
+ _single_cycle()
126
+ while watch:
127
+ time.sleep(interval)
128
+ _single_cycle()
129
+
130
+
131
+ def parse_args(argv: Optional[list[str]] = None) -> argparse.Namespace:
132
+ parser = argparse.ArgumentParser(description="Monitor Hugging Face Space build/logs.")
133
+ parser.add_argument("--space-id", default=DEFAULT_SPACE_ID, help="Ví dụ: owner/space-name")
134
+ parser.add_argument("--interval", type=int, default=30, help="Số giây giữa các l���n kiểm tra (watch mode)")
135
+ parser.add_argument("--limit", type=int, default=200, help="Số dòng log lấy về (max 400)")
136
+ parser.add_argument("--watch", action="store_true", help="Bật chế độ theo dõi liên tục")
137
+ return parser.parse_args(argv)
138
+
139
+
140
+ def main() -> None:
141
+ args = parse_args()
142
+ try:
143
+ monitor(space_id=args.space_id, watch=args.watch, interval=args.interval, limit=args.limit)
144
+ except KeyboardInterrupt:
145
+ print("\n⏹️ Dừng theo dõi theo yêu cầu người dùng.")
146
+
147
+
148
+ if __name__ == "__main__":
149
+ main()
150
+
set_hf_space_env_qwen.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script to set Qwen2.5-7B-Instruct Q4_K_M on Hugging Face Space.
4
+ Upgrade from Gemma 2-2B-it for better Vietnamese legal understanding.
5
+
6
+ Usage:
7
+ python3 set_hf_space_env_qwen.py
8
+ """
9
+ import os
10
+ import sys
11
+ from pathlib import Path
12
+
13
+ try:
14
+ from huggingface_hub import HfApi
15
+ except ImportError:
16
+ print("❌ huggingface_hub not installed. Install with: pip install huggingface_hub")
17
+ sys.exit(1)
18
+
19
+ # Space configuration
20
+ SPACE_ID = "davidtran999/hue-portal-backend"
21
+
22
+ # Environment variables for Qwen2.5-7B-Instruct Q4_K_M
23
+ # Optimized for 2 vCPU + 16GB RAM free tier
24
+ ENV_VARS = {
25
+ "DEFAULT_LLM_PROVIDER": "llama_cpp",
26
+ "LLM_PROVIDER": "llama_cpp",
27
+ # Qwen2.5-7B-Instruct Q4_K_M (~4GB, best balance for free tier)
28
+ "LLAMA_CPP_MODEL_REPO": "bartowski/Qwen2.5-7B-Instruct-GGUF",
29
+ "LLAMA_CPP_MODEL_FILE": "Qwen2.5-7B-Instruct-Q4_K_M.gguf",
30
+ # Context: 2048 tokens (reduced from 4096 to speed up inference on free tier CPU)
31
+ # Qwen2.5-7B Q4_K_M supports up to 8192, but 2048 is optimal for 2 vCPU free tier
32
+ "LLAMA_CPP_CONTEXT": "2048",
33
+ "LLAMA_CPP_THREADS": "2",
34
+ "LLAMA_CPP_BATCH": "512", # Increased to 512 for faster prompt eval (was 256)
35
+ "LLAMA_CPP_MAX_TOKENS": "512",
36
+ "LLAMA_CPP_TEMPERATURE": "0.35",
37
+ "LLAMA_CPP_TOP_P": "0.85",
38
+ "LLAMA_CPP_REPEAT_PENALTY": "1.1",
39
+ "LLAMA_CPP_USE_MMAP": "true",
40
+ "LLAMA_CPP_USE_MLOCK": "true",
41
+ "RUN_HEAVY_STARTUP_TASKS": "0",
42
+ }
43
+
44
+ def main():
45
+ # Get HF token
46
+ hf_token = os.environ.get("HF_TOKEN") or os.environ.get("HUGGINGFACE_HUB_TOKEN")
47
+ if not hf_token:
48
+ token_file = Path.home() / ".cache" / "huggingface" / "token"
49
+ if token_file.exists():
50
+ hf_token = token_file.read_text(encoding="utf-8").strip()
51
+ if not hf_token:
52
+ print("❌ HF_TOKEN not found.")
53
+ print("\n💡 Option 1: Set token as environment variable")
54
+ print(" export HF_TOKEN=your_token_here")
55
+ print(" python3 set_hf_space_env_qwen.py")
56
+ print("\n💡 Option 2: Login with Hugging Face CLI")
57
+ print(" huggingface-cli login")
58
+ print(" python3 set_hf_space_env_qwen.py")
59
+ sys.exit(1)
60
+
61
+ # Initialize API
62
+ api = HfApi(token=hf_token)
63
+
64
+ print(f"🚀 Upgrading to Qwen2.5-7B-Instruct Q4_K_M on Space: {SPACE_ID}")
65
+ print("=" * 60)
66
+ print("📊 Model specs:")
67
+ print(" - Size: ~4GB (downloads from HF, no storage limit)")
68
+ print(" - RAM: ~6-8GB (fits 16GB free tier)")
69
+ print(" - Expected latency: 7-9s on 2 vCPU")
70
+ print(" - Vietnamese legal: Excellent")
71
+ print("=" * 60)
72
+
73
+ for key, value in ENV_VARS.items():
74
+ try:
75
+ print(f"Setting {key}={value}...", end=" ")
76
+ api.delete_space_variable(repo_id=SPACE_ID, key=key)
77
+ except Exception:
78
+ pass # Ignore if variable doesn't exist yet
79
+ try:
80
+ api.add_space_variable(repo_id=SPACE_ID, key=key, value=str(value))
81
+ print("✅")
82
+ except Exception as exc:
83
+ print(f"❌ {exc}")
84
+
85
+ print("=" * 60)
86
+ print("✅ Config updated! Restarting Space...")
87
+
88
+ try:
89
+ api.restart_space(repo_id=SPACE_ID)
90
+ print("✅ Space restarted. Wait 2-3 minutes for model download & load.")
91
+ print("\n💡 Monitor logs at:")
92
+ print(f" https://huggingface.co/spaces/{SPACE_ID}/logs")
93
+ except Exception as exc:
94
+ print(f"⚠️ Config saved but restart failed: {exc}")
95
+ print(" Please restart Space manually from HF dashboard.")
96
+
97
+ if __name__ == "__main__":
98
+ main()
99
+
test_cloudflare_tunnel.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script để test Cloudflare Tunnel URL và kiểm tra dữ liệu PostgreSQL
4
+ """
5
+
6
+ import sys
7
+ import psycopg2
8
+ from pathlib import Path
9
+
10
+ # Colors
11
+ GREEN = '\033[0;32m'
12
+ YELLOW = '\033[1;33m'
13
+ RED = '\033[0;31m'
14
+ BLUE = '\033[0;34m'
15
+ NC = '\033[0m' # No Color
16
+
17
+ def log(msg):
18
+ print(f"{BLUE}[TEST]{NC} {msg}")
19
+
20
+ def success(msg):
21
+ print(f"{GREEN}✅{NC} {msg}")
22
+
23
+ def warn(msg):
24
+ print(f"{YELLOW}⚠️{NC} {msg}")
25
+
26
+ def error(msg):
27
+ print(f"{RED}❌{NC} {msg}")
28
+
29
+ def test_connection(host, port, database, user, password):
30
+ """Test kết nối PostgreSQL"""
31
+ log(f"Đang test kết nối: {host}:{port}/{database}")
32
+
33
+ try:
34
+ conn = psycopg2.connect(
35
+ host=host,
36
+ port=port,
37
+ database=database,
38
+ user=user,
39
+ password=password,
40
+ connect_timeout=10
41
+ )
42
+ success("Kết nối thành công!")
43
+
44
+ cursor = conn.cursor()
45
+
46
+ # Test 1: PostgreSQL version
47
+ cursor.execute("SELECT version();")
48
+ version = cursor.fetchone()[0]
49
+ log(f"PostgreSQL version: {version[:50]}...")
50
+
51
+ # Test 2: Kiểm tra database
52
+ cursor.execute("SELECT current_database();")
53
+ db_name = cursor.fetchone()[0]
54
+ success(f"Đang kết nối database: {db_name}")
55
+
56
+ # Test 3: Kiểm tra số lượng tables
57
+ cursor.execute("""
58
+ SELECT COUNT(*)
59
+ FROM information_schema.tables
60
+ WHERE table_schema = 'public'
61
+ """)
62
+ table_count = cursor.fetchone()[0]
63
+ success(f"Số lượng tables: {table_count}")
64
+
65
+ # Test 4: Kiểm tra dữ liệu trong các bảng chính
66
+ tables_to_check = [
67
+ 'core_legaldocument',
68
+ 'core_fine',
69
+ 'core_procedure',
70
+ 'core_office',
71
+ 'core_advisory',
72
+ ]
73
+
74
+ print(f"\n{BLUE}📊 Kiểm tra dữ liệu:{NC}")
75
+ print("=" * 60)
76
+
77
+ total_docs = 0
78
+ for table in tables_to_check:
79
+ try:
80
+ cursor.execute(f"SELECT COUNT(*) FROM {table};")
81
+ count = cursor.fetchone()[0]
82
+ total_docs += count
83
+ if count > 0:
84
+ success(f"{table}: {count:,} records")
85
+ else:
86
+ warn(f"{table}: 0 records (trống)")
87
+ except Exception as e:
88
+ error(f"{table}: Lỗi - {e}")
89
+
90
+ print("=" * 60)
91
+ success(f"Tổng số documents: {total_docs:,}")
92
+
93
+ # Test 5: Kiểm tra một vài records mẫu
94
+ if total_docs > 0:
95
+ print(f"\n{BLUE}📄 Sample records:{NC}")
96
+ try:
97
+ cursor.execute("""
98
+ SELECT id, title, created_at
99
+ FROM core_legaldocument
100
+ ORDER BY created_at DESC
101
+ LIMIT 5
102
+ """)
103
+ records = cursor.fetchall()
104
+ for idx, (doc_id, title, created_at) in enumerate(records, 1):
105
+ title_short = (title[:50] + "...") if title and len(title) > 50 else (title or "N/A")
106
+ print(f" {idx}. [{doc_id}] {title_short}")
107
+ print(f" Created: {created_at}")
108
+ except Exception as e:
109
+ warn(f"Không thể lấy sample records: {e}")
110
+
111
+ cursor.close()
112
+ conn.close()
113
+
114
+ return True, total_docs
115
+
116
+ except psycopg2.OperationalError as e:
117
+ error(f"Lỗi kết nối: {e}")
118
+ return False, 0
119
+ except Exception as e:
120
+ error(f"Lỗi: {e}")
121
+ return False, 0
122
+
123
+ def main():
124
+ print(f"{BLUE}{'='*60}{NC}")
125
+ print(f"{BLUE}Test Cloudflare Tunnel và kiểm tra dữ liệu PostgreSQL{NC}")
126
+ print(f"{BLUE}{'='*60}{NC}\n")
127
+
128
+ # Lấy thông tin từ user
129
+ print("Nhập thông tin Cloudflare Tunnel:")
130
+ tunnel_host = input(" Host (ví dụ: xyz.trycloudflare.com hoặc xyz.cfargotunnel.com): ").strip()
131
+ tunnel_port = input(" Port (ví dụ: 5432): ").strip() or "5432"
132
+
133
+ # Database credentials
134
+ db_user = input(" Database user (mặc định: hue_remote): ").strip() or "hue_remote"
135
+ db_password = input(" Database password (mặc định: huepass123): ").strip() or "huepass123"
136
+ db_name = input(" Database name (mặc định: hue_portal): ").strip() or "hue_portal"
137
+
138
+ print(f"\n{BLUE}🔍 Đang test kết nối...{NC}\n")
139
+
140
+ # Test connection
141
+ success_conn, doc_count = test_connection(
142
+ tunnel_host,
143
+ int(tunnel_port),
144
+ db_name,
145
+ db_user,
146
+ db_password
147
+ )
148
+
149
+ if success_conn:
150
+ print(f"\n{BLUE}{'='*60}{NC}")
151
+ success("KẾT NỐI THÀNH CÔNG!")
152
+ if doc_count > 0:
153
+ success(f"Có {doc_count:,} documents trong database")
154
+ print(f"\n{BLUE}📝 DATABASE_URL đ�� dùng:{NC}")
155
+ print(f"postgres://{db_user}:{db_password}@{tunnel_host}:{tunnel_port}/{db_name}")
156
+ else:
157
+ warn("Database trống, chưa có dữ liệu")
158
+ print(f"{BLUE}{'='*60}{NC}")
159
+ else:
160
+ print(f"\n{BLUE}{'='*60}{NC}")
161
+ error("KHÔNG KẾT NỐI ĐƯỢC!")
162
+ print(f"\n{BLUE}💡 Kiểm tra:{NC}")
163
+ print(" 1. Cloudflare Tunnel URL có đúng không?")
164
+ print(" 2. Tunnel có đang chạy trên server không?")
165
+ print(" 3. PostgreSQL có đang chạy không?")
166
+ print(" 4. Firewall có block port không?")
167
+ print(f"{BLUE}{'='*60}{NC}")
168
+ sys.exit(1)
169
+
170
+ if __name__ == "__main__":
171
+ main()
172
+
test_ngrok.sh ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Script test ngrok tunnel và kiểm tra PostgreSQL connection
3
+ # Usage: ./test_ngrok.sh [ngrok_host] [ngrok_port]
4
+
5
+ set -e
6
+
7
+ # Colors
8
+ GREEN='\033[0;32m'
9
+ YELLOW='\033[1;33m'
10
+ RED='\033[0;31m'
11
+ BLUE='\033[0;34m'
12
+ NC='\033[0m'
13
+
14
+ log() {
15
+ echo -e "${BLUE}[TEST]${NC} $1"
16
+ }
17
+
18
+ success() {
19
+ echo -e "${GREEN}✅${NC} $1"
20
+ }
21
+
22
+ warn() {
23
+ echo -e "${YELLOW}⚠️${NC} $1"
24
+ }
25
+
26
+ error() {
27
+ echo -e "${RED}❌${NC} $1"
28
+ }
29
+
30
+ # Default values
31
+ NGROK_API="http://192.168.1.212:4040"
32
+ DB_USER="${POSTGRES_USER:-hue_remote}"
33
+ DB_PASSWORD="${POSTGRES_PASSWORD:-huepass123}"
34
+ DB_NAME="${POSTGRES_DB:-hue_portal}"
35
+
36
+ echo -e "${BLUE}============================================================${NC}"
37
+ echo -e "${BLUE}Test Ngrok Tunnel và PostgreSQL Connection${NC}"
38
+ echo -e "${BLUE}============================================================${NC}"
39
+ echo ""
40
+
41
+ # Step 1: Check ngrok API
42
+ log "Bước 1: Kiểm tra ngrok API ($NGROK_API)..."
43
+ if command -v curl &> /dev/null; then
44
+ if curl -s "$NGROK_API/api/tunnels" &> /dev/null; then
45
+ success "Ngrok API đang chạy"
46
+ else
47
+ error "Không thể kết nối ngrok API"
48
+ echo ""
49
+ echo "💡 Kiểm tra:"
50
+ echo " 1. Ngrok container có đang chạy không?"
51
+ echo " 2. Port 4040 có được expose không?"
52
+ echo " 3. Thử truy cập: http://192.168.1.212:4040"
53
+ exit 1
54
+ fi
55
+ else
56
+ warn "Không có curl, bỏ qua kiểm tra API"
57
+ fi
58
+
59
+ # Step 2: Get ngrok tunnel URL
60
+ log "Bước 2: Lấy ngrok tunnel URL..."
61
+ if command -v curl &> /dev/null && command -v python3 &> /dev/null; then
62
+ response=$(curl -s "$NGROK_API/api/tunnels" 2>/dev/null || echo "")
63
+ if [ -n "$response" ]; then
64
+ ngrok_url=$(echo "$response" | python3 -c "
65
+ import sys, json
66
+ try:
67
+ data = json.load(sys.stdin)
68
+ tunnels = data.get('tunnels', [])
69
+ if not tunnels:
70
+ print('NO_TUNNELS')
71
+ sys.exit(0)
72
+ for tunnel in tunnels:
73
+ if tunnel.get('proto') == 'tcp':
74
+ public_url = tunnel.get('public_url', '')
75
+ if public_url.startswith('tcp://'):
76
+ url = public_url.replace('tcp://', '')
77
+ print(url)
78
+ sys.exit(0)
79
+ print('NO_TCP_TUNNEL')
80
+ except Exception as e:
81
+ print('ERROR: ' + str(e))
82
+ " 2>/dev/null)
83
+
84
+ if [ "$ngrok_url" = "NO_TUNNELS" ]; then
85
+ error "Không tìm thấy tunnel nào!"
86
+ echo ""
87
+ echo "💡 Kiểm tra:"
88
+ echo " 1. Ngrok có đang chạy command 'tcp' không?"
89
+ echo " 2. Toggle switch có được BẬT (ON) không?"
90
+ echo " 3. Xem logs: docker logs ngrok"
91
+ exit 1
92
+ elif [ "$ngrok_url" = "NO_TCP_TUNNEL" ]; then
93
+ error "Không tìm thấy TCP tunnel!"
94
+ echo ""
95
+ echo "💡 Ngrok có thể đang chạy HTTP tunnel, cần TCP tunnel cho PostgreSQL"
96
+ exit 1
97
+ elif [[ "$ngrok_url" == ERROR* ]]; then
98
+ error "Lỗi parse JSON: $ngrok_url"
99
+ exit 1
100
+ else
101
+ ngrok_host=$(echo "$ngrok_url" | cut -d':' -f1)
102
+ ngrok_port=$(echo "$ngrok_url" | cut -d':' -f2)
103
+ success "Tìm thấy ngrok URL: tcp://$ngrok_host:$ngrok_port"
104
+ fi
105
+ else
106
+ error "Không thể lấy thông tin từ ngrok API"
107
+ exit 1
108
+ fi
109
+ else
110
+ # Manual input
111
+ if [ -n "$1" ] && [ -n "$2" ]; then
112
+ ngrok_host="$1"
113
+ ngrok_port="$2"
114
+ warn "Dùng ngrok URL từ tham số: tcp://$ngrok_host:$ngrok_port"
115
+ else
116
+ error "Cần cung cấp ngrok host và port"
117
+ echo ""
118
+ echo "Usage: $0 [ngrok_host] [ngrok_port]"
119
+ echo "Ví dụ: $0 0.tcp.ap.ngrok.io 13432"
120
+ exit 1
121
+ fi
122
+ fi
123
+
124
+ echo ""
125
+ log "Thông tin kết nối:"
126
+ echo " Ngrok Host: $ngrok_host"
127
+ echo " Ngrok Port: $ngrok_port"
128
+ echo " Database User: $DB_USER"
129
+ echo " Database Name: $DB_NAME"
130
+ echo ""
131
+
132
+ # Step 3: Test PostgreSQL connection
133
+ log "Bước 3: Test kết nối PostgreSQL qua ngrok..."
134
+ export PGPASSWORD="$DB_PASSWORD"
135
+
136
+ if command -v psql &> /dev/null; then
137
+ if psql -h "$ngrok_host" -p "$ngrok_port" -U "$DB_USER" -d "$DB_NAME" -c "SELECT 1;" &>/dev/null; then
138
+ success "Kết nối PostgreSQL thành công!"
139
+ echo ""
140
+
141
+ # Get PostgreSQL version
142
+ VERSION=$(psql -h "$ngrok_host" -p "$ngrok_port" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT version();" 2>/dev/null | head -1 | xargs)
143
+ log "PostgreSQL version: ${VERSION:0:60}..."
144
+
145
+ # Count tables
146
+ TABLE_COUNT=$(psql -h "$ngrok_host" -p "$ngrok_port" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';" 2>/dev/null | xargs)
147
+ success "Số lượng tables: $TABLE_COUNT"
148
+ echo ""
149
+
150
+ # Check data
151
+ echo -e "${BLUE}📊 Kiểm tra dữ liệu:${NC}"
152
+ echo "============================================================"
153
+
154
+ TOTAL_DOCS=0
155
+
156
+ for table in core_legaldocument core_fine core_procedure core_office core_advisory; do
157
+ COUNT=$(psql -h "$ngrok_host" -p "$ngrok_port" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT COUNT(*) FROM $table;" 2>/dev/null | xargs || echo "0")
158
+ if [ "$COUNT" != "0" ] && [ -n "$COUNT" ]; then
159
+ TOTAL_DOCS=$((TOTAL_DOCS + COUNT))
160
+ success "$table: $(printf "%'d" $COUNT) records"
161
+ else
162
+ warn "$table: 0 records (trống)"
163
+ fi
164
+ done
165
+
166
+ echo "============================================================"
167
+ success "Tổng số documents: $(printf "%'d" $TOTAL_DOCS)"
168
+ echo ""
169
+
170
+ # Show DATABASE_URL
171
+ echo -e "${BLUE}============================================================${NC}"
172
+ success "✅ NGROK TUNNEL HOẠT ĐỘNG TỐT!"
173
+ if [ "$TOTAL_DOCS" -gt 0 ]; then
174
+ success "Có $(printf "%'d" $TOTAL_DOCS) documents trong database"
175
+ else
176
+ warn "Database trống, chưa có dữ liệu"
177
+ fi
178
+ echo ""
179
+ echo -e "${BLUE}📝 DATABASE_URL để dùng:${NC}"
180
+ echo "postgres://$DB_USER:$DB_PASSWORD@$ngrok_host:$ngrok_port/$DB_NAME"
181
+ echo -e "${BLUE}============================================================${NC}"
182
+
183
+ else
184
+ error "KHÔNG KẾT NỐI ĐƯỢC PostgreSQL!"
185
+ echo ""
186
+ echo -e "${BLUE}💡 Kiểm tra:${NC}"
187
+ echo " 1. PostgreSQL có đang chạy trên 192.168.1.212:5432 không?"
188
+ echo " 2. Ngrok tunnel có đang chạy đúng command 'tcp 192.168.1.212:5432' không?"
189
+ echo " 3. Toggle switch có được BẬT (ON) không?"
190
+ echo " 4. Firewall có block không?"
191
+ echo ""
192
+ echo "Thử test trực tiếp:"
193
+ echo " psql -h $ngrok_host -p $ngrok_port -U $DB_USER -d $DB_NAME"
194
+ exit 1
195
+ fi
196
+ else
197
+ warn "Không có psql, bỏ qua test PostgreSQL"
198
+ echo ""
199
+ echo -e "${BLUE}📝 DATABASE_URL để dùng:${NC}"
200
+ echo "postgres://$DB_USER:$DB_PASSWORD@$ngrok_host:$ngrok_port/$DB_NAME"
201
+ fi
202
+
203
+
204
+
205
+
206
+
test_ngrok_simple.sh ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Script test ngrok tunnel đơn giản - không cần API
3
+ # Usage: ./test_ngrok_simple.sh <ngrok_host> <ngrok_port>
4
+
5
+ set -e
6
+
7
+ # Colors
8
+ GREEN='\033[0;32m'
9
+ YELLOW='\033[1;33m'
10
+ RED='\033[0;31m'
11
+ BLUE='\033[0;34m'
12
+ NC='\033[0m'
13
+
14
+ success() {
15
+ echo -e "${GREEN}✅${NC} $1"
16
+ }
17
+
18
+ warn() {
19
+ echo -e "${YELLOW}⚠️${NC} $1"
20
+ }
21
+
22
+ error() {
23
+ echo -e "${RED}❌${NC} $1"
24
+ }
25
+
26
+ log() {
27
+ echo -e "${BLUE}[TEST]${NC} $1"
28
+ }
29
+
30
+ # Parse arguments
31
+ NGROK_HOST="${1:-}"
32
+ NGROK_PORT="${2:-}"
33
+
34
+ if [ -z "$NGROK_HOST" ] || [ -z "$NGROK_PORT" ]; then
35
+ error "Thiếu tham số!"
36
+ echo ""
37
+ echo "Usage: $0 <ngrok_host> <ngrok_port>"
38
+ echo ""
39
+ echo "Ví dụ:"
40
+ echo " $0 0.tcp.ap.ngrok.io 13432"
41
+ echo ""
42
+ echo "💡 Lấy ngrok URL từ:"
43
+ echo " 1. Docker logs: docker logs ngrok | grep tcp://"
44
+ echo " 2. Web interface: http://192.168.1.212:4040"
45
+ echo " 3. Hoặc xem trong Unraid Docker logs"
46
+ exit 1
47
+ fi
48
+
49
+ DB_USER="${POSTGRES_USER:-hue_remote}"
50
+ DB_PASSWORD="${POSTGRES_PASSWORD:-huepass123}"
51
+ DB_NAME="${POSTGRES_DB:-hue_portal}"
52
+
53
+ echo -e "${BLUE}============================================================${NC}"
54
+ echo -e "${BLUE}Test Ngrok Tunnel: $NGROK_HOST:$NGROK_PORT${NC}"
55
+ echo -e "${BLUE}============================================================${NC}"
56
+ echo ""
57
+
58
+ log "Đang test kết nối PostgreSQL..."
59
+ export PGPASSWORD="$DB_PASSWORD"
60
+
61
+ if command -v psql &> /dev/null; then
62
+ # Test với timeout 5 giây
63
+ if timeout 5 psql -h "$NGROK_HOST" -p "$NGROK_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT 1;" &>/dev/null; then
64
+ success "Kết nối thành công!"
65
+ echo ""
66
+
67
+ # Get version
68
+ VERSION=$(timeout 5 psql -h "$NGROK_HOST" -p "$NGROK_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT version();" 2>/dev/null | head -1 | xargs)
69
+ log "PostgreSQL: ${VERSION:0:50}..."
70
+
71
+ # Count tables
72
+ TABLE_COUNT=$(timeout 5 psql -h "$NGROK_HOST" -p "$NGROK_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';" 2>/dev/null | xargs)
73
+ success "Tables: $TABLE_COUNT"
74
+ echo ""
75
+
76
+ # Quick data check
77
+ TOTAL=$(timeout 5 psql -h "$NGROK_HOST" -p "$NGROK_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT COUNT(*) FROM core_legaldocument;" 2>/dev/null | xargs || echo "0")
78
+ if [ "$TOTAL" != "0" ]; then
79
+ success "Documents: $(printf "%'d" $TOTAL)"
80
+ else
81
+ warn "Database trống"
82
+ fi
83
+
84
+ echo ""
85
+ echo -e "${BLUE}============================================================${NC}"
86
+ success "✅ NGROK TUNNEL HOẠT ĐỘNG!"
87
+ echo ""
88
+ echo -e "${BLUE}📝 DATABASE_URL:${NC}"
89
+ echo "postgres://$DB_USER:$DB_PASSWORD@$NGROK_HOST:$NGROK_PORT/$DB_NAME"
90
+ echo -e "${BLUE}============================================================${NC}"
91
+
92
+ else
93
+ error "KHÔNG KẾT NỐI ĐƯỢC!"
94
+ echo ""
95
+ echo "💡 Kiểm tra:"
96
+ echo " 1. Ngrok URL có đúng không? (từ logs: docker logs ngrok)"
97
+ echo " 2. Toggle switch có ON không?"
98
+ echo " 3. PostgreSQL có chạy trên 192.168.1.212:5432 không?"
99
+ exit 1
100
+ fi
101
+ else
102
+ error "Không có psql để test!"
103
+ echo ""
104
+ echo "Cài đặt: brew install postgresql"
105
+ echo ""
106
+ echo "Hoặc dùng DATABASE_URL này:"
107
+ echo "postgres://$DB_USER:$DB_PASSWORD@$NGROK_HOST:$NGROK_PORT/$DB_NAME"
108
+ exit 1
109
+ fi
110
+
111
+
112
+
113
+
114
+
test_postgres_quick.sh ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ # Colors
4
+ GREEN='\033[0;32m'
5
+ RED='\033[0;31m'
6
+ YELLOW='\033[1;33m'
7
+ BLUE='\033[0;34m'
8
+ NC='\033[0m'
9
+
10
+ echo "============================================================"
11
+ echo "🔍 Quick Test PostgreSQL Connection"
12
+ echo "============================================================"
13
+ echo ""
14
+
15
+ HOST="postgres.aliss.io.vn"
16
+ PORT="5432"
17
+ USER="hue_remote"
18
+ PASSWORD="huepass123"
19
+ DB="hue_portal"
20
+
21
+ # Test 1: DNS Resolution
22
+ echo "1️⃣ Testing DNS resolution..."
23
+ if nslookup "$HOST" > /dev/null 2>&1; then
24
+ IP=$(dig +short "$HOST" | head -1)
25
+ echo -e "${GREEN}✅ DNS OK: $HOST → $IP${NC}"
26
+ else
27
+ echo -e "${RED}❌ DNS FAILED${NC}"
28
+ exit 1
29
+ fi
30
+
31
+ # Test 2: Port connectivity (timeout 5s)
32
+ echo ""
33
+ echo "2️⃣ Testing port connectivity (timeout 5s)..."
34
+ if timeout 5 bash -c "cat < /dev/null > /dev/tcp/$HOST/$PORT" 2>/dev/null; then
35
+ echo -e "${GREEN}✅ Port $PORT is open${NC}"
36
+ else
37
+ echo -e "${YELLOW}⚠️ Port test failed (có thể do firewall hoặc tunnel chưa ready)${NC}"
38
+ fi
39
+
40
+ # Test 3: PostgreSQL connection
41
+ echo ""
42
+ echo "3️⃣ Testing PostgreSQL connection (timeout 10s)..."
43
+ export PGPASSWORD="$PASSWORD"
44
+
45
+ if timeout 10 psql -h "$HOST" -p "$PORT" -U "$USER" -d "$DB" -c "SELECT 1 as test;" 2>&1 | grep -q "test"; then
46
+ echo -e "${GREEN}✅ PostgreSQL connection SUCCESS!${NC}"
47
+ echo ""
48
+ echo "📝 DATABASE_URL:"
49
+ echo "postgres://$USER:$PASSWORD@$HOST:$PORT/$DB"
50
+ echo ""
51
+
52
+ # Quick data check
53
+ echo "4️⃣ Checking database data..."
54
+ COUNT=$(timeout 10 psql -h "$HOST" -p "$PORT" -U "$USER" -d "$DB" -t -c "SELECT COUNT(*) FROM core_legaldocument;" 2>/dev/null | xargs)
55
+ if [ -n "$COUNT" ]; then
56
+ echo -e "${GREEN}✅ Database has $COUNT legal documents${NC}"
57
+ else
58
+ echo -e "${YELLOW}⚠️ Could not check data count${NC}"
59
+ fi
60
+
61
+ exit 0
62
+ else
63
+ echo -e "${RED}❌ PostgreSQL connection FAILED${NC}"
64
+ echo ""
65
+ echo "💡 Troubleshooting:"
66
+ echo " 1. Check tunnel logs on Unraid: docker logs mystifying_bassi --tail 20"
67
+ echo " 2. Verify tunnel config has: postgres.aliss.io.vn → tcp://192.168.1.212:5432"
68
+ echo " 3. Check PostgreSQL is running: docker ps | grep postgres"
69
+ echo " 4. Try restart tunnel: docker restart mystifying_bassi"
70
+ exit 1
71
+ fi
72
+
73
+
74
+
75
+
76
+
test_tunnel.sh ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Script test Cloudflare Tunnel URL và kiểm tra dữ liệu PostgreSQL
3
+ # Usage: ./test_tunnel.sh <host> <port> [user] [password] [database]
4
+
5
+ set -e
6
+
7
+ # Colors
8
+ GREEN='\033[0;32m'
9
+ YELLOW='\033[1;33m'
10
+ RED='\033[0;31m'
11
+ BLUE='\033[0;34m'
12
+ NC='\033[0m'
13
+
14
+ log() {
15
+ echo -e "${BLUE}[TEST]${NC} $1"
16
+ }
17
+
18
+ success() {
19
+ echo -e "${GREEN}✅${NC} $1"
20
+ }
21
+
22
+ warn() {
23
+ echo -e "${YELLOW}⚠️${NC} $1"
24
+ }
25
+
26
+ error() {
27
+ echo -e "${RED}❌${NC} $1"
28
+ }
29
+
30
+ # Parse arguments
31
+ TUNNEL_HOST="${1:-}"
32
+ TUNNEL_PORT="${2:-5432}"
33
+ DB_USER="${3:-hue_remote}"
34
+ DB_PASSWORD="${4:-huepass123}"
35
+ DB_NAME="${5:-hue_portal}"
36
+
37
+ if [ -z "$TUNNEL_HOST" ]; then
38
+ error "Thiếu tham số host!"
39
+ echo ""
40
+ echo "Usage: $0 <host> [port] [user] [password] [database]"
41
+ echo ""
42
+ echo "Ví dụ:"
43
+ echo " $0 nas.aliss.io.vn 5432"
44
+ echo " $0 xyz.trycloudflare.com 5432 hue_remote huepass123 hue_portal"
45
+ exit 1
46
+ fi
47
+
48
+ echo -e "${BLUE}============================================================${NC}"
49
+ echo -e "${BLUE}Test Cloudflare Tunnel và kiểm tra dữ liệu PostgreSQL${NC}"
50
+ echo -e "${BLUE}============================================================${NC}"
51
+ echo ""
52
+ log "Thông tin kết nối:"
53
+ echo " Host: $TUNNEL_HOST"
54
+ echo " Port: $TUNNEL_PORT"
55
+ echo " User: $DB_USER"
56
+ echo " Database: $DB_NAME"
57
+ echo ""
58
+
59
+ # Test connection
60
+ log "Đang test kết nối..."
61
+ export PGPASSWORD="$DB_PASSWORD"
62
+
63
+ if psql -h "$TUNNEL_HOST" -p "$TUNNEL_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT 1;" &>/dev/null; then
64
+ success "Kết nối thành công!"
65
+ echo ""
66
+
67
+ # Get PostgreSQL version
68
+ VERSION=$(psql -h "$TUNNEL_HOST" -p "$TUNNEL_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT version();" 2>/dev/null | head -1 | xargs)
69
+ log "PostgreSQL version: ${VERSION:0:50}..."
70
+
71
+ # Count tables
72
+ TABLE_COUNT=$(psql -h "$TUNNEL_HOST" -p "$TUNNEL_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';" 2>/dev/null | xargs)
73
+ success "Số lượng tables: $TABLE_COUNT"
74
+ echo ""
75
+
76
+ # Check data
77
+ echo -e "${BLUE}📊 Kiểm tra dữ liệu:${NC}"
78
+ echo "============================================================"
79
+
80
+ TOTAL_DOCS=0
81
+
82
+ for table in core_legaldocument core_fine core_procedure core_office core_advisory; do
83
+ COUNT=$(psql -h "$TUNNEL_HOST" -p "$TUNNEL_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT COUNT(*) FROM $table;" 2>/dev/null | xargs || echo "0")
84
+ if [ "$COUNT" != "0" ] && [ -n "$COUNT" ]; then
85
+ TOTAL_DOCS=$((TOTAL_DOCS + COUNT))
86
+ success "$table: $(printf "%'d" $COUNT) records"
87
+ else
88
+ warn "$table: 0 records (trống)"
89
+ fi
90
+ done
91
+
92
+ echo "============================================================"
93
+ success "Tổng số documents: $(printf "%'d" $TOTAL_DOCS)"
94
+ echo ""
95
+
96
+ # Show sample records
97
+ if [ "$TOTAL_DOCS" -gt 0 ]; then
98
+ echo -e "${BLUE}📄 Sample records (5 mới nhất):${NC}"
99
+ psql -h "$TUNNEL_HOST" -p "$TUNNEL_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
100
+ SELECT id, LEFT(title, 50) as title, created_at
101
+ FROM core_legaldocument
102
+ ORDER BY created_at DESC
103
+ LIMIT 5;
104
+ " 2>/dev/null || warn "Không thể lấy sample records"
105
+ echo ""
106
+ fi
107
+
108
+ # Show DATABASE_URL
109
+ echo -e "${BLUE}============================================================${NC}"
110
+ success "KẾT NỐI THÀNH CÔNG!"
111
+ if [ "$TOTAL_DOCS" -gt 0 ]; then
112
+ success "Có $(printf "%'d" $TOTAL_DOCS) documents trong database"
113
+ else
114
+ warn "Database trống, chưa có dữ liệu"
115
+ fi
116
+ echo ""
117
+ echo -e "${BLUE}📝 DATABASE_URL để dùng:${NC}"
118
+ echo "postgres://$DB_USER:$DB_PASSWORD@$TUNNEL_HOST:$TUNNEL_PORT/$DB_NAME"
119
+ echo -e "${BLUE}============================================================${NC}"
120
+
121
+ else
122
+ error "KHÔNG KẾT NỐI ĐƯỢC!"
123
+ echo ""
124
+ echo -e "${BLUE}💡 Kiểm tra:${NC}"
125
+ echo " 1. Cloudflare Tunnel URL có đúng không?"
126
+ echo " 2. Tunnel có đang chạy trên server không?"
127
+ echo " 3. PostgreSQL có đang chạy không?"
128
+ echo " 4. Firewall có block port không?"
129
+ echo ""
130
+ echo "Thử test với:"
131
+ echo " psql -h $TUNNEL_HOST -p $TUNNEL_PORT -U $DB_USER -d $DB_NAME"
132
+ exit 1
133
+ fi
134
+
135
+
136
+
137
+
138
+
139
+