mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Add API endpoint to get site usage summary
Summary: The summary includes a count of documents that are approaching limits, in grace period, or delete-only. The endpoint is only accessible to site owners, and is currently unused. A follow-up diff will add usage banners to the site home page, which will use the response from the endpoint to communicate usage information to owners. Test Plan: Browser and server tests. Reviewers: alexmojaki Reviewed By: alexmojaki Differential Revision: https://phab.getgrist.com/D3420
This commit is contained in:
@@ -1,29 +1,60 @@
|
||||
import {ApiError} from 'app/common/ApiError';
|
||||
|
||||
export interface DocUsage {
|
||||
dataLimitStatus: DataLimitStatus;
|
||||
rowCount: RowCount;
|
||||
dataSizeBytes: DataSize;
|
||||
attachmentsSizeBytes: AttachmentsSize;
|
||||
export interface DocumentUsage {
|
||||
rowCount?: number;
|
||||
dataSizeBytes?: number;
|
||||
attachmentsSizeBytes?: number;
|
||||
}
|
||||
|
||||
type NumberOrStatus = number | 'hidden' | 'pending';
|
||||
|
||||
export type RowCount = NumberOrStatus;
|
||||
|
||||
export type DataSize = NumberOrStatus;
|
||||
|
||||
export type AttachmentsSize = NumberOrStatus;
|
||||
|
||||
export type DataLimitStatus = 'approachingLimit' | 'gracePeriod' | 'deleteOnly' | null;
|
||||
|
||||
export type NonHidden<T> = Exclude<T, 'hidden'>;
|
||||
type DocUsageOrPending = {
|
||||
[Metric in keyof Required<DocumentUsage>]: Required<DocumentUsage>[Metric] | 'pending'
|
||||
}
|
||||
|
||||
export interface DocUsageSummary extends DocUsageOrPending {
|
||||
dataLimitStatus: DataLimitStatus;
|
||||
}
|
||||
|
||||
// Count of non-removed documents in an org, grouped by data limit status.
|
||||
export type OrgUsageSummary = Record<NonNullable<DataLimitStatus>, number>;
|
||||
|
||||
type FilteredDocUsage = {
|
||||
[Metric in keyof DocUsageOrPending]: DocUsageOrPending[Metric] | 'hidden'
|
||||
}
|
||||
|
||||
export interface FilteredDocUsageSummary extends FilteredDocUsage {
|
||||
dataLimitStatus: DataLimitStatus;
|
||||
}
|
||||
|
||||
// Ratio of usage at which we start telling users that they're approaching limits.
|
||||
export const APPROACHING_LIMIT_RATIO = 0.9;
|
||||
|
||||
export class LimitExceededError extends ApiError {
|
||||
constructor(message: string) {
|
||||
super(message, 413);
|
||||
/**
|
||||
* Computes a ratio of `usage` to `limit`, if possible. Returns 0 if `usage` or `limit`
|
||||
* is invalid or undefined.
|
||||
*/
|
||||
export function getUsageRatio(usage: number | undefined, limit: number | undefined): number {
|
||||
if (!isEnforceableLimit(limit) || usage === undefined || usage < 0) {
|
||||
// Treat undefined or invalid values as having 0 usage.
|
||||
return 0;
|
||||
}
|
||||
|
||||
return usage / limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty org usage summary with values initialized to 0.
|
||||
*/
|
||||
export function createEmptyOrgUsageSummary(): OrgUsageSummary {
|
||||
return {
|
||||
approachingLimit: 0,
|
||||
gracePeriod: 0,
|
||||
deleteOnly: 0,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if `limit` is defined and is a valid, positive number.
|
||||
*/
|
||||
function isEnforceableLimit(limit: number | undefined): limit is number {
|
||||
return limit !== undefined && limit > 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user