feat: Refactor S3 last modified endpoint and Dashboard data fetching to handle errors gracefully
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 6m7s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 6m7s
This commit is contained in:
+29
-9
@@ -436,22 +436,42 @@ app.post('/api/filters', async (req, res) => {
|
||||
// Новый эндпоинт для получения дат последнего изменения файлов S3
|
||||
app.get('/api/s3/last-modified', async (req, res) => {
|
||||
try {
|
||||
const [domainsHead, domainsNewHead, asnsHead, serversHead, filtersHead] = await Promise.all([
|
||||
const results = await Promise.allSettled([
|
||||
s3.headObject({ Bucket: BUCKET_NAME, Key: 'bgp_data/domains.txt' }).promise(),
|
||||
s3.headObject({ Bucket: BUCKET_NAME, Key: 'bgp_data/domains_community.txt' }).promise(),
|
||||
s3.headObject({ Bucket: BUCKET_NAME, Key: 'bgp_data/asns.txt' }).promise(),
|
||||
s3.headObject({ Bucket: BUCKET_NAME, Key: 'servers.json' }).promise(),
|
||||
s3.headObject({ Bucket: BUCKET_NAME, Key: 'filters.json' }).promise()
|
||||
]);
|
||||
res.json({
|
||||
domainsLastModified: domainsHead.LastModified ? domainsHead.LastModified.toISOString() : null,
|
||||
domainsNewLastModified: domainsNewHead.LastModified ? domainsNewHead.LastModified.toISOString() : null,
|
||||
asnsLastModified: asnsHead.LastModified ? asnsHead.LastModified.toISOString() : null,
|
||||
serversLastModified: serversHead.LastModified ? serversHead.LastModified.toISOString() : null,
|
||||
filtersLastModified: filtersHead.LastModified ? filtersHead.LastModified.toISOString() : null
|
||||
});
|
||||
|
||||
const response = {
|
||||
domainsLastModified: null,
|
||||
domainsNewLastModified: null,
|
||||
asnsLastModified: null,
|
||||
serversLastModified: null,
|
||||
filtersLastModified: null
|
||||
};
|
||||
|
||||
// Обрабатываем результаты
|
||||
if (results[0].status === 'fulfilled') {
|
||||
response.domainsLastModified = results[0].value.LastModified ? results[0].value.LastModified.toISOString() : null;
|
||||
}
|
||||
if (results[1].status === 'fulfilled') {
|
||||
response.domainsNewLastModified = results[1].value.LastModified ? results[1].value.LastModified.toISOString() : null;
|
||||
}
|
||||
if (results[2].status === 'fulfilled') {
|
||||
response.asnsLastModified = results[2].value.LastModified ? results[2].value.LastModified.toISOString() : null;
|
||||
}
|
||||
if (results[3].status === 'fulfilled') {
|
||||
response.serversLastModified = results[3].value.LastModified ? results[3].value.LastModified.toISOString() : null;
|
||||
}
|
||||
if (results[4].status === 'fulfilled') {
|
||||
response.filtersLastModified = results[4].value.LastModified ? results[4].value.LastModified.toISOString() : null;
|
||||
}
|
||||
|
||||
res.json(response);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error('Error fetching last modified dates from S3:', error);
|
||||
res.status(500).send('Error fetching last modified dates from S3');
|
||||
}
|
||||
});
|
||||
|
||||
+31
-12
@@ -78,7 +78,8 @@ function Dashboard() {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const [domainsRes, ipRangesRes, asnsRes, serversRes, s3Res] = await Promise.all([
|
||||
// Загружаем данные с обработкой ошибок для каждого endpoint
|
||||
const results = await Promise.allSettled([
|
||||
axios.get('/api/domains'),
|
||||
axios.get('/api/ip-ranges'),
|
||||
axios.get('/api/asns'),
|
||||
@@ -86,25 +87,43 @@ function Dashboard() {
|
||||
axios.get('/api/s3/last-modified')
|
||||
]);
|
||||
|
||||
// Подсчет уникальных стран и провайдеров из серверов
|
||||
const servers = serversRes.data;
|
||||
// Обрабатываем результаты
|
||||
const domainsRes = results[0];
|
||||
const ipRangesRes = results[1];
|
||||
const asnsRes = results[2];
|
||||
const serversRes = results[3];
|
||||
const s3Res = results[4];
|
||||
|
||||
// Получаем данные серверов для подсчета дополнительной статистики
|
||||
const servers = serversRes.status === 'fulfilled' ? serversRes.value.data : [];
|
||||
const countries = new Set(servers.map(server => server.country).filter(Boolean));
|
||||
const providers = new Set(servers.map(server => server.provider).filter(Boolean));
|
||||
const onlineServers = servers.filter(server => server.status === 'Онлайн').length;
|
||||
|
||||
// Получаем дату последнего обновления
|
||||
const lastModified = s3Res.status === 'fulfilled' && s3Res.value.data?.domainsLastModified
|
||||
? new Date(s3Res.value.data.domainsLastModified).toLocaleString()
|
||||
: new Date().toLocaleString();
|
||||
|
||||
setStats({
|
||||
domainsCount: domainsRes.data.length,
|
||||
ipRangesCount: ipRangesRes.data.length,
|
||||
asnsCount: asnsRes.data.length,
|
||||
domainsCount: domainsRes.status === 'fulfilled' ? domainsRes.value.data.length : 0,
|
||||
ipRangesCount: ipRangesRes.status === 'fulfilled' ? ipRangesRes.value.data.length : 0,
|
||||
asnsCount: asnsRes.status === 'fulfilled' ? asnsRes.value.data.length : 0,
|
||||
serversCount: servers.length,
|
||||
lastModified: s3Res.data?.domainsLastModified || null,
|
||||
lastModified,
|
||||
countriesCount: countries.size,
|
||||
providersCount: providers.size,
|
||||
onlineServers,
|
||||
totalServers: servers.length
|
||||
});
|
||||
|
||||
// Проверяем, есть ли ошибки
|
||||
const errors = results.filter(result => result.status === 'rejected');
|
||||
if (errors.length > 0) {
|
||||
console.warn('Некоторые API недоступны:', errors.map(e => e.reason?.message));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Ошибка загрузки статистики:', e);
|
||||
console.error('Критическая ошибка загрузки статистики:', e);
|
||||
setError('Не удалось загрузить статистику');
|
||||
setStats({
|
||||
domainsCount: null,
|
||||
@@ -250,11 +269,11 @@ function Dashboard() {
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<MetricCard
|
||||
title="База данных"
|
||||
value="ОК"
|
||||
title="API статус"
|
||||
value={loading ? '...' : (error ? 'Ошибка' : 'ОК')}
|
||||
icon={IconDatabase}
|
||||
color="success"
|
||||
description="Все системы в норме"
|
||||
color={loading ? 'secondary' : (error ? 'danger' : 'success')}
|
||||
description={error ? 'Проблемы с подключением' : 'Все API работают'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user