From 26e7a39a61e08e33175cba0658232d97592765e2 Mon Sep 17 00:00:00 2001
From: Audric Ackermann <audric@getsession.org>
Date: Fri, 26 Jul 2024 11:03:28 +1000
Subject: [PATCH] feat: hit only once every 30mins the fs for release

once we've already fetched the latest release
---
 ts/components/leftpane/ActionsPanel.tsx       | 34 +-----------
 .../useFetchLatestReleaseFromFileServer.ts    | 15 +++++
 ts/session/fetch_latest_release/index.ts      | 55 +++++++++++++++++++
 3 files changed, 73 insertions(+), 31 deletions(-)
 create mode 100644 ts/hooks/useFetchLatestReleaseFromFileServer.ts
 create mode 100644 ts/session/fetch_latest_release/index.ts

diff --git a/ts/components/leftpane/ActionsPanel.tsx b/ts/components/leftpane/ActionsPanel.tsx
index 319300713..8fbe069ad 100644
--- a/ts/components/leftpane/ActionsPanel.tsx
+++ b/ts/components/leftpane/ActionsPanel.tsx
@@ -1,7 +1,5 @@
-import { ipcRenderer } from 'electron';
 import React, { useEffect, useState } from 'react';
-
-import { debounce, isEmpty, isString } from 'lodash';
+import { debounce } from 'lodash';
 import { useDispatch, useSelector } from 'react-redux';
 import useInterval from 'react-use/lib/useInterval';
 import useTimeoutFn from 'react-use/lib/useTimeoutFn';
@@ -37,7 +35,7 @@ import { SessionIconButton } from '../icon/SessionIconButton';
 import { LeftPaneSectionContainer } from './LeftPaneSectionContainer';
 
 import { SettingsKey } from '../../data/settings-key';
