Files
memind/scripts/cleanup-tang-scheduled-tasks-103.mjs
T
john d58dc2a251 feat(wechat): add Intent Transaction Layer with unified task schema
Introduce Draft → Confirm → Commit flow for WeChat schedule intents behind
feature flags, plus h5_tasks dual-write/read aggregation and rollout scripts
so reminders and automations get explicit user confirmation before persisting.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-24 15:59:17 +08:00

81 lines
2.5 KiB
JavaScript

#!/usr/bin/env node
/**
* Cleanup Tang's duplicate scheduled tasks on 103.
* Dry-run by default; pass --apply to mutate rows.
*/
import process from 'node:process';
import mysql from 'mysql2/promise';
import { loadH5Environment } from './load-env.mjs';
loadH5Environment(import.meta.dirname);
const TANG = 'a70ff537-8908-486e-9b6c-042e07cc25db';
const DUPLICATE_WEATHER_TASK_ID = '66f0ee11-7777-415f-affd-34422c772d0f';
const KEEP_WEATHER_TASK_ID = '23456db0-918e-4055-9ca3-e17e83b2dc24';
const fmt = (ms) => new Date(Number(ms)).toLocaleString('zh-CN', {
timeZone: 'Asia/Shanghai',
hour12: false,
});
async function main() {
const apply = process.argv.includes('--apply');
const pool = mysql.createPool({ uri: process.env.DATABASE_URL, connectionLimit: 2 });
const now = Date.now();
const plan = [];
const [dupRows] = await pool.query(
`SELECT id, title, status, hour, minute, last_run_at, created_at
FROM h5_scheduled_tasks
WHERE id = ? AND user_id = ?
LIMIT 1`,
[DUPLICATE_WEATHER_TASK_ID, TANG],
);
const dup = dupRows[0];
if (!dup) {
plan.push({ taskId: DUPLICATE_WEATHER_TASK_ID, action: 'skip', reason: 'not_found' });
} else if (dup.status === 'cancelled') {
plan.push({ taskId: DUPLICATE_WEATHER_TASK_ID, action: 'skip', reason: 'already_cancelled', title: dup.title });
} else {
plan.push({
taskId: DUPLICATE_WEATHER_TASK_ID,
title: dup.title,
status: dup.status,
schedule: `${dup.hour}:${String(dup.minute).padStart(2, '0')}`,
keepTaskId: KEEP_WEATHER_TASK_ID,
action: apply ? 'cancel_duplicate' : 'would_cancel_duplicate',
});
if (apply) {
await pool.query(
`UPDATE h5_scheduled_tasks
SET status = 'cancelled', updated_at = ?, last_error = NULL
WHERE id = ? AND user_id = ?`,
[now, DUPLICATE_WEATHER_TASK_ID, TANG],
);
}
}
const [activeRows] = await pool.query(
`SELECT id, title, status, hour, minute, next_run_at
FROM h5_scheduled_tasks
WHERE user_id = ? AND status IN ('active', 'locked')
ORDER BY hour, minute, created_at`,
[TANG],
);
console.log(JSON.stringify({ apply, now: fmt(now), plan, remainingActive: activeRows.map((row) => ({
id: row.id,
title: row.title,
status: row.status,
schedule: `${row.hour}:${String(row.minute).padStart(2, '0')}`,
nextRunAt: fmt(row.next_run_at),
})) }, null, 2));
await pool.end();
}
main().catch((err) => {
console.error(err);
process.exit(1);
});