58 lines
1.6 KiB
TypeScript
58 lines
1.6 KiB
TypeScript
/**
|
|
* computeSubResourceCacheTTL
|
|
*
|
|
* Computes the Redis TTL (in milliseconds) for opportunity sub-resources
|
|
* (notes, contacts, activities, etc.) that share the parent opportunity's
|
|
* activity window.
|
|
*
|
|
* Rules are identical to the main opportunity TTL but use different
|
|
* exported constant names so callers can distinguish them.
|
|
*/
|
|
|
|
export const SUB_TTL_HIGH_ACTIVITY = 60_000; // 60 seconds
|
|
export const SUB_TTL_MODERATE_ACTIVITY = 120_000; // 2 minutes
|
|
export const SUB_TTL_LOW_ACTIVITY = 300_000; // 5 minutes
|
|
|
|
export interface ComputeSubResourceCacheTTLInput {
|
|
closedFlag: boolean;
|
|
closedDate: Date | null;
|
|
expectedCloseDate: Date | null;
|
|
lastUpdated: Date | null;
|
|
now?: Date;
|
|
}
|
|
|
|
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
|
|
function ageMs(date: Date, now: Date): number {
|
|
return Math.abs(now.getTime() - date.getTime());
|
|
}
|
|
|
|
export function computeSubResourceCacheTTL(
|
|
input: ComputeSubResourceCacheTTLInput
|
|
): number | null {
|
|
const now = input.now ?? new Date();
|
|
|
|
// Rule 1a — closed > 30 days → no cache
|
|
if (input.closedFlag) {
|
|
if (!input.closedDate) return null;
|
|
const daysClosed = ageMs(input.closedDate, now) / DAY_MS;
|
|
if (daysClosed > 30) return null;
|
|
return SUB_TTL_LOW_ACTIVITY;
|
|
}
|
|
|
|
const dates = [input.lastUpdated, input.expectedCloseDate].filter(
|
|
(d): d is Date => d !== null
|
|
);
|
|
|
|
if (dates.length === 0) {
|
|
return SUB_TTL_LOW_ACTIVITY;
|
|
}
|
|
|
|
const minDeltaDays =
|
|
Math.min(...dates.map((d) => ageMs(d, now))) / DAY_MS;
|
|
|
|
if (minDeltaDays <= 5) return SUB_TTL_HIGH_ACTIVITY;
|
|
if (minDeltaDays <= 14) return SUB_TTL_MODERATE_ACTIVITY;
|
|
return SUB_TTL_LOW_ACTIVITY;
|
|
}
|