(versionId: string, noteId: string)
| 366 | ); |
| 367 | return head.id; |
| 368 | } |
| 369 | |
| 370 | const id = crypto.randomUUID(); |
| 371 | const key = this.versionKey(noteId, id); |
| 372 | await this.bucket.put(key, content, { httpMetadata: { contentType: "application/json" } }); |
| 373 | this.sql.exec( |
| 374 | "INSERT INTO note_versions (id, note_id, parent_id, branch_id, title, is_checkpoint, data, created_by, kind, summary, storage, content_hash) VALUES (?, ?, ?, ?, ?, 1, ?, ?, ?, ?, 'r2', ?)", |
| 375 | id, noteId, parentId, branch.id, title, key, createdBy, kind, summary, hash |
| 376 | ); |
| 377 | |
| 378 | this.sql.exec("UPDATE note_branches SET head_version_id = ? WHERE id = ?", id, branch.id); |
| 379 | |
| 380 | await this.pruneVersions(noteId); |
| 381 | return id; |
| 382 | } |
| 383 | |
| 384 | private async pruneVersions(noteId: string) { |
| 385 | const stale = this.sql.exec( |
| 386 | `SELECT id, data, storage FROM note_versions WHERE note_id = ? AND id NOT IN ( |
| 387 | SELECT id FROM note_versions WHERE note_id = ? ORDER BY created_at DESC LIMIT ${this.MAX_VERSIONS_PER_NOTE} |
| 388 | )`, noteId, noteId |
| 389 | ).toArray() as any[]; |
| 390 | if (stale.length === 0) return; |
| 391 | for (let i = 0; i < stale.length; i += 500) { |
| 392 | const batch = stale.slice(i, i + 500); |
| 393 | this.sql.exec( |
| 394 | `DELETE FROM note_versions WHERE id IN (${batch.map(() => "?").join(",")})`, |
| 395 | ...batch.map((r) => r.id) |
| 396 | ); |
no test coverage detected