|
1 | 1 | const sessions = new Map(); |
| 2 | +const maxWriteBlockBytes = 1024 * 1024; |
2 | 3 |
|
3 | 4 | self.onmessage = async (event) => { |
4 | 5 | const { id, command, payload } = event.data ?? {}; |
@@ -59,12 +60,7 @@ async function appendChunksAsync(databaseName, blobKey, chunks) { |
59 | 60 |
|
60 | 61 | for (const chunk of Array.isArray(chunks) ? chunks : []) { |
61 | 62 | const data = chunk.data instanceof Uint8Array ? chunk.data : new Uint8Array(chunk.data ?? []); |
62 | | - const written = session.accessHandle.write(data, { at: session.position }); |
63 | | - if (written !== data.byteLength) { |
64 | | - throw new Error(`Short OPFS write for ${blobKey}: wrote ${written} of ${data.byteLength} bytes.`); |
65 | | - } |
66 | | - |
67 | | - session.position += written; |
| 63 | + writeAllBytes(session, blobKey, data); |
68 | 64 | } |
69 | 65 | } |
70 | 66 |
|
@@ -156,6 +152,37 @@ function getSessionKey(databaseName, blobKey) { |
156 | 152 | return `${databaseName}::${blobKey}`; |
157 | 153 | } |
158 | 154 |
|
| 155 | +function writeAllBytes(session, blobKey, data) { |
| 156 | + let offset = 0; |
| 157 | + |
| 158 | + while (offset < data.byteLength) { |
| 159 | + const bytesRemaining = data.byteLength - offset; |
| 160 | + const bytesToWrite = Math.min(bytesRemaining, maxWriteBlockBytes); |
| 161 | + const slice = data.subarray(offset, offset + bytesToWrite); |
| 162 | + const written = normalizeBytesWritten( |
| 163 | + session.accessHandle.write(slice, { at: session.position }), |
| 164 | + bytesToWrite, |
| 165 | + blobKey, |
| 166 | + session.position); |
| 167 | + |
| 168 | + offset += written; |
| 169 | + session.position += written; |
| 170 | + } |
| 171 | +} |
| 172 | + |
| 173 | +function normalizeBytesWritten(value, expectedBytes, blobKey, position) { |
| 174 | + if (!Number.isFinite(value)) { |
| 175 | + throw new Error(`Invalid OPFS write result for ${blobKey} at ${position}: ${String(value)}.`); |
| 176 | + } |
| 177 | + |
| 178 | + const written = Math.trunc(value); |
| 179 | + if (written <= 0 || written > expectedBytes) { |
| 180 | + throw new Error(`Invalid OPFS write result for ${blobKey} at ${position}: wrote ${written} of ${expectedBytes} bytes.`); |
| 181 | + } |
| 182 | + |
| 183 | + return written; |
| 184 | +} |
| 185 | + |
159 | 186 | async function getDatabaseDirectoryAsync(databaseName, create) { |
160 | 187 | const root = await navigator.storage.getDirectory(); |
161 | 188 | return await root.getDirectoryHandle(getDatabaseDirectoryName(databaseName), { create }); |
|
0 commit comments