102 lines
2.6 KiB
JavaScript
102 lines
2.6 KiB
JavaScript
/**
|
|
* @fileoverview Per-tenant usage metering counters.
|
|
* @module store/usage
|
|
*/
|
|
|
|
import { getStore, persist } from './db.js';
|
|
import { getTenant, resolveLimits } from './tenants.js';
|
|
import { createDebugger } from '../debug/logger.js';
|
|
|
|
const log = createDebugger('billing');
|
|
|
|
/**
|
|
* @returns {string} YYYY-MM period key
|
|
*/
|
|
function currentPeriod() {
|
|
const d = new Date();
|
|
return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}`;
|
|
}
|
|
|
|
/**
|
|
* @param {string} tenantId
|
|
* @returns {{ period: string, timestamps: number, verifications: number, statusChecks: number, batchTimestamps: number, overage: object }}
|
|
*/
|
|
function emptyUsage(tenantId) {
|
|
return {
|
|
tenantId,
|
|
period: currentPeriod(),
|
|
timestamps: 0,
|
|
verifications: 0,
|
|
statusChecks: 0,
|
|
batchTimestamps: 0,
|
|
overage: { timestamps: 0, verifications: 0 },
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get usage for tenant, rolling period if month changed.
|
|
* @param {string} tenantId
|
|
* @returns {ReturnType<typeof emptyUsage>}
|
|
*/
|
|
export function getUsage(tenantId) {
|
|
const store = getStore();
|
|
let usage = store.usage[tenantId];
|
|
const period = currentPeriod();
|
|
|
|
if (!usage || usage.period !== period) {
|
|
usage = emptyUsage(tenantId);
|
|
store.usage[tenantId] = usage;
|
|
}
|
|
|
|
return usage;
|
|
}
|
|
|
|
/**
|
|
* Public summary for /auth/me.
|
|
* @param {string} tenantId
|
|
* @returns {object}
|
|
*/
|
|
export function getUsageSummary(tenantId) {
|
|
const usage = getUsage(tenantId);
|
|
const tenant = getTenant(tenantId);
|
|
const limits = tenant ? resolveLimits(tenant) : null;
|
|
|
|
return {
|
|
period: usage.period,
|
|
timestamps: usage.timestamps,
|
|
verifications: usage.verifications,
|
|
statusChecks: usage.statusChecks,
|
|
batchTimestamps: usage.batchTimestamps,
|
|
limits: limits
|
|
? {
|
|
timestamps: limits.timestamps,
|
|
verifications: limits.verifications,
|
|
batch: limits.batch,
|
|
batchMaxItems: limits.batchMaxItems,
|
|
}
|
|
: null,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Increment a usage metric.
|
|
*
|
|
* @param {string} tenantId
|
|
* @param {string} metric - e.g. `timestamps`, `verifications`, `statusChecks`, `batchTimestamps`, `overage.timestamps`
|
|
* @param {number} [amount=1]
|
|
* @returns {void}
|
|
*/
|
|
export function incrementUsage(tenantId, metric, amount = 1) {
|
|
const usage = getUsage(tenantId);
|
|
|
|
if (metric.startsWith('overage.')) {
|
|
const key = metric.slice('overage.'.length);
|
|
usage.overage[key] = (usage.overage[key] ?? 0) + amount;
|
|
} else {
|
|
usage[metric] = (usage[metric] ?? 0) + amount;
|
|
}
|
|
|
|
getStore().usage[tenantId] = usage;
|
|
persist();
|
|
log.debug('usage incremented', { tenantId, metric, amount, value: usage[metric] ?? usage.overage });
|
|
}
|