|
1 | 1 | import { Env } from '..';
|
2 | 2 | import { isDateOlderThan } from '../utils/date';
|
3 | 3 |
|
4 |
| -const CURSOR_SIZE = 500; |
| 4 | +// Cursor size should be kept below 1000 to avoid limits on bulk operations |
| 5 | +export const CURSOR_SIZE = 500; |
5 | 6 |
|
6 |
| -export async function deleteOldCache(env: Env) { |
| 7 | +class R2KeysForDeletion { |
| 8 | + keys: string[] = []; |
| 9 | + add(key: string) { |
| 10 | + this.keys.push(key); |
| 11 | + } |
| 12 | +} |
| 13 | + |
| 14 | +export async function deleteOldCache(env: Env): Promise<void> { |
7 | 15 | const BUCKET_CUTOFF_HOURS = env.BUCKET_OBJECT_EXPIRATION_HOURS;
|
8 | 16 | let truncated = false;
|
9 | 17 | let cursor: string | undefined;
|
10 | 18 | let list: R2Objects;
|
11 |
| - const keysMarkedForDeletion: string[] = []; |
| 19 | + const keysMarkedForDeletion: R2KeysForDeletion[] = []; |
12 | 20 |
|
13 | 21 | do {
|
14 | 22 | list = await env.R2_STORE.list({ limit: CURSOR_SIZE, cursor });
|
15 | 23 | truncated = list.truncated;
|
16 | 24 | cursor = list.truncated ? list.cursor : undefined;
|
17 | 25 |
|
| 26 | + /** |
| 27 | + * Deleting keys while iterating over the list can sometimes cause the list to be truncated. |
| 28 | + * So we mark the keys for deletion and delete after at least one additional iteration. |
| 29 | + */ |
| 30 | + const keysAvailableForDeletion = keysMarkedForDeletion.shift(); |
| 31 | + if (keysAvailableForDeletion) { |
| 32 | + await env.R2_STORE.delete(keysAvailableForDeletion.keys); |
| 33 | + } |
| 34 | + |
| 35 | + const keysForDeletion = new R2KeysForDeletion(); |
18 | 36 | for (const object of list.objects) {
|
19 | 37 | if (isDateOlderThan(object.uploaded, BUCKET_CUTOFF_HOURS)) {
|
20 |
| - keysMarkedForDeletion.push(object.key); |
| 38 | + keysForDeletion.add(object.key); |
21 | 39 | }
|
22 | 40 | }
|
| 41 | + keysMarkedForDeletion.push(keysForDeletion); |
23 | 42 | } while (truncated);
|
24 |
| - |
25 |
| - if (keysMarkedForDeletion.length > 0) { |
26 |
| - // if (env.ENVIRONMENT === 'development') { |
27 |
| - // console.log(`Deleting ${keysMarkedForDeletion.length} keys`, keysMarkedForDeletion); |
28 |
| - // } |
29 |
| - await env.R2_STORE.delete(keysMarkedForDeletion); |
| 43 | + for (const keysForDeletion of keysMarkedForDeletion) { |
| 44 | + await env.R2_STORE.delete(keysForDeletion.keys); |
30 | 45 | }
|
31 | 46 | }
|
0 commit comments