web/satellite: rework session timeout reset with ongoing upload
Using eventbus was a terrible approach because if session would expire in less than 3 mins then we would do an explicit API request to reset session for each upload progress ping. With this change we simply check if there is at least one ongoing upload and refresh session with one single API request and we don't show inactivity modal. This is a possible fix for this issue (at least I can't reproduce it): https://github.com/storj/storj/issues/5618 How to test: setup storj-up with InactivityTimerDuration config value set to 120 seconds. go to object browser and start upload of some heavy file, for example 1GB. check if inactivity timer would be shown in 2 mins, additionaly you may check DevTools network tab. in my case upload is successfully done in about 3-4 mins without any problems. Change-Id: I09142a7affac08db1d02992ca2d2f40c6267324f
This commit is contained in:
parent
7942f3774f
commit
132a688bec
@ -203,7 +203,6 @@ import { BrowserFile } from '@/types/browser';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import eventBus from '@/utils/eventBus';
|
||||
import { Bucket } from '@/types/buckets';
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
@ -439,10 +438,7 @@ function filename(file: BrowserFile): string {
|
||||
* Upload the current selected or dragged-and-dropped file.
|
||||
*/
|
||||
async function upload(e: Event): Promise<void> {
|
||||
const callback = () => {
|
||||
eventBus.$emit('upload_progress');
|
||||
};
|
||||
await store.dispatch('files/upload', { e, callback });
|
||||
await store.dispatch('files/upload', { e });
|
||||
await analytics.eventTriggered(AnalyticsEvent.OBJECT_UPLOADED);
|
||||
const target = e.target as HTMLInputElement;
|
||||
target.value = '';
|
||||
|
@ -143,7 +143,8 @@ export const makeFilesModule = (): FilesModule => ({
|
||||
return groupedFiles;
|
||||
},
|
||||
|
||||
isInitialized: (state: FilesState) => state.s3 !== null,
|
||||
isInitialized: (state: FilesState): boolean => state.s3 !== null,
|
||||
uploadingLength: (state: FilesState): number => state.uploading.length,
|
||||
},
|
||||
mutations: {
|
||||
init(
|
||||
@ -431,7 +432,7 @@ export const makeFilesModule = (): FilesModule => ({
|
||||
commit('setObjectsCount', responseV2.KeyCount === undefined ? 0 : responseV2.KeyCount);
|
||||
},
|
||||
|
||||
async upload({ commit, state, dispatch }, { e, callback }: { e: DragEvent, callback: () => void }) {
|
||||
async upload({ commit, state, dispatch }, { e }: { e: DragEvent }) {
|
||||
assertIsInitialized(state);
|
||||
|
||||
type Item = DataTransferItem | FileSystemEntry;
|
||||
@ -525,7 +526,6 @@ export const makeFilesModule = (): FilesModule => ({
|
||||
);
|
||||
|
||||
upload.on('httpUploadProgress', async (progress) => {
|
||||
await callback();
|
||||
commit('setProgress', {
|
||||
Key: params.Key,
|
||||
progress: Math.round((progress.loaded / progress.total) * 100),
|
||||
|
@ -1,8 +0,0 @@
|
||||
// Copyright (C) 2022 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import Vue from 'vue';
|
||||
|
||||
const eventBus = new Vue();
|
||||
|
||||
export default eventBus;
|
@ -103,7 +103,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
|
||||
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
|
||||
|
||||
import { ErrorUnauthorized } from '@/api/errors/ErrorUnauthorized';
|
||||
import { RouteConfig } from '@/router';
|
||||
@ -112,7 +112,6 @@ import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { USER_ACTIONS } from '@/store/modules/users';
|
||||
import { CouponType } from '@/types/coupons';
|
||||
import { CreditCard } from '@/types/payments';
|
||||
import { Project } from '@/types/projects';
|
||||
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS, PM_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { AppState } from '@/utils/constants/appStateEnum';
|
||||
@ -121,7 +120,6 @@ import { User } from '@/types/users';
|
||||
import { AuthHttpApi } from '@/api/auth';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import eventBus from '@/utils/eventBus';
|
||||
import { AB_TESTING_ACTIONS } from '@/store/modules/abTesting';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
|
||||
@ -160,7 +158,6 @@ const auth: AuthHttpApi = new AuthHttpApi();
|
||||
const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
|
||||
const resetActivityEvents: string[] = ['keypress', 'mousemove', 'mousedown', 'touchmove'];
|
||||
const inactivityModalTime = 60000;
|
||||
const ACTIVITY_REFRESH_TIME_LIMIT = 180000;
|
||||
const sessionDuration: number = parseInt(MetaUtils.getMetaContent('inactivity-timer-duration')) * 1000;
|
||||
const sessionRefreshInterval: number = sessionDuration / 2;
|
||||
const debugTimerShown = MetaUtils.getMetaContent('inactivity-timer-viewer-enabled') === 'true';
|
||||
@ -302,13 +299,6 @@ const isProjectListPage = computed((): boolean => {
|
||||
return router.history.current?.name === RouteConfig.ProjectsList.name;
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns credit cards from store.
|
||||
*/
|
||||
const creditCards = computed((): CreditCard[] => {
|
||||
return store.state.paymentsModule.creditCards;
|
||||
});
|
||||
|
||||
/**
|
||||
* Indicates if current route is onboarding tour.
|
||||
*/
|
||||
@ -411,7 +401,12 @@ function restartSessionTimers(): void {
|
||||
}
|
||||
}, sessionRefreshInterval);
|
||||
|
||||
inactivityTimerId.value = setTimeout(() => {
|
||||
inactivityTimerId.value = setTimeout(async () => {
|
||||
if (store.getters['files/uploadingLength']) {
|
||||
await refreshSession();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSessionActive.value) return;
|
||||
inactivityModalShown.value = true;
|
||||
inactivityTimerId.value = setTimeout(async () => {
|
||||
@ -458,28 +453,6 @@ function selectProject(fetchedProjects: Project[]): void {
|
||||
storeProject(fetchedProjects[0].id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to trigger session timer update while doing not UI-related work for a long time.
|
||||
*/
|
||||
async function resetSessionOnLogicRelatedActivity(): Promise<void> {
|
||||
const isInactivityTimerEnabled = MetaUtils.getMetaContent('inactivity-timer-enabled');
|
||||
|
||||
if (!isInactivityTimerEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const expiresAt = LocalData.getSessionExpirationDate();
|
||||
|
||||
if (expiresAt) {
|
||||
const ms = Math.max(0, expiresAt.getTime() - Date.now());
|
||||
|
||||
// Isn't triggered when decent amount of session time is left.
|
||||
if (ms < ACTIVITY_REFRESH_TIME_LIMIT) {
|
||||
await refreshSession();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes session and resets session timers.
|
||||
*/
|
||||
@ -602,15 +575,6 @@ async function onSessionActivity(): Promise<void> {
|
||||
isSessionActive.value = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes to activity events to refresh session timers.
|
||||
*/
|
||||
onBeforeMount(() => {
|
||||
eventBus.$on('upload_progress', () => {
|
||||
resetSessionOnLogicRelatedActivity();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Lifecycle hook after initial render.
|
||||
* Pre fetches user`s and project information.
|
||||
@ -709,7 +673,10 @@ onMounted(async () => {
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
eventBus.$off('upload_progress');
|
||||
clearSessionTimers();
|
||||
resetActivityEvents.forEach((eventName: string) => {
|
||||
document.removeEventListener(eventName, onSessionActivity);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -103,8 +103,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import { computed, onBeforeMount, onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
@ -132,7 +131,6 @@ import { MetaUtils } from '@/utils/meta';
|
||||
import { AppState } from '@/utils/constants/appStateEnum';
|
||||
import { LocalData } from '@/utils/localData';
|
||||
import { CouponType } from '@/types/coupons';
|
||||
import eventBus from '@/utils/eventBus';
|
||||
import { AuthHttpApi } from '@/api/auth';
|
||||
import Heading from '@/views/all-dashboard/components/Heading.vue';
|
||||
|
||||
@ -160,7 +158,6 @@ const analytics = new AnalyticsHttpApi();
|
||||
const auth: AuthHttpApi = new AuthHttpApi();
|
||||
|
||||
const inactivityModalTime = 60000;
|
||||
const ACTIVITY_REFRESH_TIME_LIMIT = 180000;
|
||||
const sessionDuration: number = parseInt(MetaUtils.getMetaContent('inactivity-timer-duration')) * 1000;
|
||||
const sessionRefreshInterval: number = sessionDuration / 2;
|
||||
const debugTimerShown = MetaUtils.getMetaContent('inactivity-timer-viewer-enabled') === 'true';
|
||||
@ -448,7 +445,12 @@ function restartSessionTimers(): void {
|
||||
}
|
||||
}, sessionRefreshInterval);
|
||||
|
||||
inactivityTimerId.value = setTimeout(() => {
|
||||
inactivityTimerId.value = setTimeout(async () => {
|
||||
if (store.getters['files/uploadingLength']) {
|
||||
await refreshSession();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSessionActive.value) return;
|
||||
inactivityModalShown.value = true;
|
||||
inactivityTimerId.value = setTimeout(async () => {
|
||||
@ -477,28 +479,6 @@ function restartSessionTimers(): void {
|
||||
debugTimer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to trigger session timer update while doing not UI-related work for a long time.
|
||||
*/
|
||||
async function resetSessionOnLogicRelatedActivity(): Promise<void> {
|
||||
const isInactivityTimerEnabled = MetaUtils.getMetaContent('inactivity-timer-enabled');
|
||||
|
||||
if (!isInactivityTimerEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const expiresAt = LocalData.getSessionExpirationDate();
|
||||
|
||||
if (expiresAt) {
|
||||
const ms = Math.max(0, expiresAt.getTime() - Date.now());
|
||||
|
||||
// Isn't triggered when decent amount of session time is left.
|
||||
if (ms < ACTIVITY_REFRESH_TIME_LIMIT) {
|
||||
await refreshSession();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes session and resets session timers.
|
||||
*/
|
||||
@ -609,17 +589,7 @@ onMounted(async () => {
|
||||
await store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED);
|
||||
});
|
||||
|
||||
/**
|
||||
* Subscribes to activity events to refresh session timers.
|
||||
*/
|
||||
onBeforeMount(() => {
|
||||
eventBus.$on('upload_progress', () => {
|
||||
resetSessionOnLogicRelatedActivity();
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
eventBus.$off('upload_progress');
|
||||
clearSessionTimers();
|
||||
resetActivityEvents.forEach((eventName: string) => {
|
||||
document.removeEventListener(eventName, onSessionActivity);
|
||||
|
Loading…
Reference in New Issue
Block a user