mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
|
import {ApiError} from 'app/common/ApiError';
|
||
|
import {APPROACHING_LIMIT_RATIO, DataLimitStatus, DocumentUsage, getUsageRatio} from 'app/common/DocUsage';
|
||
|
import {Features} from 'app/common/Features';
|
||
|
import * as moment from 'moment-timezone';
|
||
|
|
||
|
/**
|
||
|
* 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.
|
||
|
*/
|
||
|
export function getDataLimitStatus(params: GetDataLimitStatusParams): DataLimitStatus {
|
||
|
const {docUsage, productFeatures, gracePeriodStart} = params;
|
||
|
const ratio = getDataLimitRatio(docUsage, productFeatures);
|
||
|
if (ratio > 1) {
|
||
|
const start = gracePeriodStart;
|
||
|
const days = productFeatures?.gracePeriodDays;
|
||
|
if (start && days && moment().diff(moment(start), 'days') >= days) {
|
||
|
return 'deleteOnly';
|
||
|
} else {
|
||
|
return 'gracePeriod';
|
||
|
}
|
||
|
} else if (ratio > APPROACHING_LIMIT_RATIO) {
|
||
|
return 'approachingLimit';
|
||
|
} else {
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 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;
|
||
|
const rowRatio = getUsageRatio(rowCount, maxRows);
|
||
|
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.
|
||
|
*
|
||
|
* Useful for relatively comparing the severity of two statuses.
|
||
|
*/
|
||
|
export function getSeverity(dataLimitStatus: DataLimitStatus): number {
|
||
|
switch (dataLimitStatus) {
|
||
|
case null: { return 0; }
|
||
|
case 'approachingLimit': { return 1; }
|
||
|
case 'gracePeriod': { return 2; }
|
||
|
case 'deleteOnly': { return 3; }
|
||
|
}
|
||
|
}
|