From deb5b3d025ee42a78816b5a57489722239bbbbeb Mon Sep 17 00:00:00 2001
From: James Andariese
Date: Sun, 27 Feb 2022 02:17:48 -0600
Subject: Add configurable hibernation interval after auto-wakeup (#2422)
---
.../settings/settings/EditSettingsForm.js | 2 +
src/config.ts | 13 +++++
src/containers/settings/EditSettingsScreen.js | 27 +++++++++++
src/i18n/locales/en-US.json | 2 +
src/stores/ServicesStore.js | 56 ++++++++++++++++++++--
5 files changed, 96 insertions(+), 4 deletions(-)
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index bdb8484d4..c92bde346 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -424,6 +424,8 @@ class EditSettingsForm extends Component {
+
+
diff --git a/src/config.ts b/src/config.ts
index 5c9fbaee4..3dbcd809b 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -58,6 +58,17 @@ export const WAKE_UP_STRATEGIES = {
3600: 'Wake up after 1hour',
};
+export const WAKE_UP_HIBERNATION_STRATEGIES = {
+ 0: 'Use main hibernation strategy',
+ 10: 'Extremely Fast Hibernation (10sec)',
+ 30: 'Very Fast Hibernation (30sec)',
+ 60: 'Fast Hibernation (1min)',
+ 300: 'Normal Hibernation (5min)',
+ 600: 'Slow Hibernation (10min)',
+ 1800: 'Very Slow Hibernation (30min)',
+ 3600: 'Extremely Slow Hibernation (1hour)',
+};
+
export const NAVIGATION_BAR_BEHAVIOURS = {
custom: 'Show navigation bar on custom websites only',
always: 'Show navigation bar on all services',
@@ -217,6 +228,8 @@ export const DEFAULT_APP_SETTINGS = {
hibernateOnStartup: true,
hibernationStrategy: '300', // seconds
wakeUpStrategy: '300', // seconds
+ wakeUpHibernationStrategy: '0', // seconds -- 0 means do the same as hibernationStrategy
+ wakeUpHibernationSplay: true,
inactivityLock: 0,
automaticUpdates: true,
universalDarkMode: true,
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js
index eff5f20ff..6e405cd92 100644
--- a/src/containers/settings/EditSettingsScreen.js
+++ b/src/containers/settings/EditSettingsScreen.js
@@ -20,6 +20,7 @@ import {
DEFAULT_SETTING_KEEP_ALL_WORKSPACES_LOADED,
DEFAULT_IS_FEATURE_ENABLED_BY_USER,
WAKE_UP_STRATEGIES,
+ WAKE_UP_HIBERNATION_STRATEGIES,
SPLIT_COLUMNS_MIN,
SPLIT_COLUMNS_MAX,
} from '../../config';
@@ -115,6 +116,14 @@ const messages = defineMessages({
id: 'settings.app.form.wakeUpStrategy',
defaultMessage: 'Wake up strategy',
},
+ wakeUpHibernationStrategy: {
+ id: 'settings.app.form.wakeUpHibernationStrategy',
+ defaultMessage: 'Hibernation strategy after automatic wake up',
+ },
+ wakeUpHibernationSplay: {
+ id: 'settings.app.form.wakeUpHibernationSplay',
+ defaultMessage: 'Splay hibernate/wake cycles to reduce load',
+ },
predefinedTodoServer: {
id: 'settings.app.form.predefinedTodoServer',
defaultMessage: 'Todo Server',
@@ -295,6 +304,8 @@ class EditSettingsScreen extends Component {
hibernateOnStartup: Boolean(settingsData.hibernateOnStartup),
hibernationStrategy: Number(settingsData.hibernationStrategy),
wakeUpStrategy: Number(settingsData.wakeUpStrategy),
+ wakeUpHibernationStrategy: Number(settingsData.wakeUpHibernationStrategy),
+ wakeUpHibernationSplay: Boolean(settingsData.wakeUpHibernationSplay),
predefinedTodoServer: settingsData.predefinedTodoServer,
customTodoServer: settingsData.customTodoServer,
lockingFeatureEnabled: Boolean(settingsData.lockingFeatureEnabled),
@@ -391,6 +402,11 @@ class EditSettingsScreen extends Component {
sort: false,
});
+ const wakeUpHibernationStrategies = getSelectOptions({
+ locales: WAKE_UP_HIBERNATION_STRATEGIES,
+ sort: false,
+ });
+
const todoApp = getSelectOptions({
locales: TODO_APPS,
sort: false,
@@ -511,6 +527,17 @@ class EditSettingsScreen extends Component {
options: wakeUpStrategies,
default: DEFAULT_APP_SETTINGS.wakeUpStrategy,
},
+ wakeUpHibernationStrategy: {
+ label: intl.formatMessage(messages.wakeUpHibernationStrategy),
+ value: settings.all.app.wakeUpHibernationStrategy,
+ options: wakeUpHibernationStrategies,
+ default: DEFAULT_APP_SETTINGS.wakeUpHibernationStrategy,
+ },
+ wakeUpHibernationSplay: {
+ label: intl.formatMessage(messages.wakeUpHibernationSplay),
+ value: settings.all.app.wakeUpHibernationSplay,
+ default: DEFAULT_APP_SETTINGS.wakeUpHibernationSplay,
+ },
predefinedTodoServer: {
label: intl.formatMessage(messages.predefinedTodoServer),
value: settings.all.app.predefinedTodoServer,
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json
index 3f1e5728f..f6b53d501 100644
--- a/src/i18n/locales/en-US.json
+++ b/src/i18n/locales/en-US.json
@@ -243,6 +243,8 @@
"settings.app.form.universalDarkMode": "Enable universal Dark Mode",
"settings.app.form.useTouchIdToUnlock": "Allow using TouchID to unlock Ferdi",
"settings.app.form.useVerticalStyle": "Use horizontal style",
+ "settings.app.form.wakeUpHibernationSplay": "Splay hibernate/wake cycles to reduce load",
+ "settings.app.form.wakeUpHibernationStrategy": "Hibernation strategy after automatic wake up",
"settings.app.form.wakeUpStrategy": "Wake up strategy",
"settings.app.headlineAdvanced": "Advanced",
"settings.app.headlineAppearance": "Appearance",
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index e546850f9..e2bfd22f3 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -239,7 +239,7 @@ export default class ServicesStore extends Store {
ms(`${this.stores.settings.all.app.wakeUpStrategy}s`)
) {
// If service is in hibernation and the wakeup time has elapsed, wake it.
- this._awake({ serviceId: service.id });
+ this._awake({ serviceId: service.id, automatic: true });
}
}
@@ -1043,11 +1043,59 @@ export default class ServicesStore extends Store {
service.lastHibernated = Date.now();
}
- @action _awake({ serviceId }) {
+ @action _awake({ serviceId, automatic }) {
+ const now = Date.now();
const service = this.one(serviceId);
- debug(`Waking up from service hibernation for ${service.name}`);
+ const automaticTag = automatic ? ' automatically ' : ' ';
+ debug(
+ `Waking up${automaticTag}from service hibernation for ${service.name}`,
+ );
+
+ if (automatic) {
+ // if this is an automatic wake up, use the wakeUpHibernationStrategy
+ // which sets the lastUsed time to an offset from now rather than to now.
+ // Also add an optional random splay to desync the wakeups and
+ // potentially reduce load.
+ //
+ // offsetNow = now - (hibernationStrategy - wakeUpHibernationStrategy)
+ //
+ // if wUHS = hS = 60, offsetNow = now. hibernation again in 60 seconds.
+ //
+ // if wUHS = 20 and hS = 60, offsetNow = now - 40. hibernation again in
+ // 20 seconds.
+ //
+ // possibly also include splay in wUHS before subtracting from hS.
+ //
+ const mainStrategy = this.stores.settings.all.app.hibernationStrategy;
+ let strategy = this.stores.settings.all.app.wakeUpHibernationStrategy;
+ debug(`wakeUpHibernationStrategy = ${strategy}`);
+ debug(`hibernationStrategy = ${mainStrategy}`);
+ if (!strategy || strategy < 1) {
+ strategy = this.stores.settings.all.app.hibernationStrategy;
+ }
+ let splay = 0;
+ // Add splay. This will keep the service awake a little longer.
+ if (
+ this.stores.settings.all.app.wakeUpHibernationSplay &&
+ Math.random() >= 0.5
+ ) {
+ // Add 10 additional seconds 50% of the time.
+ splay = 10;
+ debug('Added splay');
+ } else {
+ debug('skipping splay');
+ }
+ // wake up again in strategy + splay seconds instead of mainStrategy seconds.
+ service.lastUsed = now - ms(`${mainStrategy - (strategy + splay)}s`);
+ } else {
+ service.lastUsed = now;
+ }
+ debug(
+ `Setting service.lastUsed to ${service.lastUsed} (${
+ (now - service.lastUsed) / 1000
+ }s ago)`,
+ );
service.isHibernationRequested = false;
- service.lastUsed = Date.now();
service.lastHibernated = null;
}
--
cgit v1.2.3-54-g00ecf