przywrócenie komunikacji po WS (test)

This commit is contained in:
2024-01-30 13:58:47 +01:00
parent f130e6900b
commit c7da8477fa
7 changed files with 286 additions and 253 deletions
+47 -5
View File
@@ -47,6 +47,8 @@ import TrainModal from './components/TrainsView/TrainModal.vue';
import StorageManager from './managers/storageManager';
import { useApiStore } from './store/apiStore';
import { Status } from './typings/common';
import { Websocket } from './typings/api';
import socket from './websocket';
export default defineComponent({
components: {
@@ -86,7 +88,39 @@ export default defineComponent({
this.setReleaseURL();
this.setupOfflineHandling();
this.apiStore.setupAPI();
this.apiStore.setupStaticAPIData();
this.connectToWebsocket();
},
async connectToWebsocket() {
this.apiStore.dataStatuses.connection = Status.Data.Loading;
console.log('ws connecting');
socket.on('connect_error', (err) => {
console.error(`WS connection error: ${err.message}`);
this.apiStore.dataStatuses.connection = Status.Data.Error;
this.apiStore.websocketData = undefined;
});
let timeFrom = Date.now();
socket.on('connect', () => {
socket.emit('CONNECTION', { version: packageInfo.version }, () => {
console.log(`Connection time: ${Date.now() - timeFrom}ms`);
});
console.log('ws connected');
});
socket.on('UPDATE', (data: Websocket.Payload) => {
console.log('ws update');
this.apiStore.websocketData = data;
this.apiStore.dataStatuses.connection = Status.Data.Loaded;
});
this.fetchWebsocketData();
},
setupOfflineHandling() {
@@ -101,16 +135,24 @@ export default defineComponent({
handleOfflineMode() {
this.store.isOffline = true;
this.apiStore.stopActiveDataScheduler();
this.apiStore.activeData = undefined;
this.apiStore.websocketData = undefined;
this.apiStore.dataStatuses.connection = Status.Data.Offline;
},
handleOnlineMode() {
this.store.isOffline = false;
this.apiStore.setupAPI();
this.apiStore.setupStaticAPIData();
this.connectToWebsocket();
},
fetchWebsocketData() {
socket.emit('FETCH_DATA', (data: Websocket.Payload) => {
console.log('ws fetch data');
this.apiStore.websocketData = data;
this.apiStore.dataStatuses.connection = Status.Data.Loaded;
});
},
changeLang(lang: string) {
+7 -68
View File
@@ -1,9 +1,11 @@
import { defineStore } from 'pinia';
import http from '../http';
import { API } from '../typings/api';
import { API, Websocket } from '../typings/api';
import axios from 'axios';
import { Status } from '../typings/common';
import { StationJSONData } from './typings';
import { io } from 'socket.io-client';
import packageInfo from '../../package.json';
export const useApiStore = defineStore('apiStore', {
state: () => ({
@@ -20,43 +22,19 @@ export const useApiStore = defineStore('apiStore', {
donatorsData: [] as API.Donators.Response,
sceneryData: [] as StationJSONData[],
activeDataTimeout: undefined as number | undefined
websocketData: undefined as Websocket.Payload | undefined
// activeDataTimeout: undefined as number | undefined
}),
actions: {
async setupAPI() {
async setupStaticAPIData() {
// Static data
this.fetchStockInfoData();
this.fetchDonatorsData();
this.fetchStationsGeneralInfo();
if (this.activeDataTimeout === undefined) this.startActiveDataScheduler();
},
// async setDataStatuses() {
// if (!window.navigator.onLine) {
// this.dataStatuses.connection = Status.Data.Offline;
// this.dataStatuses.sceneries = Status.Data.Offline;
// this.dataStatuses.trains = Status.Data.Offline;
// this.dataStatuses.dispatchers = Status.Data.Offline;
// this.dataStatuses.timetables = Status.Data.Offline;
// }
// if (!this.activeData?.activeSceneries) {
// this.dataStatuses.connection = Status.Data.Loaded;
// this.dataStatuses.sceneries = Status.Data.Error;
// this.dataStatuses.trains = Status.Data.Error;
// this.dataStatuses.dispatchers = Status.Data.Error;
// return;
// }
// this.dataStatuses.connection = Status.Data.Loaded;
// this.dataStatuses.sceneries = Status.Data.Loaded;
// this.dataStatuses.trains = !this.activeData.trains ? Status.Data.Warning : Status.Data.Loaded;
// this.dataStatuses.dispatchers = Status.Data.Loaded;
// },
async fetchDonatorsData() {
try {
const response = await http.get<API.Donators.Response>('api/getDonators');
@@ -79,45 +57,6 @@ export const useApiStore = defineStore('apiStore', {
}
},
async startActiveDataScheduler() {
if (!window.navigator.onLine) {
this.dataStatuses.connection = Status.Data.Offline;
return;
}
if (import.meta.env.VITE_API_MODE === 'mock') {
const mockActiveData = await import('../data/mockActiveData.json');
this.dataStatuses.connection = Status.Data.Loaded;
this.activeData = mockActiveData;
console.warn('Stacjownik działa w trybie mockowania danych z WS');
return;
}
try {
const data = (await http.get<API.ActiveData.Response>('api/getActiveData')).data;
this.activeData = data;
this.dataStatuses.connection = Status.Data.Loaded;
} catch (error) {
this.dataStatuses.connection = Status.Data.Error;
console.error('Wystąpił błąd podczas pobierania danych online z API!');
} finally {
this.activeDataTimeout = window.setTimeout(
() => {
this.startActiveDataScheduler();
},
~~(1000 * (Math.random() * (25 - 20) + 25))
);
}
},
async stopActiveDataScheduler() {
window.clearTimeout(this.activeDataTimeout);
this.activeDataTimeout = undefined;
},
async fetchStationsGeneralInfo() {
const sceneryData: StationJSONData[] = (await http.get<StationJSONData[]>('api/getSceneries'))
.data;
+3 -94
View File
@@ -34,7 +34,7 @@ export const useMainStore = defineStore('store', {
trainList(): Train[] {
const apiStore = useApiStore();
return (apiStore.activeData?.trains ?? [])
return (apiStore.websocketData?.activeTrains ?? [])
.filter((train) => train.timetable || train.online)
.map((train) => {
const stock = train.stockString.split(';');
@@ -88,9 +88,9 @@ export const useMainStore = defineStore('store', {
const apiStore = useApiStore();
if (state.isOffline) return [];
if (!apiStore.activeData?.activeSceneries) return [];
if (!apiStore.websocketData?.activeSceneries) return [];
return apiStore.activeData?.activeSceneries.reduce((list, scenery) => {
return apiStore.websocketData?.activeSceneries.reduce((list, scenery) => {
if (scenery.isOnline !== 1 && Date.now() - scenery.lastSeen > 1000 * 60 * 2) return list;
if (scenery.dispatcherStatus == Status.ActiveDispatcher.UNKNOWN) return list;
@@ -197,96 +197,5 @@ export const useMainStore = defineStore('store', {
};
});
}
},
actions: {
async processStationsOnlineInfo(activeData: API.ActiveData.Response) {
if (!activeData.activeSceneries) return;
const onlineSceneries = activeData.activeSceneries.reduce((acc, scenery) => {
const savedStation = this.stationList.find((st) => scenery.stationName === st.name);
if (scenery.isOnline !== 1 && Date.now() - scenery.lastSeen > 1000 * 60 * 2) return acc;
if (scenery.dispatcherStatus == Status.ActiveDispatcher.UNKNOWN) return acc;
const station = this.stationList.find((s) => s.name === scenery.stationName);
const scheduledTrains = getScheduledTrains(this.trainList, scenery, station?.generalInfo);
const stationTrains = getStationTrains(
this.trainList,
scheduledTrains,
this.region.id,
scenery
);
// Remove checkpoint duplicates
const uniqueScheduledTrains = scheduledTrains.reduce(
(uniqueList, sTrain) =>
uniqueList.find((v) => v.trainId === sTrain.trainId)
? uniqueList
: [...uniqueList, sTrain],
[] as ScheduledTrain[]
);
const dispatcherTimestamp =
scenery.dispatcherStatus == Status.ActiveDispatcher.NO_LIMIT
? Date.now() + 25500000
: scenery.dispatcherStatus > 5
? scenery.dispatcherStatus
: null;
const onlineInfo = {
name: scenery.stationName,
hash: scenery.stationHash,
region: scenery.region,
maxUsers: scenery.maxUsers,
currentUsers: scenery.currentUsers,
spawns: parseSpawns(scenery.spawnString),
dispatcherName: scenery.dispatcherName,
dispatcherRate: scenery.dispatcherRate,
dispatcherId: scenery.dispatcherId,
dispatcherExp: scenery.dispatcherExp,
dispatcherIsSupporter: scenery.dispatcherIsSupporter,
scheduledTrains: scheduledTrains,
stationTrains: stationTrains,
dispatcherStatus: scenery.dispatcherStatus,
dispatcherTimestamp: dispatcherTimestamp,
isOnline: scenery.isOnline == 1,
scheduledTrainCount: {
all: uniqueScheduledTrains.length,
confirmed: uniqueScheduledTrains.filter((train) => train.stopInfo.confirmed).length,
unconfirmed: uniqueScheduledTrains.filter((train) => !train.stopInfo.confirmed).length
}
};
if (savedStation) savedStation.onlineInfo = onlineInfo;
else
this.stationList.push({
name: onlineInfo.name,
onlineInfo: onlineInfo
});
acc.push(onlineInfo);
return acc;
}, [] as OnlineScenery[]);
// Reset online info of already offline sceneries
this.stationList
.filter(
(station) =>
station.onlineInfo &&
onlineSceneries.findIndex(
(os) => os.region == station.onlineInfo!.region && station.name == os.name
) != -1
)
.forEach((station) => (station.onlineInfo = undefined));
},
async changeRegion(region: StoreState['region']) {
this.region = region;
}
}
});
+8
View File
@@ -368,3 +368,11 @@ export namespace GithubAPI {
}
}
}
export namespace Websocket {
export interface Payload {
activeSceneries: API.ActiveSceneries.Response;
activeTrains: API.ActiveTrains.Response;
connectedSocketCount: number;
}
}
+14
View File
@@ -0,0 +1,14 @@
import { io } from 'socket.io-client';
const URL =
import.meta.env.VITE_WS_MODE === 'development'
? 'http://localhost:3001'
: 'https://stacjownik.spythere.eu';
const socket = io(URL, {
transports: ['websocket', 'polling'],
rememberUpgrade: true,
reconnection: true
});
export default socket;