Connect Login Refresh: UserAccountComm: refresh token on wake; WebViewDialog: Connect login retry with exp backoff implemented, added a bit more logging

This commit is contained in:
Jan Bařtipán 2024-07-12 18:07:07 +02:00 committed by Lukas Matena
parent 6491dd7453
commit 6a7ac53335
4 changed files with 82 additions and 14 deletions

View File

@ -512,6 +512,14 @@ void UserAccountCommunication::on_activate_window(bool active)
std::lock_guard<std::mutex> lck(m_thread_stop_mutex);
m_window_is_active = active;
}
auto now = std::time(nullptr);
BOOST_LOG_TRIVIAL(info) << "UserAccountCommunication activate: active " << active;
if (active && m_next_token_refresh_at - now < 60) {
BOOST_LOG_TRIVIAL(info) << "Enqueue access token refresh on activation";
enqueue_refresh();
m_token_timer->Stop();
}
}
void UserAccountCommunication::wakeup_session_thread()
@ -527,12 +535,16 @@ void UserAccountCommunication::set_refresh_time(int seconds)
{
assert(m_token_timer);
m_token_timer->Stop();
int miliseconds = std::max(seconds * 1000 - 66666, 60000);
m_token_timer->StartOnce(miliseconds);
const auto prior_expiration_secs = 5 * 60;
int milliseconds = std::max((seconds - prior_expiration_secs) * 1000, 60000);
m_next_token_refresh_at = std::time(nullptr) + milliseconds / 1000;
m_token_timer->StartOnce(milliseconds);
}
void UserAccountCommunication::on_token_timer(wxTimerEvent& evt)
{
BOOST_LOG_TRIVIAL(info) << "UserAccountCommunication: Token refresh timer fired";
enqueue_refresh();
}
void UserAccountCommunication::on_polling_timer(wxTimerEvent& evt)

View File

@ -13,7 +13,7 @@
#include <thread>
#include <mutex>
#include <memory>
#include <wx/timer.h>
#include <ctime>
namespace Slic3r {
namespace GUI {
@ -97,6 +97,7 @@ private:
wxTimer* m_token_timer;
wxEvtHandler* m_timer_evt_handler;
std::time_t m_next_token_refresh_at;
void wakeup_session_thread();
void init_session_thread();

View File

@ -123,6 +123,7 @@ void UserAccountSession::init_with_code(const std::string& code, const std::stri
void UserAccountSession::token_success_callback(const std::string& body)
{
BOOST_LOG_TRIVIAL(debug) << "Access token refreshed";
// Data we need
std::string access_token, refresh_token, shared_session_key;
int expires_in = 300;
@ -176,6 +177,7 @@ void UserAccountSession::token_success_callback(const std::string& body)
void UserAccountSession::code_exchange_fail_callback(const std::string& body)
{
BOOST_LOG_TRIVIAL(debug) << "Access token refresh failed, body: " << body;
clear();
cancel_queue();
// Unlike refresh_fail_callback, no event was triggered so far, do it. (USER_ACCOUNT_ACTION_CODE_FOR_TOKEN does not send events)

View File

@ -636,6 +636,30 @@ wxString ConnectWebViewPanel::get_login_script(bool refresh)
window.__access_token_version = 0;
)",
#else
// R"(
// console.log('Preparing login');
// function errorHandler(err) {
// const msg = {
// action: 'ERROR',
// error: JSON.stringify(err),
// critical: false
// };
// console.error('Login error occurred', msg);
// window._prusaSlicer.postMessage(msg);
// };
// window.fetch('/slicer/login', {method: 'POST', headers: {Authorization: 'Bearer %s'}})
// .then(function (resp) {
// console.log('Login resp', resp);
// resp.text()
// .then(function (json) { console.log('Login resp body', json); return json; })
// .then(function (body) {
// if (resp.status >= 400) errorHandler({status: resp.status, body});
// });
// })
// .catch(function (err){
// errorHandler({message: err.message, stack: err.stack});
// });
// )",
R"(
console.log('Preparing login');
function errorHandler(err) {
@ -647,18 +671,46 @@ wxString ConnectWebViewPanel::get_login_script(bool refresh)
console.error('Login error occurred', msg);
window._prusaSlicer.postMessage(msg);
};
window.fetch('/slicer/login', {method: 'POST', headers: {Authorization: 'Bearer %s'}})
.then(function (resp) {
console.log('Login resp', resp);
resp.text()
.then(function (json) { console.log('Login resp body', json); return json; })
.then(function (body) {
if (resp.status >= 400) errorHandler({status: resp.status, body});
});
})
.catch(function (err){
errorHandler({message: err.message, stack: err.stack});
function delay(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms);
});
}
(async () => {
let retry = false;
let backoff = 1000;
const maxBackoff = 64000;
do {
let error = false;
try {
console.log('Slicer Login request');
let resp = await fetch('/slicer/login', {method: 'POST', headers: {Authorization: 'Bearer %s'}});
let body = await resp.text();
console.log('Slicer Login resp', resp.status, body);
if (resp.status >= 500) {
retry = true;
} else {
retry = false;
if (resp.status >= 400)
errorHandler({status: resp.status, body});
}
} catch (e) {
console.error('Slicer Login failed', e.toString());
retry = true;
}
if (retry) {
await delay(backoff + 1000 * Math.random());
if (backoff < maxBackoff) {
backoff *= 2;
}
}
} while (retry);
})();
)",
#endif
access_token
@ -691,6 +743,7 @@ void ConnectWebViewPanel::on_script_message(wxWebViewEvent& evt)
}
void ConnectWebViewPanel::on_navigation_request(wxWebViewEvent &evt)
{
BOOST_LOG_TRIVIAL(debug) << "Navigation requested to: " << into_u8(evt.GetURL());
if (evt.GetURL() == m_default_url) {
m_reached_default_url = true;
return;