Skip to content

Commit 5af29e9

Browse files
committed
Added heartbeat mechanism
1 parent ddcf6ca commit 5af29e9

4 files changed

Lines changed: 78 additions & 11 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,31 +42,63 @@ jobs:
4242
go_url: ${{ steps.deploy-go.outputs.url }}
4343
steps:
4444
- uses: actions/checkout@v4
45+
4546
- uses: google-github-actions/auth@v2
4647
with:
4748
credentials_json: ${{ secrets.GCP_SA_KEY }}
4849

49-
- name: Deploy Python API
50+
- name: Set up Cloud SDK
51+
uses: google-github-actions/setup-gcloud@v2
52+
53+
# 🚨 Authorize Docker to push to your new Artifact Registry
54+
- name: Configure Docker
55+
run: gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
56+
57+
# ---------------------------------------------------
58+
# 🚀 FAST DEPLOY: PYTHON API
59+
# ---------------------------------------------------
60+
- name: Build and Push Python Image
61+
run: |
62+
cd backend-python
63+
IMAGE="us-central1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/watchparty-repo/watchparty-api:latest"
64+
docker build -t $IMAGE .
65+
docker push $IMAGE
66+
67+
- name: Deploy Python to Cloud Run
5068
id: deploy-python
5169
uses: google-github-actions/deploy-cloudrun@v2
5270
with:
5371
service: watchparty-api
5472
region: us-central1
55-
source: ./backend-python
56-
flags: --add-cloudsql-instances=watchparty-482106:us-central1:watchparty-db
73+
# 🚨 Deploy the pre-built image instead of building from source
74+
image: us-central1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/watchparty-repo/watchparty-api:latest
75+
flags: |
76+
--add-cloudsql-instances=watchparty-482106:us-central1:watchparty-db
77+
--port=8080
5778
env_vars: |
5879
DATABASE_URL=${{ secrets.DATABASE_URL }}
5980
JWT_SECRET=${{ secrets.JWT_SECRET }}
6081
GCP_PROJECT_ID=${{ secrets.GCP_PROJECT_ID }}
6182
GOOGLE_CLIENT_ID=${{ secrets.GOOGLE_CLIENT_ID }}
6283
63-
- name: Deploy Go WebSocket
84+
# ---------------------------------------------------
85+
# 🚀 FAST DEPLOY: GO WEBSOCKET
86+
# ---------------------------------------------------
87+
- name: Build and Push Go Image
88+
run: |
89+
cd backend-go
90+
IMAGE="us-central1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/watchparty-repo/watchparty-ws:latest"
91+
docker build -t $IMAGE .
92+
docker push $IMAGE
93+
94+
- name: Deploy Go to Cloud Run
6495
id: deploy-go
6596
uses: google-github-actions/deploy-cloudrun@v2
6697
with:
6798
service: watchparty-ws
6899
region: us-central1
69-
source: ./backend-go
100+
# 🚨 Deploy the pre-built image
101+
image: us-central1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/watchparty-repo/watchparty-ws:latest
70102
env_vars: |
71103
REDIS_ADDR=${{ secrets.REDIS_ADDR }}
72104
JWT_SECRET=${{ secrets.JWT_SECRET }}

backend-go/internal/handlers/websockets.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ func WebSocketHandler(rm domain.RoomManager) http.HandlerFunc {
3535
roomID = "general"
3636
}
3737

38-
// 🚨 SECURE JWT VERIFICATION
3938
secret := os.Getenv("JWT_SECRET")
4039
if secret == "" {
4140
secret = "super-secret-fallback"
@@ -133,6 +132,8 @@ func WebSocketHandler(rm domain.RoomManager) http.HandlerFunc {
133132
}
134133

135134
switch msg.Type {
135+
case "ping":
136+
continue
136137
case "play", "pause", "seek", "sync_state":
137138
if err := rm.HandleVideoCommand(r.Context(), roomID, msg); err != nil {
138139
log.Printf("Failed video command: %v", err)

frontend/wpfe/src/components/Dashboard.jsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,15 @@ const Dashboard = ({ user, onLogout }) => {
4949
useEffect(() => {
5050
if (error && !hasAlerted.current) {
5151
hasAlerted.current = true;
52-
alert(
53-
error === "room_exists" ? "Room name taken!" : "Room does not exist!",
54-
);
52+
53+
let alertMsg = error;
54+
if (error === "room_exists") alertMsg = "Room name taken!";
55+
else if (error === "room_not_found_silent")
56+
alertMsg = "Room does not exist!";
57+
else if (error === "connection_lost")
58+
alertMsg = "Connection lost. Please rejoin.";
59+
60+
alert(alertMsg);
5561
navigate("/");
5662
}
5763
}, [error, navigate]);

frontend/wpfe/src/hooks/useWatchParty.jsx

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ export const useWatchParty = (urlRoom = null, action = "join") => {
4343
const [typingUsers, setTypingUsers] = useState([]);
4444

4545
const playerRef = useRef(null);
46+
const playingRef = useRef(false);
47+
useEffect(() => {
48+
playingRef.current = playing;
49+
}, [playing]);
4650
const ws = useRef(null);
4751
const lastTypingTime = useRef(0);
4852
const typingTimeout = useRef({});
@@ -112,8 +116,15 @@ export const useWatchParty = (urlRoom = null, action = "join") => {
112116

113117
if (msg.type === "request_sync") {
114118
if (isHostRef.current && playerRef.current) {
115-
const currentTime = playerRef.current.getCurrentTime();
116-
sendSignal("sync_state", currentTime);
119+
const currentTime = playerRef.current.getCurrentTime();
120+
ws.current.send(JSON.stringify({
121+
type: "sync_state",
122+
username: usernameRef.current,
123+
room: room,
124+
timestamp: currentTime,
125+
video_id: currentVideoRef.current ? currentVideoRef.current.id : 0,
126+
content: playingRef.current ? "playing" : "paused"
127+
}));
117128
}
118129
return;
119130
}
@@ -384,6 +395,23 @@ export const useWatchParty = (urlRoom = null, action = "join") => {
384395
);
385396
};
386397

398+
const heartbeat = setInterval(() => {
399+
if (ws.current?.readyState === WebSocket.OPEN) {
400+
ws.current.send(JSON.stringify({
401+
type: "ping",
402+
username: username,
403+
room: room
404+
}));
405+
}
406+
}, 25000);
407+
408+
return () => {
409+
clearInterval(heartbeat);
410+
intentionalClose.current = true;
411+
if (ws.current) ws.current.close();
412+
};
413+
}, [room, username, action]);
414+
387415
return () => {
388416
intentionalClose.current = true;
389417
if (ws.current) ws.current.close();

0 commit comments

Comments
 (0)