@coopenomics/desktop 2025.11.28-alpha-2 → 2025.11.29-alpha-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coopenomics/desktop",
3
- "version": "2025.11.28-alpha-2",
3
+ "version": "2025.11.29-alpha-1",
4
4
  "description": "A Desktop Project",
5
5
  "productName": "Desktop App",
6
6
  "author": "Alex Ant <dacom.dark.sun@gmail.com>",
@@ -25,9 +25,9 @@
25
25
  "start": "node -r ./alias-resolver.js dist/ssr/index.js"
26
26
  },
27
27
  "dependencies": {
28
- "@coopenomics/controller": "2025.11.28-alpha-2",
29
- "@coopenomics/notifications": "2025.11.28-alpha-2",
30
- "@coopenomics/sdk": "2025.11.28-alpha-2",
28
+ "@coopenomics/controller": "2025.11.29-alpha-1",
29
+ "@coopenomics/notifications": "2025.11.29-alpha-1",
30
+ "@coopenomics/sdk": "2025.11.29-alpha-1",
31
31
  "@dicebear/collection": "^9.0.1",
32
32
  "@dicebear/core": "^9.0.1",
33
33
  "@editorjs/code": "^2.9.3",
@@ -59,7 +59,7 @@
59
59
  "@wharfkit/wallet-plugin-privatekey": "^1.1.0",
60
60
  "axios": "^1.2.1",
61
61
  "compression": "^1.7.4",
62
- "cooptypes": "2025.11.28-alpha-2",
62
+ "cooptypes": "2025.11.29-alpha-1",
63
63
  "dompurify": "^3.1.7",
64
64
  "dotenv": "^16.4.5",
65
65
  "email-regex": "^5.0.0",
@@ -123,5 +123,5 @@
123
123
  "npm": ">= 6.13.4",
124
124
  "yarn": ">= 1.21.1"
125
125
  },
126
- "gitHead": "83d4bd88cf24e5131c2808239f8d364529f1ff02"
126
+ "gitHead": "e4d0781eb86ea8e54d7b01533b689f47ea086ef7"
127
127
  }
@@ -6,6 +6,11 @@ import { Zeus } from '@coopenomics/sdk';
6
6
 
7
7
  const namespace = 'systemStore';
8
8
 
