c02414ea40
Co-authored-by: Lala, Shahd <Shahd.Lala@sybit.de> Reviewed-on: #7
72 lines
2.0 KiB
TypeScript
72 lines
2.0 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
import { Observable } from 'rxjs';
|
|
import { GameStreamEvent, ErrorEvent } from '../models/game.models';
|
|
|
|
const WS_CONNECT_TIMEOUT_MS = 3000;
|
|
|
|
@Injectable({ providedIn: 'root' })
|
|
export class StreamHandlerService {
|
|
createGameStream(wsUrl: string, gameId: string): Observable<GameStreamEvent> {
|
|
return new Observable<GameStreamEvent>((observer) => {
|
|
const ws = new WebSocket(wsUrl);
|
|
let connected = false;
|
|
|
|
const emitErrorEvent = (message: string): void => {
|
|
const errorEvent: ErrorEvent = {
|
|
type: 'error',
|
|
error: { code: 'STREAM_ERROR', message }
|
|
};
|
|
observer.next(errorEvent);
|
|
};
|
|
|
|
const failAndComplete = (reason: string): void => {
|
|
console.warn(`[StreamHandler] WebSocket failed for ${gameId}: ${reason}`);
|
|
emitErrorEvent(reason);
|
|
observer.complete();
|
|
};
|
|
|
|
const connectionTimeoutId = setTimeout(() => {
|
|
if (!connected) {
|
|
ws.close();
|
|
failAndComplete('WebSocket connection timed out — falling back to polling');
|
|
}
|
|
}, WS_CONNECT_TIMEOUT_MS);
|
|
|
|
ws.onopen = () => {
|
|
connected = true;
|
|
clearTimeout(connectionTimeoutId);
|
|
console.log(`[StreamHandler] WebSocket connected for ${gameId}`);
|
|
};
|
|
|
|
ws.onmessage = (message) => {
|
|
const payload = typeof message.data === 'string' ? message.data : '';
|
|
if (!payload.trim()) return;
|
|
try {
|
|
const event = JSON.parse(payload) as GameStreamEvent;
|
|
observer.next(event);
|
|
} catch {
|
|
// ignore malformed frames
|
|
}
|
|
};
|
|
|
|
ws.onerror = () => {
|
|
clearTimeout(connectionTimeoutId);
|
|
if (!connected) {
|
|
failAndComplete('WebSocket connection error — falling back to polling');
|
|
}
|
|
};
|
|
|
|
ws.onclose = () => {
|
|
clearTimeout(connectionTimeoutId);
|
|
if (connected) {
|
|
observer.complete();
|
|
}
|
|
};
|
|
|
|
return () => {
|
|
ws.close();
|
|
};
|
|
});
|
|
}
|
|
}
|