ghostdrive1 commited on
Commit
86ba74e
·
verified ·
1 Parent(s): 69d14a0

Upload folder using huggingface_hub

Browse files
examples/redis_space/Dockerfile ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ # Install Redis
4
+ RUN apt-get update && apt-get install -y redis-server && rm -rf /var/lib/apt/lists/*
5
+
6
+ WORKDIR /app
7
+
8
+ # Install Python dependencies
9
+ RUN pip install fastapi uvicorn websockets huggingface_hub schedule
10
+
11
+ COPY . .
12
+
13
+ # Set up Redis data directory
14
+ RUN mkdir -p /data
15
+ RUN sed -i 's/^dir .*/dir \/data/' /etc/redis/redis.conf
16
+
17
+ # Add start script
18
+ RUN chmod +x start.sh
19
+
20
+ CMD ["./start.sh"]
examples/redis_space/app.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ from fastapi import FastAPI, WebSocket
3
+ from fastapi.responses import HTMLResponse
4
+ import logging
5
+
6
+ logging.basicConfig(level=logging.INFO)
7
+ logger = logging.getLogger(__name__)
8
+
9
+ app = FastAPI()
10
+
11
+ @app.get("/")
12
+ def read_root():
13
+ return HTMLResponse("<h1>Redis WebSocket Proxy Running</h1>")
14
+
15
+ @app.websocket("/ws")
16
+ async def websocket_endpoint(websocket: WebSocket):
17
+ await websocket.accept()
18
+ logger.info("WebSocket connection accepted.")
19
+
20
+ try:
21
+ # Connect to local Redis TCP port
22
+ reader, writer = await asyncio.open_connection("127.0.0.1", 6379)
23
+ logger.info("Connected to local Redis.")
24
+ except Exception as e:
25
+ logger.error(f"Failed to connect to local Redis: {e}")
26
+ await websocket.close()
27
+ return
28
+
29
+ async def pipe_ws_to_tcp():
30
+ try:
31
+ while True:
32
+ data = await websocket.receive_bytes()
33
+ writer.write(data)
34
+ await writer.drain()
35
+ except Exception as e:
36
+ logger.info(f"ws_to_tcp closed: {e}")
37
+
38
+ async def pipe_tcp_to_ws():
39
+ try:
40
+ while True:
41
+ data = await reader.read(4096)
42
+ if not data:
43
+ break
44
+ await websocket.send_bytes(data)
45
+ except Exception as e:
46
+ logger.info(f"tcp_to_ws closed: {e}")
47
+
48
+ try:
49
+ await asyncio.gather(
50
+ pipe_ws_to_tcp(),
51
+ pipe_tcp_to_ws(),
52
+ return_exceptions=True
53
+ )
54
+ finally:
55
+ writer.close()
56
+ try:
57
+ await websocket.close()
58
+ except:
59
+ pass
60
+ logger.info("Connection closed.")
examples/redis_space/backup_manager.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import schedule
4
+ from huggingface_hub import HfApi, hf_hub_download
5
+ import subprocess
6
+ import logging
7
+
8
+ logging.basicConfig(level=logging.INFO)
9
+ logger = logging.getLogger(__name__)
10
+
11
+ HF_TOKEN = os.getenv("HF_TOKEN")
12
+ DATASET_REPO = os.getenv("DATASET_REPO", "augment17/agentscope-redis-backup")
13
+ DUMP_FILE = "/data/dump.rdb"
14
+ LOCAL_DUMP = "dump.rdb"
15
+
16
+ api = HfApi(token=HF_TOKEN)
17
+
18
+ def ensure_repo():
19
+ try:
20
+ api.repo_info(repo_id=DATASET_REPO, repo_type="dataset")
21
+ except Exception:
22
+ logger.info(f"Creating dataset repo {DATASET_REPO}...")
23
+ api.create_repo(repo_id=DATASET_REPO, repo_type="dataset", private=True)
24
+
25
+ def restore_backup():
26
+ ensure_repo()
27
+ try:
28
+ logger.info("Checking for existing Redis backup...")
29
+ downloaded_file = hf_hub_download(
30
+ repo_id=DATASET_REPO,
31
+ repo_type="dataset",
32
+ filename=LOCAL_DUMP,
33
+ token=HF_TOKEN,
34
+ local_dir="/data"
35
+ )
36
+ logger.info(f"Restored backup from {downloaded_file}")
37
+ except Exception as e:
38
+ logger.info(f"No existing backup found or failed to restore: {e}")
39
+
40
+ def perform_backup():
41
+ logger.info("Performing Redis backup...")
42
+ try:
43
+ # Trigger Redis bgsave
44
+ subprocess.run(["redis-cli", "save"], check=True)
45
+ if os.path.exists(DUMP_FILE):
46
+ api.upload_file(
47
+ path_or_fileobj=DUMP_FILE,
48
+ path_in_repo=LOCAL_DUMP,
49
+ repo_id=DATASET_REPO,
50
+ repo_type="dataset",
51
+ token=HF_TOKEN
52
+ )
53
+ logger.info("Backup uploaded to Hugging Face Datasets successfully.")
54
+ else:
55
+ logger.error("dump.rdb not found after save!")
56
+ except Exception as e:
57
+ logger.error(f"Backup failed: {e}")
58
+
59
+ if __name__ == "__main__":
60
+ mode = os.getenv("MODE", "restore")
61
+ if mode == "restore":
62
+ restore_backup()
63
+ elif mode == "cron":
64
+ logger.info("Starting backup cron schedule (every 30 minutes)...")
65
+ schedule.every(30).minutes.do(perform_backup)
66
+ while True:
67
+ schedule.run_pending()
68
+ time.sleep(60)
examples/redis_space/start.sh ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Restore backup from HF Datasets
5
+ echo "Restoring database from Hugging Face Datasets..."
6
+ MODE=restore python backup_manager.py
7
+
8
+ # Start Redis Server in background
9
+ echo "Starting Redis server..."
10
+ redis-server /etc/redis/redis.conf &
11
+
12
+ # Start backup cron loop in background
13
+ echo "Starting background backup loop..."
14
+ MODE=cron python backup_manager.py &
15
+
16
+ # Start FastAPI WebSocket Proxy in foreground (port 7860 for HF Spaces)
17
+ echo "Starting FastAPI WebSocket proxy..."
18
+ uvicorn app:app --host 0.0.0.0 --port 7860
local_ws_proxy.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import os
3
+ import websockets
4
+ import logging
5
+
6
+ logging.basicConfig(level=logging.INFO)
7
+ logger = logging.getLogger(__name__)
8
+
9
+ # The remote HF Space websocket URL (e.g., wss://augment17-redis.hf.space/ws)
10
+ REMOTE_WS_URL = os.getenv("REMOTE_REDIS_WS_URL")
11
+ LOCAL_PORT = int(os.getenv("LOCAL_REDIS_PORT", 6379))
12
+
13
+ async def handle_client(reader, writer):
14
+ if not REMOTE_WS_URL:
15
+ logger.error("REMOTE_REDIS_WS_URL is not set!")
16
+ writer.close()
17
+ return
18
+
19
+ logger.info("New local TCP connection. Connecting to remote WebSocket...")
20
+ try:
21
+ async with websockets.connect(REMOTE_WS_URL) as ws:
22
+ logger.info("Connected to remote WebSocket.")
23
+
24
+ async def pipe_tcp_to_ws():
25
+ try:
26
+ while True:
27
+ data = await reader.read(4096)
28
+ if not data:
29
+ break
30
+ await ws.send(data)
31
+ except Exception as e:
32
+ logger.info(f"tcp_to_ws closed: {e}")
33
+
34
+ async def pipe_ws_to_tcp():
35
+ try:
36
+ while True:
37
+ data = await ws.recv()
38
+ writer.write(data)
39
+ await writer.drain()
40
+ except Exception as e:
41
+ logger.info(f"ws_to_tcp closed: {e}")
42
+
43
+ await asyncio.gather(
44
+ pipe_tcp_to_ws(),
45
+ pipe_ws_to_tcp(),
46
+ return_exceptions=True
47
+ )
48
+ except Exception as e:
49
+ logger.error(f"WebSocket connection failed: {e}")
50
+ finally:
51
+ writer.close()
52
+ logger.info("Local TCP connection closed.")
53
+
54
+ async def main():
55
+ server = await asyncio.start_server(handle_client, '127.0.0.1', LOCAL_PORT)
56
+ addr = server.sockets[0].getsockname()
57
+ logger.info(f"Local WebSocket-to-TCP proxy listening on {addr}")
58
+
59
+ async with server:
60
+ await server.serve_forever()
61
+
62
+ if __name__ == '__main__':
63
+ asyncio.run(main())