6d1e06dfd6
Co-authored-by: shahdlala66 <shahd.lala66@gmail.com> Co-authored-by: Lala, Shahd <Shahd.Lala@sybit.de> Reviewed-on: #6
74 lines
2.2 KiB
TypeScript
74 lines
2.2 KiB
TypeScript
import { Injectable, DestroyRef, inject } from '@angular/core';
|
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
import { interval, startWith, Subscription, switchMap } from 'rxjs';
|
|
import { GameApiService } from './game-api.service';
|
|
import { GameStreamEvent } from '../models/game.models';
|
|
|
|
@Injectable({ providedIn: 'root' })
|
|
export class GameStreamService {
|
|
private readonly gameApi = inject(GameApiService);
|
|
private readonly destroyRef = inject(DestroyRef);
|
|
private streamSubscription: Subscription | null = null;
|
|
private pollSubscription: Subscription | null = null;
|
|
private lastGameStateHash: string | null = null;
|
|
|
|
startStreaming(
|
|
gameId: string,
|
|
onEvent: (event: GameStreamEvent) => void,
|
|
onStreamError: () => void
|
|
): void {
|
|
this.streamSubscription = this.gameApi
|
|
.streamGame(gameId)
|
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
.subscribe({
|
|
next: (event) => {
|
|
this.lastGameStateHash = JSON.stringify(event);
|
|
onEvent(event);
|
|
},
|
|
error: () => {
|
|
onStreamError();
|
|
this.startPolling(gameId, onEvent);
|
|
},
|
|
complete: () => {
|
|
onStreamError();
|
|
this.startPolling(gameId, onEvent);
|
|
}
|
|
});
|
|
}
|
|
|
|
startPolling(gameId: string, onEvent: (event: GameStreamEvent) => void): void {
|
|
if (this.pollSubscription) {
|
|
return;
|
|
}
|
|
|
|
this.pollSubscription = interval(5000)
|
|
.pipe(
|
|
startWith(0),
|
|
switchMap(() => this.gameApi.getGame(gameId)),
|
|
takeUntilDestroyed(this.destroyRef)
|
|
)
|
|
.subscribe({
|
|
next: (game) => {
|
|
// Only emit if game state changed to avoid unnecessary updates
|
|
const stateHash = JSON.stringify(game.state);
|
|
if (this.lastGameStateHash !== stateHash) {
|
|
this.lastGameStateHash = stateHash;
|
|
const event: GameStreamEvent = {
|
|
type: 'gameFull',
|
|
game
|
|
};
|
|
onEvent(event);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
cleanup(): void {
|
|
this.streamSubscription?.unsubscribe();
|
|
this.pollSubscription?.unsubscribe();
|
|
this.streamSubscription = null;
|
|
this.pollSubscription = null;
|
|
this.lastGameStateHash = null;
|
|
}
|
|
}
|