@cocalc/server
Version:
CoCalc server functionality: functions used by either the hub and the next.js server
86 lines • 3.67 kB
JavaScript
;
/*
Handle all mentions that haven't yet been handled.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const pool_1 = __importDefault(require("@cocalc/database/pool"));
const awaiting_1 = require("awaiting");
const logger_1 = require("@cocalc/backend/logger");
const notify_1 = __importDefault(require("./notify"));
const logger = (0, logger_1.getLogger)("mentions - handle");
// TODO: should be in the database server settings; also should be
// user configurable, and this is just a default
const minEmailInterval = "6 hours";
const maxPerInterval = 50; // up to 50 emails for a given chatroom every 6 hours.
// We check for new notifications this frequently.
const polIntervalSeconds = 15;
// Handle all notification, then wait for the given time, then again
// handle all unhandled notifications.
async function init() {
while (true) {
try {
await handleAllMentions();
}
catch (err) {
logger.warn(`WARNING -- error handling mentions -- ${err}`);
}
await (0, awaiting_1.delay)(polIntervalSeconds * 1000);
}
}
exports.default = init;
async function handleAllMentions() {
const pool = (0, pool_1.default)();
const { rows } = await pool.query("SELECT time, project_id, path, source, target, description, fragment_id FROM mentions WHERE action IS null");
for (const row of rows) {
const { time, project_id, path, source, target, description, fragment_id } = row;
try {
await handleMention({ project_id, path, time, target, fragment_id }, source, description ?? "");
}
catch (err) {
logger.warn(`WARNING -- error handling mention (will try later) -- ${err}`);
}
}
}
async function handleMention(key, source, description) {
// Check that source and target are both currently
// collaborators on the project.
const action = await determineAction(key);
try {
switch (action) {
case "ignore": // already recently notified about this chatroom.
await setAction(key, action);
return;
case "notify":
let whatDid = await (0, notify_1.default)(key, source, description);
// record what we did.
await setAction(key, whatDid);
return;
default:
throw Error(`BUG: unknown action "${action}"`);
}
}
catch (err) {
await setError(key, action, `${err}`);
}
}
async function determineAction(key) {
const pool = (0, pool_1.default)();
const { rows } = await pool.query(`SELECT COUNT(*)::INT FROM mentions WHERE project_id=$1 AND path=$2 AND target=$3 AND action = 'email' AND time >= NOW() - INTERVAL '${parseInt(minEmailInterval)}'`, [key.project_id, key.path, key.target]);
const count = rows[0]?.count ?? 0;
if (count >= maxPerInterval) {
return "ignore";
}
return "notify";
}
async function setAction(key, action) {
const pool = (0, pool_1.default)();
await pool.query("UPDATE mentions SET action=$1 WHERE project_id=$2 AND path=$3 AND time=$4 AND target=$5", [action, key.project_id, key.path, key.time, key.target]);
}
async function setError(key, action, error) {
const pool = (0, pool_1.default)();
await pool.query("UPDATE mentions SET action=$1, error=$2 WHERE project_id=$3 AND path=$4 AND time=$5 AND target=$6", [action, error, key.project_id, key.path, key.time, key.target]);
}
//# sourceMappingURL=handle.js.map