-import { getLatestReleaseFromFileServer } from '../../session/apis/file_server_api/FileServerApi';
+import { useFetchLatestReleaseFromFileServer } from '../../hooks/useFetchLatestReleaseFromFileServer';
 import {
   forceRefreshRandomSnodePool,
   getFreshSwarmFor,
@@ -144,11 +142,6 @@ const Section = (props: { type: SectionType }) => {
 
 const cleanUpMediasInterval = DURATION.MINUTES * 60;
 
-// every 1 minute we fetch from the fileserver to check for a new release
-// * if there is none, no request to github are made.
-// * if there is a version on the fileserver more recent than our current, we fetch github to get the UpdateInfos and trigger an update as usual (asking user via dialog)
-const fetchReleaseFromFileServerInterval = 1000 * 60; // try to fetch the latest release from the fileserver every minute
-
 const setupTheme = async () => {
   const shouldFollowSystemTheme = window.getSettingValue(SettingsKey.hasFollowSystemThemeEnabled);
   const theme = window.Events.getThemeSetting();
@@ -232,22 +225,6 @@ const doAppStartUp = async () => {
   }, 20000);
 };
 
-async function fetchReleaseFromFSAndUpdateMain() {
-  try {
-    window.log.info('[updater] about to fetchReleaseFromFSAndUpdateMain');
-
-    const latest = await getLatestReleaseFromFileServer();
-    window.log.info('[updater] fetched latest release from fileserver: ', latest);
-
-    if (isString(latest) && !isEmpty(latest)) {
-      ipcRenderer.send('set-release-from-file-server', latest);
-      window.readyForUpdates();
-    }
-  } catch (e) {
-    window.log.warn(e);
-  }
-}
-
 /**
  * ActionsPanel is the far left banner (not the left pane).
  * The panel with buttons to switch between the message/contact/settings/theme views
@@ -272,12 +249,7 @@ export const ActionsPanel = () => {
 
   useInterval(cleanUpOldDecryptedMedias, startCleanUpMedia ? cleanUpMediasInterval : null);
 
-  useInterval(() => {
-    if (!ourPrimaryConversation) {
-      return;
-    }
-    void fetchReleaseFromFSAndUpdateMain();
-  }, fetchReleaseFromFileServerInterval);
+  useFetchLatestReleaseFromFileServer();
 
   useInterval(() => {
     if (!ourPrimaryConversation) {
diff --git a/ts/hooks/useFetchLatestReleaseFromFileServer.ts b/ts/hooks/useFetchLatestReleaseFromFileServer.ts
new file mode 100644
index 000000000..4766954e5
--- /dev/null
+++ b/ts/hooks/useFetchLatestReleaseFromFileServer.ts
@@ -0,0 +1,15 @@
+import { useSelector } from 'react-redux';
+import useInterval from 'react-use/lib/useInterval';
+import { getOurPrimaryConversation } from '../state/selectors/conversations';
+import { fetchLatestRelease } from '../session/fetch_latest_release';
+
+export function useFetchLatestReleaseFromFileServer() {
+  const ourPrimaryConversation = useSelector(getOurPrimaryConversation);
+
+  useInterval(() => {
+    if (!ourPrimaryConversation) {
+      return;
+    }
+    void fetchLatestRelease.fetchReleaseFromFSAndUpdateMain();
+  }, fetchLatestRelease.fetchReleaseFromFileServerInterval);
+}
diff --git a/ts/session/fetch_latest_release/index.ts b/ts/session/fetch_latest_release/index.ts
new file mode 100644
index 000000000..0ecbe7cb8
--- /dev/null
+++ b/ts/session/fetch_latest_release/index.ts
@@ -0,0 +1,55 @@
+// every 1 minute we fetch from the fileserver to check for a new release
+// * if there is none, no request to github are made.
+// * if there is a version on the fileserver more recent than our current, we fetch github to get the UpdateInfos and trigger an update as usual (asking user via dialog)
+
+import { isEmpty, isString } from 'lodash';
+import { ipcRenderer } from 'electron';
+import { DURATION } from '../constants';
+import { getLatestReleaseFromFileServer } from '../apis/file_server_api/FileServerApi';
+
+/**
+ * Try to fetch the latest release from the fileserver every 1 minute.
+ * If we did fetch a release already in the last 30 minutes, we will skip the call.
+ */
+const fetchReleaseFromFileServerInterval = DURATION.MINUTES * 1;
+
+/**
+ * We don't want to hit the fileserver too often. Only often on start, and then every 30 minutes
+ */
+const skipIfLessThan = DURATION.MINUTES * 30;
+
+let lastFetchedTimestamp = Number.MIN_SAFE_INTEGER;
+
+function resetForTesting() {
+  lastFetchedTimestamp = Number.MIN_SAFE_INTEGER;
+}
+
+async function fetchReleaseFromFSAndUpdateMain() {
+  try {
+    window.log.info('[updater] about to fetchReleaseFromFSAndUpdateMain');
+    const diff = Date.now() - lastFetchedTimestamp;
+    if (diff < skipIfLessThan) {
+      window.log.info(
+        `[updater] fetched release from fs ${Math.floor(diff / DURATION.MINUTES)}minutes ago, skipping until that's at least ${Math.floor(skipIfLessThan / DURATION.MINUTES)}`
+      );
+      return;
+    }
+
+    const justFetched = await getLatestReleaseFromFileServer();
+    window.log.info('[updater] fetched latest release from fileserver: ', justFetched);
+
+    if (isString(justFetched) && !isEmpty(justFetched)) {
+      lastFetchedTimestamp = Date.now();
+      ipcRenderer.send('set-release-from-file-server', justFetched);
+      window.readyForUpdates();
+    }
+  } catch (e) {
+    window.log.warn(e);
+  }
+}
+
+export const fetchLatestRelease = {
+  fetchReleaseFromFileServerInterval,
+  fetchReleaseFromFSAndUpdateMain,
+  resetForTesting,
+};