2022-05-16 17:41:12 +00:00
|
|
|
import {ApiError} from 'app/common/ApiError';
|
2024-08-28 01:27:59 +00:00
|
|
|
import {APPROACHING_LIMIT_RATIO, DataLimitInfo, DataLimitStatus,
|
|
|
|
DocumentUsage, getUsageRatio} from 'app/common/DocUsage';
|
2022-05-16 17:41:12 +00:00
|
|
|
import {Features} from 'app/common/Features';
|
2022-07-04 14:14:55 +00:00
|
|
|
import moment from 'moment-timezone';
|
2022-05-16 17:41:12 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Error class indicating failure due to limits being exceeded.
|
|
|
|
*/
|
|
|
|
export class LimitExceededError extends ApiError {
|
|
|
|
constructor(message: string) {
|
|
|
|
super(message, 413);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface GetDataLimitStatusParams {
|
|
|
|
docUsage: DocumentUsage | null;
|
|
|
|
productFeatures: Features | undefined;
|
|
|
|
gracePeriodStart: Date | null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Given a set of params that includes document usage, current product features, and
|
|
|
|
* a grace-period start (if any), returns the data limit status of a document.
|
|
|
|
*/
|
2024-08-28 01:27:59 +00:00
|
|
|
export function getDataLimitInfo(params: GetDataLimitStatusParams): DataLimitInfo {
|
2022-05-16 17:41:12 +00:00
|
|
|
const {docUsage, productFeatures, gracePeriodStart} = params;
|
|
|
|
const ratio = getDataLimitRatio(docUsage, productFeatures);
|
|
|
|
if (ratio > 1) {
|
|
|
|
const start = gracePeriodStart;
|
2024-08-28 01:27:59 +00:00
|
|
|
// In case we forgot to define a grace period, we'll default to two weeks.
|
|
|
|
const days = productFeatures?.gracePeriodDays ?? 14;
|
|
|
|
const daysRemaining = start && days ? days - moment().diff(moment(start), 'days') : NaN;
|
|
|
|
if (daysRemaining > 0) {
|
|
|
|
return {status: 'gracePeriod', daysRemaining};
|
2022-05-16 17:41:12 +00:00
|
|
|
} else {
|
2024-08-28 01:27:59 +00:00
|
|
|
return {status: 'deleteOnly'};
|
2022-05-16 17:41:12 +00:00
|
|
|
}
|
|
|
|
} else if (ratio > APPROACHING_LIMIT_RATIO) {
|
2024-08-28 01:27:59 +00:00
|
|
|
return {status: 'approachingLimit'};
|
2022-05-16 17:41:12 +00:00
|
|
|
}
|
2024-08-28 01:27:59 +00:00
|
|
|
|
|
|
|
return {status: null};
|
2022-05-16 17:41:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Given `docUsage` and `productFeatures`, returns the highest usage ratio
|
|
|
|
* across all data-related limits (currently only row count and data size).
|
|
|
|
*/
|
|
|
|
export function getDataLimitRatio(
|
|
|
|
docUsage: DocumentUsage | null,
|
|
|
|
productFeatures: Features | undefined
|
|
|
|
): number {
|
|
|
|
if (!docUsage) { return 0; }
|
|
|
|
|
|
|
|
const {rowCount, dataSizeBytes} = docUsage;
|
|
|
|
const maxRows = productFeatures?.baseMaxRowsPerDocument;
|
|
|
|
const maxDataSize = productFeatures?.baseMaxDataSizePerDocument;
|
2022-08-03 07:18:21 +00:00
|
|
|
const rowRatio = getUsageRatio(rowCount?.total, maxRows);
|
2022-05-16 17:41:12 +00:00
|
|
|
const dataSizeRatio = getUsageRatio(dataSizeBytes, maxDataSize);
|
|
|
|
return Math.max(rowRatio, dataSizeRatio);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Maps `dataLimitStatus` status to an integer and returns it; larger integer
|
|
|
|
* values indicate a more "severe" status.
|
|
|
|
*
|
2022-06-06 16:21:26 +00:00
|
|
|
* Useful for relatively comparing the severity of two DataLimitStatus values.
|
2022-05-16 17:41:12 +00:00
|
|
|
*/
|
|
|
|
export function getSeverity(dataLimitStatus: DataLimitStatus): number {
|
|
|
|
switch (dataLimitStatus) {
|
|
|
|
case null: { return 0; }
|
|
|
|
case 'approachingLimit': { return 1; }
|
|
|
|
case 'gracePeriod': { return 2; }
|
|
|
|
case 'deleteOnly': { return 3; }
|
|
|
|
}
|
|
|
|
}
|