New version nudge (#1793)
## Ticket 1329 The existing nudge to refresh the webpage only happens when the app cannot find the specific javascript file in the server. As we don't purge the files on each build, the browser typically uses the cached version of the app, which could be weeks behind (based on the error logs). ## Approach Poll the current version periodically (set to 1 hour for now) and invoke the nudge when a newer version is detected. We typically don't need to bump `MINIMUM_VERSION` unless there is an urgent need to make users move away from older versions (e.g. API changes, mistakes, etc.) ## Trade-offs Wanted to put the value in a separate file called `.min.version` so that the env's history won't be polluted with version bumps, but not sure how to implement with minimal code without having to read from the file. Getting from the env is the easiest to implement (per my limited knowledge).
This commit is contained in:
parent
769b1cdabb
commit
5638f64831
6 changed files with 78 additions and 4 deletions
|
@ -2,6 +2,10 @@
|
|||
|
||||
# Copy this file to .env to make modifications
|
||||
|
||||
# --- Minimum Version (Format: YYYYMMDDNNN) ---
|
||||
# Bump this when we want to nudge the user to refresh.
|
||||
MINIMUM_VERSION=20220705001
|
||||
|
||||
# --- Base config ---
|
||||
WEBPACK_WEB_PORT=9090
|
||||
WEBPACK_ELECTRON_PORT=9091
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
require('dotenv-defaults').config({ silent: false });
|
||||
|
||||
const config = {
|
||||
MINIMUM_VERSION: process.env.MINIMUM_VERSION,
|
||||
WEBPACK_WEB_PORT: process.env.WEBPACK_WEB_PORT,
|
||||
WEBPACK_ELECTRON_PORT: process.env.WEBPACK_ELECTRON_PORT,
|
||||
WEB_SERVER_PORT: process.env.WEB_SERVER_PORT,
|
||||
|
|
18
ui/index.jsx
18
ui/index.jsx
|
@ -13,7 +13,14 @@ import * as MODALS from 'constants/modal_types';
|
|||
import React, { Fragment, useState, useEffect } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import { doDaemonReady, doAutoUpdate, doOpenModal, doHideModal, doToggle3PAnalytics } from 'redux/actions/app';
|
||||
import {
|
||||
doDaemonReady,
|
||||
doAutoUpdate,
|
||||
doOpenModal,
|
||||
doHideModal,
|
||||
doToggle3PAnalytics,
|
||||
doMinVersionSubscribe,
|
||||
} from 'redux/actions/app';
|
||||
import Lbry, { apiCall } from 'lbry';
|
||||
import { isURIValid } from 'util/lbryURI';
|
||||
import { setSearchApi } from 'redux/actions/search';
|
||||
|
@ -252,9 +259,16 @@ function AppWrapper() {
|
|||
app.store.dispatch(doFetchUserLocale());
|
||||
}, 25);
|
||||
|
||||
const nonCriticalTimer = setTimeout(() => {
|
||||
app.store.dispatch(doMinVersionSubscribe());
|
||||
}, 5000);
|
||||
|
||||
analytics.startupEvent(Date.now());
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
clearTimeout(nonCriticalTimer);
|
||||
};
|
||||
}
|
||||
}, [readyToLaunch, persistDone]);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import isDev from 'electron-is-dev';
|
|||
import { ipcRenderer, remote } from 'electron';
|
||||
// @endif
|
||||
import path from 'path';
|
||||
import { MINIMUM_VERSION, URL } from 'config';
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
|
@ -269,6 +270,33 @@ export function doCheckUpgradeSubscribe() {
|
|||
};
|
||||
}
|
||||
|
||||
export function doMinVersionCheck() {
|
||||
return (dispatch) => {
|
||||
fetch(`${URL}/$/minVersion/v1/get`)
|
||||
.then((response) => response.json())
|
||||
.then((json) => {
|
||||
if (json?.status === 'success' && json?.data && MINIMUM_VERSION) {
|
||||
const liveMinimumVersion = Number(json.data);
|
||||
if (liveMinimumVersion > MINIMUM_VERSION) {
|
||||
dispatch({ type: ACTIONS.RELOAD_REQUIRED });
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doMinVersionSubscribe() {
|
||||
return (dispatch) => {
|
||||
dispatch(doMinVersionCheck());
|
||||
|
||||
const CHECK_UPGRADE_INTERVAL_MS = 60 * 60 * 1000;
|
||||
setInterval(() => dispatch(doMinVersionCheck()), CHECK_UPGRADE_INTERVAL_MS);
|
||||
};
|
||||
}
|
||||
|
||||
export function doCheckDaemonVersion() {
|
||||
return (dispatch) => {
|
||||
// @if TARGET='app'
|
||||
|
|
25
web/src/minVersion.js
Normal file
25
web/src/minVersion.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
const { MINIMUM_VERSION } = require('../../config');
|
||||
|
||||
async function getMinVersion(ctx, version) {
|
||||
if (!MINIMUM_VERSION) {
|
||||
ctx.status = 404;
|
||||
ctx.body = { message: 'Not Found' };
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ctx.set('Content-Type', 'application/json');
|
||||
ctx.set('Access-Control-Allow-Origin', '*');
|
||||
ctx.body = {
|
||||
status: 'success',
|
||||
data: MINIMUM_VERSION,
|
||||
};
|
||||
} catch (err) {
|
||||
ctx.status = err.statusCode || err.status || 500;
|
||||
ctx.body = {
|
||||
message: err.message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getMinVersion };
|
|
@ -1,12 +1,13 @@
|
|||
const { fetchStreamUrl } = require('./fetchStreamUrl');
|
||||
const { getHomepage } = require('./homepageApi');
|
||||
const { getHtml } = require('./html');
|
||||
const { getMinVersion } = require('./minVersion');
|
||||
const { getOEmbed } = require('./oEmbed');
|
||||
const { getRss } = require('./rss');
|
||||
const { getTempFile } = require('./tempfile');
|
||||
|
||||
const fetch = require('node-fetch');
|
||||
const Router = require('@koa/router');
|
||||
const { getHomepage } = require('./homepageApi');
|
||||
|
||||
// So any code from 'lbry-redux'/'lbryinc' that uses `fetch` can be run on the server
|
||||
global.fetch = fetch;
|
||||
|
@ -36,8 +37,9 @@ const tempfileMiddleware = async (ctx) => {
|
|||
ctx.body = temp;
|
||||
};
|
||||
|
||||
router.get(`/$/api/content/v1/get`, async (ctx) => getHomepage(ctx, 1));
|
||||
router.get(`/$/minVersion/v1/get`, async (ctx) => getMinVersion(ctx));
|
||||
|
||||
router.get(`/$/api/content/v1/get`, async (ctx) => getHomepage(ctx, 1));
|
||||
router.get(`/$/api/content/v2/get`, async (ctx) => getHomepage(ctx, 2));
|
||||
|
||||
router.get(`/$/download/:claimName/:claimId`, async (ctx) => {
|
||||
|
|
Loading…
Reference in a new issue