Terminplaner: Aufbewahrungs-Loeschung seitenweise (Grundlagen, verfallen/abgesagt/abgelehnt)

loeschKandidaten liest eine Seite (Standard 100, aelteste Bezugszeit zuerst, optional je Funktion)
ohne Gastfelder; die Frist steht in der Abfrage. arbeiteSeiten (Seite lesen, bearbeiten, neu lesen)
endet bei leerer Seite, am Deckel (config.termine.loeschDeckel, 2000 je Status und Lauf, Rest an den
Folgetagen, gezaehlt als gedeckelt) oder bei einer Seite ohne Fortschritt. verfallen, abgesagt und
abgelehnt laufen darueber, unter der Buchungssperre werden Status und Bezugszeit frisch geprueft.
taeglicherJob liefert gedeckelt getrennt vom Loeschzaehler. Neue Indizes idx_status_ends und
idx_status_updated auf termineBookings (scripts/termine-setup.mjs legt sie an).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-04 08:55:32 +00:00
1 parent 2dd9c0dec7
commit 5c95dfc322
8 files changed
+484 -33

No files matched your search

+28
View File
@@ -152,6 +152,8 @@ test('Schema: Indizes wie in der Spezifikation und nur auf vorhandenen Attribute
['idx_verify', 'verifyHash'],
['idx_manage', 'manageHash'],
['idx_status_start', 'status', 'startsAt'],
['idx_status_ends', 'status', 'endsAt'],
['idx_status_updated', 'status', 'updatedAt'],
])
assert.deepEqual(indexes('termineClaims'), [['idx_booking', 'bookingId'], ['idx_bis', 'bis']])
assert.deepEqual(indexes('termineOutbox'), [['idx_status_next', 'status', 'naechsterVersuch']])
@@ -230,6 +232,9 @@ test('main legt auf leerer Datenbank 4 Collections, alle Attribute und Indizes a
assert.deepEqual(client.calls.collections, NAMES.map((id) => ({ id, name: id })))
assert.deepEqual([...client.calls.attrs].sort(), [...expectedAttrs].sort())
assert.deepEqual([...client.calls.indexes].sort(), [...expectedIndexes].sort())
// die Loeschfristen (Tagesjob) lesen ueber Status + Bezugszeit: beide Indizes werden angelegt
assert.ok(client.calls.indexes.includes('termineBookings.idx_status_ends'))
assert.ok(client.calls.indexes.includes('termineBookings.idx_status_updated'))
assert.equal(result.missing.length, expectedAttrs.length)
assert.deepEqual(result.missingCollections, NAMES)
assert.equal(result.missingIndexes.length, expectedIndexes.length)
@@ -267,6 +272,29 @@ test('main: legt nur fehlende Attribute und Indizes einer vorhandenen Collection
assert.equal(client.calls.collections.length, 3)
})
test('main: eine vorhandene termineBookings-Collection bekommt nur die beiden Loesch-Indizes nachgezogen (--check meldet sie)', async () => {
const vorhanden = {
termineBookings: {
attrs: keysOf('termineBookings'),
indexes: ['idx_feature_start', 'idx_status_held', 'idx_feature_email', 'idx_verify', 'idx_manage', 'idx_status_start'],
},
}
const lines = []
const pruefung = fakeClient(vorhanden)
const offen = await main({ check: true, client: pruefung, log: (line) => lines.push(line) })
assert.deepEqual(offen.missingIndexes.filter((i) => i.collection === 'termineBookings').map((i) => i.key), ['idx_status_ends', 'idx_status_updated'])
assert.ok(lines.some((line) => line.includes('Index termineBookings.idx_status_ends FEHLT')))
assert.ok(lines.some((line) => line.includes('Index termineBookings.idx_status_updated FEHLT')))
const client = fakeClient(vorhanden)
await main({ client, log: quiet })
assert.deepEqual(
client.calls.indexes.filter((k) => k.startsWith('termineBookings.')),
['termineBookings.idx_status_ends', 'termineBookings.idx_status_updated'],
)
assert.deepEqual(client.calls.attrs.filter((k) => k.startsWith('termineBookings.')), [])
})
test('main --check legt nichts an und meldet Fehlendes', async () => {
const client = fakeClient()
const lines = []