Browse Source

server check

Viktoriia 1 year ago
parent
commit
fba82da626

+ 16 - 2
Route.tsx

@@ -55,6 +55,8 @@ import TabBarButton from './src/components/TabBarButton';
 import { ParamListBase, RouteProp } from '@react-navigation/native';
 import setupDatabaseAndSync from 'src/database';
 import { MenuDrawer } from 'src/components';
+import { setFastestMapHost } from 'src/constants';
+import { determineFastestServer } from 'src/utils/determineServer';
 
 const ScreenStack = createStackNavigator();
 const BottomTab = createBottomTabNavigator();
@@ -73,27 +75,39 @@ const Route = () => {
     'montserrat-400': require('./assets/fonts/Montserrat-Regular.ttf'),
   });
   const [dbLoaded, setDbLoaded] = useState(false);
+  const [serverReady, setServerReady] = useState(false);
 
   useEffect(() => {
     const prepareApp = async () => {
       // checkTokenAndUpdate();
+      await findFastestServer();
       await openDatabases();
       setDbLoaded(true);
+      setServerReady(true);
       await setupDatabaseAndSync();
     };
 
+    const findFastestServer = async () => {
+      try {
+        const fastest = await determineFastestServer();
+        setFastestMapHost(fastest);
+      } catch (error) {
+        console.error('Error finding fastest server:', error);
+      }
+    };
+
     prepareApp();
   }, []);
 
   useEffect(() => {
     const hideSplashScreen = async () => {
-      if (fontsLoaded && dbLoaded) {
+      if (fontsLoaded && dbLoaded && serverReady) {
         await SplashScreen.hideAsync();
       }
     };
 
     hideSplashScreen();
-  }, [fontsLoaded, dbLoaded]);
+  }, [fontsLoaded, dbLoaded, serverReady]);
 
   const checkTokenAndUpdate = async () => {
     const storedToken = storage.get('deviceToken', StoreType.STRING);

+ 6 - 0
src/constants/secrets.ts

@@ -6,3 +6,9 @@ export const API_HOST = extra?.API_HOST || Constants?.expoConfig?.extra?.API_HOS
 export const MAP_HOST = extra?.MAP_HOST || Constants?.expoConfig?.extra?.MAP_HOST;
 
 export const API_URL = `${API_HOST}/webapi`;
+
+export let FASTEST_MAP_HOST: string = MAP_HOST;
+
+export const setFastestMapHost = (server: string | null) => {
+  FASTEST_MAP_HOST = server ?? MAP_HOST;
+};

+ 2 - 2
src/database/tilesService/index.ts

@@ -1,7 +1,7 @@
 import * as FileSystem  from 'expo-file-system';
+import { FASTEST_MAP_HOST } from 'src/constants';
 
 const baseTilesDir = `${FileSystem.cacheDirectory}tiles/`;
-const MAP_HOST = 'https://maps.nomadmania.eu';
 
 interface TileType {
   url: string;
@@ -19,7 +19,7 @@ async function ensureDirExists(dirPath: string): Promise<void> {
 
 async function downloadTile(z: number, x: number, y: number, tile: TileType): Promise<void> {
   try {
-    const tileUrl = `${MAP_HOST}${tile.url}/${z}/${x}/${y}`;
+    const tileUrl = `${FASTEST_MAP_HOST}${tile.url}/${z}/${x}/${y}`;
     const filePath = `${baseTilesDir}${tile.type}/${z}/${x}/${y}`;
     await FileSystem.downloadAsync(tileUrl, filePath);
 

+ 6 - 8
src/screens/InAppScreens/MapScreen/index.tsx

@@ -32,7 +32,7 @@ import { fetchSeriesData, usePostSetToggleItem } from '@api/series';
 import MarkerItem from './MarkerItem';
 import ClusterItem from './ClusterItem';
 import { FeatureCollection, ItemSeries, MapScreenProps, Region, Series } from '../../../types/map';
-import { MAP_HOST } from 'src/constants';
+import { FASTEST_MAP_HOST } from 'src/constants';
 import { useConnection } from 'src/contexts/ConnectionContext';
 import ClusteredMapView from 'react-native-map-clustering';
 import { fetchUserData, fetchUserDataDare } from '@api/regions';
@@ -42,20 +42,18 @@ import { usePostSetDareRegionMutation } from '@api/myDARE';
 import moment from 'moment';
 import { qualityOptions } from '../TravelsScreen/utils/constants';
 
-const tilesBaseURL = `${MAP_HOST}/tiles_osm`;
 const localTileDir = `${FileSystem.cacheDirectory}tiles/background`;
-
-const gridUrl = `${MAP_HOST}/tiles_nm/grid`;
 const localGridDir = `${FileSystem.cacheDirectory}tiles/grid`;
-
 const localVisitedDir = `${FileSystem.cacheDirectory}tiles/user_visited`;
-
-const dareTiles = `${MAP_HOST}/tiles_nm/regions_mqp`;
 const localDareDir = `${FileSystem.cacheDirectory}tiles/regions_mqp`;
 
 const AnimatedMarker = Animated.createAnimatedComponent(Marker);
 
 const MapScreen: React.FC<MapScreenProps> = ({ navigation }) => {
+  const tilesBaseURL = `${FASTEST_MAP_HOST}/tiles_osm`;
+  const gridUrl = `${FASTEST_MAP_HOST}/tiles_nm/grid`;
+  const dareTiles = `${FASTEST_MAP_HOST}/tiles_nm/regions_mqp`;
+
   const userId = storage.get('uid', StoreType.STRING);
   const token = storage.get('token', StoreType.STRING) as string;
   const netInfo = useConnection();
@@ -66,7 +64,7 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation }) => {
   const { mutate: updateSeriesItem } = usePostSetToggleItem();
   const { mutate: updateNM } = usePostSetNmRegionMutation();
   const { mutate: updateDARE } = usePostSetDareRegionMutation();
-  const visitedTiles = `${MAP_HOST}/tiles_nm/user_visited/${userId}`;
+  const visitedTiles = `${FASTEST_MAP_HOST}/tiles_nm/user_visited/${userId}`;
   const mapRef = useRef<MapView>(null);
 
   const [isConnected, setIsConnected] = useState<boolean | null>(true);

+ 3 - 3
src/screens/InAppScreens/TravelsScreen/AddRegionsScreen/index.tsx

@@ -7,7 +7,7 @@ import { useNavigation } from '@react-navigation/native';
 
 import { Header, Modal, FlatList as List } from 'src/components';
 
-import { MAP_HOST } from 'src/constants';
+import { FASTEST_MAP_HOST } from 'src/constants';
 import { Colors } from 'src/theme';
 import { findRegionInDataset } from 'src/utils/mapHelpers';
 import { calculateMapRegion } from '../utils/calculateRegion';
@@ -238,14 +238,14 @@ const AddRegionsScreen = ({ route }: { route: any }) => {
           onPress={handleMapPress}
         >
           <UrlTile
-            urlTemplate={`${MAP_HOST}/tiles_osm/{z}/{x}/{y}`}
+            urlTemplate={`${FASTEST_MAP_HOST}/tiles_osm/{z}/{x}/{y}`}
             maximumZ={15}
             maximumNativeZ={13}
             shouldReplaceMapContent
             minimumZ={0}
           />
           <UrlTile
-            urlTemplate={`${MAP_HOST}/tiles_nm/grid/{z}/{x}/{y}`}
+            urlTemplate={`${FASTEST_MAP_HOST}/tiles_nm/grid/{z}/{x}/{y}`}
             maximumZ={15}
             maximumNativeZ={13}
             shouldReplaceMapContent

+ 2 - 2
src/screens/InAppScreens/TravelsScreen/EarthScreen/index.tsx

@@ -8,7 +8,7 @@ import { useGetKyeQuery, usePostSetKye } from '@api/travels';
 import { StoreType, storage } from 'src/storage';
 
 import { FeatureCollection } from '@turf/turf';
-import { MAP_HOST } from 'src/constants';
+import { FASTEST_MAP_HOST } from 'src/constants';
 import { styles } from './styles';
 
 interface PropertiesData {
@@ -175,7 +175,7 @@ const EarthScreen = () => {
           }}
         >
           <UrlTile
-            urlTemplate={`${MAP_HOST}/tiles_osm/{z}/{x}/{y}`}
+            urlTemplate={`${FASTEST_MAP_HOST}/tiles_osm/{z}/{x}/{y}`}
             maximumZ={15}
             maximumNativeZ={13}
             shouldReplaceMapContent

+ 4 - 2
src/types/api.ts

@@ -80,7 +80,8 @@ export enum API_ENDPOINT {
   GET_USER_DATA_DARE = 'get-user-data-dare-app',
   DELETE_USER = 'delete-user',
   GET_LAST_REGIONS_UPDATE = 'last-regions-db-update',
-  GET_LAST_DARE_UPDATE = 'last-dare-db-update'
+  GET_LAST_DARE_UPDATE = 'last-dare-db-update',
+  GET_SERVERS = 'get-servers'
 }
 
 export enum API {
@@ -144,7 +145,8 @@ export enum API {
   GET_USER_DATA_DARE = `${API_ROUTE.REGIONS}/${API_ENDPOINT.GET_USER_DATA_DARE}`,
   DELETE_USER = `${API_ROUTE.APP}/${API_ENDPOINT.DELETE_USER}`,
   GET_LAST_REGIONS_DB_UPDATE = `${API_ROUTE.APP}/${API_ENDPOINT.GET_LAST_REGIONS_UPDATE}`,
-  GET_LAST_DARE_DB_UPDATE = `${API_ROUTE.APP}/${API_ENDPOINT.GET_LAST_DARE_UPDATE}`
+  GET_LAST_DARE_DB_UPDATE = `${API_ROUTE.APP}/${API_ENDPOINT.GET_LAST_DARE_UPDATE}`,
+  GET_SERVERS = `${API_ROUTE.APP}/${API_ENDPOINT.GET_SERVERS}`
 }
 
 export type BaseAxiosError = AxiosError;

+ 52 - 0
src/utils/determineServer.ts

@@ -0,0 +1,52 @@
+import axios from 'axios';
+import { API_URL } from 'src/constants';
+import { API } from 'src/types';
+
+const SERVER_LIST_URL = API_URL + '/' + API.GET_SERVERS;
+const TIMEOUT = 1500;
+
+const fetchWithTimeout = (url: string, timeout = TIMEOUT) => {
+  return axios.get(url, { timeout });
+};
+
+const testServerSpeed = async (serverUrl: string) => {
+  const startTime = Date.now();
+  try {
+    await fetchWithTimeout(serverUrl);
+    const endTime = Date.now();
+    return endTime - startTime;
+  } catch (error) {
+    console.error(`Error fetching ${serverUrl}:`, error);
+    return TIMEOUT;
+  }
+};
+
+export const determineFastestServer = async () => {
+  try {
+    const response = await axios.get(SERVER_LIST_URL);
+    const servers = response.data?.maps;
+
+    const speedTests = await Promise.allSettled(
+      servers?.map((server: string) => testServerSpeed(server + '/tiles_osm/2/2/2'))
+    );
+
+    let fastestServer = null;
+    let fastestTime = TIMEOUT;
+
+    speedTests.forEach((result, index) => {
+      if (result.status === 'fulfilled' && result.value < fastestTime) {
+        fastestTime = result.value;
+        fastestServer = servers[index];
+      }
+    });
+
+    if (fastestServer) {
+      return fastestServer;
+    } else {
+      return null;
+    }
+  } catch (error) {
+    console.error('Error determining fastest server:', error);
+    throw error;
+  }
+};