9
+ // Константы для экспоненциального backoff
10
+ const BASE_INTERVAL_MS = 30000; // Базовый интервал 30 секунд (было 10)
11
+ const MAX_INTERVAL_MS = 300000; // Максимальный интервал 5 минут
12
+ const BACKOFF_MULTIPLIER = 2; // Множитель для backoff
13
+
9
14
  interface ISystemStore {
10
15
  info: Ref<ISystemInfo>;
11
16
  backendAvailable: Ref<boolean>;
@@ -21,44 +26,96 @@ export const useSystemStore = defineStore(namespace, (): ISystemStore => {
21
26
  } as ISystemInfo);
22
27
  const backendAvailable = ref<boolean>(true);
23
28
  const maintenanceCounter = ref<number>(0); // Счетчик для принудительного обновления
24
- let monitoringInterval: ReturnType<typeof setInterval> | null = null;
29
+
30
+ let monitoringTimeout: ReturnType<typeof setTimeout> | null = null;
31
+ let isLoading = false; // Защита от конкурентных запросов
32
+ let currentInterval = BASE_INTERVAL_MS; // Текущий интервал (для backoff)
33
+ let consecutiveErrors = 0; // Счетчик последовательных ошибок
25
34
 
26
35
  const loadSystemInfo = async () => {
36
+ // Защита от конкурентных запросов
37
+ if (isLoading) {
38
+ console.debug('loadSystemInfo: запрос уже выполняется, пропускаем');
39
+ return;
40
+ }
41
+
42
+ isLoading = true;
27
43
  try {
28
44
  info.value = await api.loadSystemInfo();
29
45
  backendAvailable.value = true;
30
46
  triggerRef(info); // Принудительно триггерим реактивность
47
+
48
+ // При успехе сбрасываем backoff
49
+ consecutiveErrors = 0;
50
+ currentInterval = BASE_INTERVAL_MS;
31
51
  } catch (error) {
32
52
  console.warn('Failed to load system info, backend might be unavailable:', error);
33
53
  backendAvailable.value = false;
34
54
  // При недоступности бэкенда устанавливаем статус обслуживания
35
55
  info.value.system_status = Zeus.SystemStatus.maintenance;
56
+
57
+ // Увеличиваем интервал при ошибках (экспоненциальный backoff)
58
+ consecutiveErrors++;
59
+ currentInterval = Math.min(
60
+ BASE_INTERVAL_MS * Math.pow(BACKOFF_MULTIPLIER, consecutiveErrors),
61
+ MAX_INTERVAL_MS
62
+ );
63
+ console.debug(`Backoff: следующая попытка через ${currentInterval / 1000} секунд`);
64
+
36
65
  throw error; // Перебрасываем ошибку для обработки выше
66
+ } finally {
67
+ isLoading = false;
37
68
  }
38
69
  };
39
70
 
40
- const startSystemMonitoring = () => {
41
- // Останавливаем существующий мониторинг, если он есть
71
+ const scheduleNextCheck = () => {
72
+ // КРИТИЧНО: Не запускаем мониторинг на сервере (SSR)
73
+ // В SSR setInterval/setTimeout создают утечки памяти и накапливают запросы
74
+ if (typeof window === 'undefined') {
75
+ return;
76
+ }
77
+
42
78
  stopSystemMonitoring();
43
79
 
44
- // Запускаем периодическую проверку каждые 10 секунд
45
- monitoringInterval = setInterval(async () => {
80
+ monitoringTimeout = setTimeout(async () => {
46
81
  try {
47
82
  await loadSystemInfo();
48
83
  } catch (error) {
49
84
  console.warn('Failed to update system info during monitoring:', error);
50
85
  // При недоступности бэкенда устанавливаем статус обслуживания
51
86
  backendAvailable.value = false;
52
- info.value.system_status = Zeus.SystemStatus.maintenance; // Обновляем статус напрямую
87
+ info.value.system_status = Zeus.SystemStatus.maintenance;
53
88
  maintenanceCounter.value++; // Увеличиваем счетчик для триггера watch
54
89
  }
55
- }, 10000);
90
+
91
+ // Планируем следующую проверку с учетом возможного backoff
92
+ scheduleNextCheck();
93
+ }, currentInterval);
94
+ };
95
+
96
+ const startSystemMonitoring = () => {
97
+ // КРИТИЧНО: Не запускаем мониторинг на сервере (SSR)
98
+ // Это предотвращает утечку таймеров и самоDDoS
99
+ if (typeof window === 'undefined') {
100
+ console.debug('startSystemMonitoring: пропускаем на сервере (SSR)');
101
+ return;
102
+ }
103
+
104
+ // Останавливаем существующий мониторинг, если он есть
105
+ stopSystemMonitoring();
106
+
107
+ // Сбрасываем backoff при явном старте мониторинга
108
+ consecutiveErrors = 0;
109
+ currentInterval = BASE_INTERVAL_MS;
110
+
111
+ // Используем setTimeout вместо setInterval для гибкого управления интервалом
112
+ scheduleNextCheck();
56
113
  };
57
114
 
58
115
  const stopSystemMonitoring = () => {
59
- if (monitoringInterval) {
60
- clearInterval(monitoringInterval);
61
- monitoringInterval = null;
116
+ if (monitoringTimeout) {
117
+ clearTimeout(monitoringTimeout);
118
+ monitoringTimeout = null;
62
119
  }
63
120
  };
64
121
 
@@ -8,19 +8,30 @@ import { useInitExtensionsProcess } from 'src/processes/init-installed-extension
8
8
  import { applyThemeFromStorage } from 'src/shared/lib/utils';
9
9
  import { useSessionStore } from 'src/entities/Session';
10
10
 
11
+ // Проверка, работаем ли мы на сервере (SSR)
12
+ const isServer = typeof window === 'undefined';
13
+
11
14
  export async function useInitAppProcess(router: Router) {
12
15
  applyThemeFromStorage();
13
16
  const system = useSystemStore();
14
17
 
15
- try {
16
- await system.loadSystemInfo();
17
- } catch (error) {
18
- console.warn('Failed to load initial system info, backend might be unavailable:', error);
19
- // Продолжаем инициализацию даже при недоступности бэкенда
18
+ // Загружаем системную информацию только на клиенте
19
+ // На сервере SSR это создает лишнюю нагрузку и задержку рендеринга
20
+ if (!isServer) {
21
+ try {
22
+ await system.loadSystemInfo();
23
+ } catch (error) {
24
+ console.warn('Failed to load initial system info, backend might be unavailable:', error);
25
+ // Продолжаем инициализацию даже при недоступности бэкенда
26
+ }
20
27
  }
21
28
 
22
29
  // Запускаем мониторинг системной информации для отслеживания статуса
23
- system.startSystemMonitoring();
30
+ // Метод startSystemMonitoring сам проверяет SSR, но явная проверка здесь
31
+ // делает код более понятным и предотвращает лишние вызовы
32
+ if (!isServer) {
33
+ system.startSystemMonitoring();
34
+ }
24
35
 
25
36
  const desktops = useDesktopStore();
26
37