Commit 58502666 authored by Florent POITTEVIN's avatar Florent POITTEVIN
Browse files

feat: polling allow to restore polling interval on user event

parent 3cd8d4e1
......@@ -294,10 +294,11 @@ export class DepositDetailEditRoutable extends SharedAbstractDetailEditRoutable<
private _createPollingListenerForFileReady(): void {
this.subscribe(PollingHelper.startPollingObs({
intervalRefreshInSecond: environment.refreshDepositSubmittedIntervalInSecond,
incremental: true,
maxIntervalInSecond: 60,
stopAfterMaxIntervalReached: true,
initialIntervalRefreshInSecond: environment.refreshDepositSubmittedIntervalInSecond,
incrementInterval: true,
maximumIntervalRefreshInSecond: 60,
stopRefreshAfterMaximumIntervalReached: true,
resetIntervalWhenUserMouseEvent: true,
doBeforeFilter: () => {
const shouldContinuePollingBefore = this.shouldContinuePolling;
this.computedShouldContinuePolling();
......
......@@ -223,7 +223,11 @@ export class DepositListRoutable extends SharedAbstractListRoutable<Deposit, Dep
this.refreshCounter();
this.subscribe(PollingHelper.startPollingObs({
intervalRefreshInSecond: this.INTERVAL_REFRESH_IN_SECOND,
initialIntervalRefreshInSecond: this.INTERVAL_REFRESH_IN_SECOND,
resetIntervalWhenUserMouseEvent: true,
incrementInterval: true,
maximumIntervalRefreshInSecond: 60 * 10,
stopRefreshAfterMaximumIntervalReached: true,
actionToDo: () => this.refreshCounter(),
}));
}
......
......@@ -1028,9 +1028,9 @@ export class DepositState extends ResourceLogoState<DepositStateModel, Deposit>
let isReady = false;
return PollingHelper.startPollingObs({
intervalRefreshInSecond: 1,
incremental: true,
maxIntervalInSecond: 5,
initialIntervalRefreshInSecond: 1,
incrementInterval: true,
maximumIntervalRefreshInSecond: 5,
continueUntil: () => !isReady,
actionToDo: () => {
const url = `${this._urlResource}/${depositId}/${ApiResourceNameEnum.DATAFILE}/${datafileId}`;
......
......@@ -50,7 +50,7 @@ export class HomeCarouselPresentational extends SharedAbstractPresentational imp
super.ngOnInit();
this.subscribe(PollingHelper.startPollingObs({
intervalRefreshInSecond: environment.frequencyChangeCarouselTileInSecond,
initialIntervalRefreshInSecond: environment.frequencyChangeCarouselTileInSecond,
filter: () => {
if (this.skipNextChangeDueToManualChangeOfTiles) {
this.skipNextChangeDueToManualChangeOfTiles = false;
......
......@@ -140,15 +140,17 @@ export class OrderMyOrderDetailEditRoutable extends SharedAbstractDetailEditComm
},
];
private readonly INTERVAL_REFRESH_IN_SECOND: number = 5;
private readonly INTERVAL_MAX: number = 5;
private readonly INTERVAL_REFRESH_INITIAL_IN_SECOND: number = 5;
private readonly INTERVAL_REFRESH_MAX_IN_SECOND: number = 60;
ngOnInit(): void {
super.ngOnInit();
this.subscribe(PollingHelper.startPollingObs({
intervalRefreshInSecond: this.INTERVAL_REFRESH_IN_SECOND,
incremental: true,
initialIntervalRefreshInSecond: this.INTERVAL_REFRESH_INITIAL_IN_SECOND,
incrementInterval: true,
resetIntervalWhenUserMouseEvent: true,
maximumIntervalRefreshInSecond: this.INTERVAL_REFRESH_MAX_IN_SECOND,
continueUntil: () => isNullOrUndefined(this.current) || (this.current.status !== Enums.Order.StatusEnum.READY && this.current.status !== Enums.Order.StatusEnum.INERROR),
actionToDo: () => this._store.dispatch(ResourceActionHelper.getById(this._resourceNameSpace, this._resId, true)),
}));
......@@ -175,8 +177,9 @@ export class OrderMyOrderDetailEditRoutable extends SharedAbstractDetailEditComm
this.subscribe(PollingHelper.startPollingObs({
// Manage case when we are on the page that become ready
intervalRefreshInSecond: 1,
incremental: true,
initialIntervalRefreshInSecond: 1,
incrementInterval: true,
resetIntervalWhenUserMouseEvent: true,
filter: () => (this.current.status === Enums.Order.StatusEnum.READY || this.current.status === Enums.Order.StatusEnum.INERROR) && SessionStorageHelper.getListItem(SessionStorageEnum.newOrderAvailable)
.includes(this._resId),
actionToDo: () => {
......
......@@ -77,9 +77,10 @@ export class PreservationPlanningJobExecutionListContainer extends SharedAbstrac
this.retrieveCurrentModelWithUrl();
this.subscribe(PollingHelper.startPollingObs({
intervalRefreshInSecond: this.INTERVAL_REFRESH_IN_SECOND,
incremental: true,
maxIntervalInSecond: this.MAX_INTERVAL_REFRESH_IN_SECOND,
initialIntervalRefreshInSecond: this.INTERVAL_REFRESH_IN_SECOND,
incrementInterval: true,
maximumIntervalRefreshInSecond: this.MAX_INTERVAL_REFRESH_IN_SECOND,
resetIntervalWhenUserMouseEvent: true,
filter: () => isTrue(this.pollingToUpdateProgressBar),
actionToDo: () => this.getAll(),
}));
......
......@@ -165,8 +165,9 @@ export class PreservationPlanningJobExecutionDetailRoutable extends SharedAbstra
));
this.subscribe(PollingHelper.startPollingObs({
intervalRefreshInSecond: 2,
incremental: true,
initialIntervalRefreshInSecond: 2,
incrementInterval: true,
resetIntervalWhenUserMouseEvent: true,
continueUntil: () => isNullOrUndefined(CompositionState.currentSnapshot(this._store, PreservationPlanningJobExecutionState)) || (CompositionState.currentSnapshot(this._store, PreservationPlanningJobExecutionState).status !== Enums.PreservationJob.ExecutionStatusEnum.IN_ERROR &&
CompositionState.currentSnapshot(this._store, PreservationPlanningJobExecutionState).status !== Enums.PreservationJob.ExecutionStatusEnum.COMPLETED),
actionToDo: () => this.refresh(),
......
......@@ -42,7 +42,9 @@ export class PreservationPlanningMonitoringHomeRoutable extends SharedAbstractPr
this._store.dispatch(new PreservationPlanningMonitoringAction.Get(true));
this.subscribe(PollingHelper.startPollingObs({
intervalRefreshInSecond: this.INTERVAL_REFRESH_IN_SECOND,
initialIntervalRefreshInSecond: this.INTERVAL_REFRESH_IN_SECOND,
incrementInterval: true,
resetIntervalWhenUserMouseEvent: true,
actionToDo: () => this.getAll(),
}));
}
......
/* tslint:disable:no-console */
import {environment} from "@environments/environment";
import {intervalBackoff} from "backoff-rxjs";
import {IntervalBackoffConfig} from "backoff-rxjs/observable/intervalBackoff";
import {exponentialBackoffDelay} from "backoff-rxjs/utils";
import {
fromEvent,
Observable,
timer,
} from "rxjs";
import {
filter,
map,
sampleTime,
startWith,
switchMap,
takeWhile,
tap,
} from "rxjs/operators";
......@@ -20,53 +25,75 @@ import {
export class PollingHelper<Type> {
private static SECOND_TO_MILLISECOND: number = 1000;
private static LOG_INFOS: boolean = false;
static startPollingObs<Type>(config: PollingConfigInfo<Type>): Observable<Type> {
const stopAfterMaxIntervalReached = isTrue(config.incremental) && isTrue(config.stopAfterMaxIntervalReached);
const stopAfterMaxIntervalReached = isTrue(config.incrementInterval) && isTrue(config.stopRefreshAfterMaximumIntervalReached);
let maxIntervalReached = false;
const maxIntervalInSecond = isNumberFinite(config.maxIntervalInSecond) ? config.maxIntervalInSecond : environment.pollingMaxIntervalInSecond;
const maxIntervalInSecond = isNumberFinite(config.maximumIntervalRefreshInSecond) ? config.maximumIntervalRefreshInSecond : environment.pollingMaxIntervalInSecond;
const intervalInMillisecond = config.intervalRefreshInSecond * this.SECOND_TO_MILLISECOND;
let observable = timer(intervalInMillisecond, intervalInMillisecond);
if (isTrue(config.incremental)) {
observable = intervalBackoff({
initialInterval: intervalInMillisecond,
maxInterval: maxIntervalInSecond * this.SECOND_TO_MILLISECOND,
backoffDelay: (iteration, initialInterval) => {
const intervalInMillisecond = config.initialIntervalRefreshInSecond * this.SECOND_TO_MILLISECOND;
const optionIntervalBackoff = {
initialInterval: intervalInMillisecond,
maxInterval: maxIntervalInSecond * this.SECOND_TO_MILLISECOND,
backoffDelay: (iteration, initialInterval) => {
if (isTrue(config.incrementInterval)) {
const interval = exponentialBackoffDelay(iteration, initialInterval);
if (isTrue(stopAfterMaxIntervalReached) && isFalse(maxIntervalReached)) {
maxIntervalReached = interval >= maxIntervalInSecond * this.SECOND_TO_MILLISECOND;
if (this.LOG_INFOS && maxIntervalReached) {
console.info("Max interval rechead");
}
}
return interval;
},
}).pipe(
filter(() => {
const shouldContinue = isFalse(stopAfterMaxIntervalReached) || isFalse(maxIntervalReached);
return shouldContinue;
}),
);
}
return observable.pipe(
} else {
return initialInterval;
}
},
} as IntervalBackoffConfig;
const observable = intervalBackoff(optionIntervalBackoff).pipe(
filter(() => {
const shouldContinue = isFalse(stopAfterMaxIntervalReached) || isFalse(maxIntervalReached);
if (this.LOG_INFOS && isTrue(stopAfterMaxIntervalReached) && isFalse(shouldContinue)) {
console.info("Stop action (Max interval rechead)");
}
return shouldContinue;
}),
takeWhile(() => isUndefined(config.continueUntil) || config.continueUntil()),
tap(() => isUndefined(config.doBeforeFilter) || config.doBeforeFilter()),
filter(() => isUndefined(config.filter) || config.filter()),
map(() => config.actionToDo()),
tap(() => {
// if (isTrue(config.incremental)) {
// console.warn("INCREMENTE TIME: " + DateUtil.convertDateToTimeString(new Date()));
// }
map(() => {
return config.actionToDo();
}),
);
if (isTrue(config.incrementInterval) && isTrue(config.resetIntervalWhenUserMouseEvent)) {
return fromEvent(document, "mousemove").pipe(
sampleTime(intervalInMillisecond),
tap(() => {
if (this.LOG_INFOS) {
console.info("Reset interval due to user mouse event");
}
maxIntervalReached = false;
}),
startWith(null),
switchMap(() => observable),
);
} else {
return observable;
}
}
}
export interface PollingConfigInfo<Type> {
intervalRefreshInSecond: number;
initialIntervalRefreshInSecond: number;
maximumIntervalRefreshInSecond?: number | undefined;
doBeforeFilter?: () => void | undefined;
continueUntil?: () => boolean | undefined;
filter?: () => boolean | undefined;
actionToDo: () => Type;
incremental?: boolean | undefined;
maxIntervalInSecond?: number | undefined;
stopAfterMaxIntervalReached?: boolean | undefined;
incrementInterval?: boolean | undefined;
stopRefreshAfterMaximumIntervalReached?: boolean | undefined;
resetIntervalWhenUserMouseEvent?: boolean | undefined;
}
......@@ -427,7 +427,10 @@ export class AppState extends BasicState<AppStateModel> {
@Action(AppAction.StartPollingOrder)
startPollingOrder(ctx: StateContext<AppStateModel>, action: AppAction.StartPollingOrder): void {
PollingHelper.startPollingObs({
intervalRefreshInSecond: environment.refreshOrderAvailableIntervalInSecond,
initialIntervalRefreshInSecond: environment.refreshOrderAvailableIntervalInSecond,
incrementInterval: true,
resetIntervalWhenUserMouseEvent: true,
maximumIntervalRefreshInSecond: environment.refreshOrderAvailableIntervalInSecond * 10,
filter: () => SessionStorageHelper.getListItem(SessionStorageEnum.orderPending).length > 0,
actionToDo: () => {
const listOrderPending = SessionStorageHelper.getListItem(SessionStorageEnum.orderPending);
......@@ -464,7 +467,10 @@ export class AppState extends BasicState<AppStateModel> {
}
PollingHelper.startPollingObs({
intervalRefreshInSecond: environment.refreshNotificationInboxAvailableIntervalInSecond,
initialIntervalRefreshInSecond: environment.refreshNotificationInboxAvailableIntervalInSecond,
incrementInterval: true,
resetIntervalWhenUserMouseEvent: true,
maximumIntervalRefreshInSecond: environment.refreshNotificationInboxAvailableIntervalInSecond * 10,
filter: () => ctx.getState().isLoggedIn,
actionToDo: () => {
this.store.dispatch(new AppAction.UpdateNotificationInbox);
......
......@@ -142,7 +142,7 @@ $breakpoints-media-interval: (
@mixin icon-important($size) {
font-size: $size !important;
line-height: $size !important;;
width: $size !important;;
height: $size !important;;
line-height: $size !important;
width: $size !important;
height: $size !important;
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment