mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-03-28 03:29:25 +01:00
feat(System): check internet status on backend and allow custom test url
This commit is contained in:
parent
7029e1ea81
commit
a2206b8c13
|
|
@ -11,6 +11,10 @@ export default class SystemController {
|
|||
private dockerService: DockerService
|
||||
) { }
|
||||
|
||||
async getInternetStatus({ }: HttpContext) {
|
||||
return await this.systemService.getInternetStatus();
|
||||
}
|
||||
|
||||
async getSystemInfo({ }: HttpContext) {
|
||||
return await this.systemService.getSystemInfo();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import { NomadDiskInfo, NomadDiskInfoRaw, SystemInformationResponse } from '../.
|
|||
import { readFileSync } from 'fs'
|
||||
import path, { join } from 'path'
|
||||
import { getAllFilesystems, getFile } from '../utils/fs.js'
|
||||
import axios from 'axios'
|
||||
import env from '#start/env'
|
||||
|
||||
@inject()
|
||||
export class SystemService {
|
||||
|
|
@ -16,6 +18,45 @@ export class SystemService {
|
|||
|
||||
constructor(private dockerService: DockerService) {}
|
||||
|
||||
async getInternetStatus(): Promise<boolean> {
|
||||
const DEFAULT_TEST_URL = 'https://1.1.1.1/cdn-cgi/trace'
|
||||
const MAX_ATTEMPTS = 3
|
||||
|
||||
let testUrl = DEFAULT_TEST_URL
|
||||
let customTestUrl = env.get('INTERNET_STATUS_TEST_URL')?.trim()
|
||||
|
||||
// check that customTestUrl is a valid URL, if provided
|
||||
if (customTestUrl && customTestUrl !== '') {
|
||||
try {
|
||||
new URL(customTestUrl)
|
||||
testUrl = customTestUrl
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
`Invalid INTERNET_STATUS_TEST_URL: ${customTestUrl}. Falling back to default URL.`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
||||
try {
|
||||
const res = await axios.get(testUrl, { timeout: 5000 })
|
||||
return res.status === 200
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
`Internet status check attempt ${attempt}/${MAX_ATTEMPTS} failed: ${error instanceof Error ? error.message : error}`
|
||||
)
|
||||
|
||||
if (attempt < MAX_ATTEMPTS) {
|
||||
// delay before next attempt
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.warn('All internet status check attempts failed.')
|
||||
return false
|
||||
}
|
||||
|
||||
async getServices({ installedOnly = true }: { installedOnly?: boolean }): Promise<ServiceSlim[]> {
|
||||
const query = Service.query()
|
||||
.orderBy('friendly_name', 'asc')
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
// Helper hook to check internet connection status
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { testInternetConnection } from '~/lib/util';
|
||||
import api from '~/lib/api';
|
||||
|
||||
const useInternetStatus = () => {
|
||||
const [isOnline, setIsOnline] = useState<boolean>(false);
|
||||
const { data } = useQuery<boolean>({
|
||||
queryKey: ['internetStatus'],
|
||||
queryFn: testInternetConnection,
|
||||
queryFn: async () => (await api.getInternetStatus()) ?? false,
|
||||
refetchOnWindowFocus: false, // Don't refetch on window focus
|
||||
refetchOnReconnect: false, // Refetch when the browser reconnects
|
||||
refetchOnReconnect: true, // Refetch when the browser reconnects
|
||||
refetchOnMount: false, // Don't refetch when the component mounts
|
||||
retry: 2, // Retry up to 2 times on failure
|
||||
staleTime: 1000 * 60 * 10, // Data is fresh for 10 minutes
|
||||
retry: 0, // Retry already handled in backend
|
||||
staleTime: 1000 * 60 * 5, // Data is fresh for 5 minutes
|
||||
});
|
||||
|
||||
// Update the online status when data changes
|
||||
|
|
|
|||
|
|
@ -92,6 +92,13 @@ class API {
|
|||
})()
|
||||
}
|
||||
|
||||
async getInternetStatus() {
|
||||
return catchInternal(async () => {
|
||||
const response = await this.client.get<boolean>('/system/internet-status')
|
||||
return response.data
|
||||
})()
|
||||
}
|
||||
|
||||
async getSystemInfo() {
|
||||
return catchInternal(async () => {
|
||||
const response = await this.client.get<SystemInformationResponse>('/system/info')
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import axios from 'axios'
|
||||
|
||||
export function capitalizeFirstLetter(str?: string | null): string {
|
||||
if (!str) return ''
|
||||
|
|
@ -14,18 +13,6 @@ export function formatBytes(bytes: number, decimals = 2): string {
|
|||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
|
||||
}
|
||||
|
||||
export async function testInternetConnection(): Promise<boolean> {
|
||||
try {
|
||||
const response = await axios.get('https://1.1.1.1/cdn-cgi/trace', {
|
||||
timeout: 5000,
|
||||
})
|
||||
return response.status === 200
|
||||
} catch (error) {
|
||||
console.error('Error testing internet connection:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export function generateRandomString(length: number): string {
|
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
||||
let result = ''
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export default await Env.create(new URL('../', import.meta.url), {
|
|||
HOST: Env.schema.string({ format: 'host' }),
|
||||
URL: Env.schema.string(),
|
||||
LOG_LEVEL: Env.schema.string(),
|
||||
INTERNET_STATUS_TEST_URL: Env.schema.string.optional(),
|
||||
|
||||
/*
|
||||
|----------------------------------------------------------
|
||||
|
|
@ -26,7 +27,6 @@ export default await Env.create(new URL('../', import.meta.url), {
|
|||
*/
|
||||
//SESSION_DRIVER: Env.schema.enum(['cookie', 'memory'] as const),
|
||||
|
||||
|
||||
/*
|
||||
|----------------------------------------------------------
|
||||
| Variables for configuring the database package
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ router
|
|||
router
|
||||
.group(() => {
|
||||
router.get('/info', [SystemController, 'getSystemInfo'])
|
||||
router.get('/internet-status', [SystemController, 'getInternetStatus'])
|
||||
router.get('/services', [SystemController, 'getServices'])
|
||||
router.post('/services/affect', [SystemController, 'affectService'])
|
||||
router.post('/services/install', [SystemController, 'installService'])
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user