feat: füge Skripte zur Behebung von SRS-Elementen hinzu, die mit next_due_at gleich oder unmittelbar vor created_at erstellt wurden
All checks were successful
Deploy to production / deploy (push) Successful in 2m11s
All checks were successful
Deploy to production / deploy (push) Successful in 2m11s
This commit is contained in:
67
backend/scripts/fix-srs-immediate-due.js
Normal file
67
backend/scripts/fix-srs-immediate-due.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
import { sequelize } from '../utils/sequelize.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix SRS items that were created with next_due_at equal-or-immediately-before created_at
|
||||||
|
* - Detect items created recently whose next_due_at is within a small window of created_at
|
||||||
|
* - Move next_due_at to the next calendar day at 08:00 local (safe default)
|
||||||
|
*
|
||||||
|
* Run on the server after a backup. Prints counts and example rows before/after.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const DRY_RUN = process.env.DRY_RUN !== 'false';
|
||||||
|
|
||||||
|
const run = async () => {
|
||||||
|
try {
|
||||||
|
await sequelize.authenticate();
|
||||||
|
console.log('✅ DB connection OK');
|
||||||
|
|
||||||
|
// Conservative selector: items created in the last 3 days where next_due_at is within 2 minutes of created_at
|
||||||
|
const selector = `
|
||||||
|
SELECT id, item_key, course_id, stage, next_due_at, created_at
|
||||||
|
FROM community.vocab_srs_item
|
||||||
|
WHERE created_at >= now() - interval '3 days'
|
||||||
|
AND abs(extract(epoch from (next_due_at - created_at))) < 120
|
||||||
|
ORDER BY created_at ASC
|
||||||
|
LIMIT 500
|
||||||
|
`;
|
||||||
|
|
||||||
|
const recent = await sequelize.query(selector, { type: sequelize.QueryTypes.SELECT });
|
||||||
|
console.log('\nFound items matching heuristic: ', recent.length);
|
||||||
|
console.table(recent.slice(0, 20));
|
||||||
|
|
||||||
|
if (recent.length === 0) {
|
||||||
|
console.log('\nNo candidate rows found — nothing to do.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute update target: next calendar day at 08:00 based on created_at
|
||||||
|
// Use an UPDATE with an expression so each row gets next_due_at = date_trunc('day', created_at + '1 day') + '08:00'
|
||||||
|
const updateQuery = `
|
||||||
|
UPDATE community.vocab_srs_item
|
||||||
|
SET next_due_at = date_trunc('day', created_at + interval '1 day') + interval '8 hours'
|
||||||
|
WHERE created_at >= now() - interval '3 days'
|
||||||
|
AND abs(extract(epoch from (next_due_at - created_at))) < 120
|
||||||
|
RETURNING id, item_key, course_id, stage, next_due_at, created_at;
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (DRY_RUN) {
|
||||||
|
console.log('\nDRY RUN: to apply changes set ENV var DRY_RUN=false');
|
||||||
|
console.log('Preview of UPDATE SQL:\n', updateQuery);
|
||||||
|
} else {
|
||||||
|
console.log('\nApplying update...');
|
||||||
|
const updated = await sequelize.query(updateQuery, { type: sequelize.QueryTypes.SELECT });
|
||||||
|
console.log('\nUpdated rows: ', updated.length);
|
||||||
|
console.table(updated.slice(0, 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\nRecommendation: rerun `backend/scripts/diag-srs-stats.js` to verify totals afterwards.');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error running fix script:', err);
|
||||||
|
process.exitCode = 2;
|
||||||
|
} finally {
|
||||||
|
try { await sequelize.close(); } catch (_) {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
run();
|
||||||
23
backend/scripts/fix-srs-queries.sql
Normal file
23
backend/scripts/fix-srs-queries.sql
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
-- Fix items that were created with next_due_at ~= created_at (within 2 minutes)
|
||||||
|
-- Run this after a backup. Adjust the WHERE clause if you want a different window.
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- Preview rows to be changed
|
||||||
|
SELECT id, item_key, course_id, stage, next_due_at, created_at
|
||||||
|
FROM community.vocab_srs_item
|
||||||
|
WHERE created_at >= now() - interval '3 days'
|
||||||
|
AND abs(EXTRACT(EPOCH FROM (next_due_at - created_at))) < 120
|
||||||
|
ORDER BY created_at ASC
|
||||||
|
LIMIT 200;
|
||||||
|
|
||||||
|
-- Conservative update: set next_due_at to next calendar day at 08:00
|
||||||
|
UPDATE community.vocab_srs_item
|
||||||
|
SET next_due_at = date_trunc('day', created_at + interval '1 day') + interval '8 hours'
|
||||||
|
WHERE created_at >= now() - interval '3 days'
|
||||||
|
AND abs(EXTRACT(EPOCH FROM (next_due_at - created_at))) < 120
|
||||||
|
RETURNING id, item_key, course_id, stage, next_due_at, created_at;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
-- After running, re-run backend/scripts/diag-srs-stats.js to validate counts.
|
||||||
Reference in New Issue
Block a user