MCPcopy Create free account
hub / github.com/cloudflare/computer / writeFileStreaming

Function writeFileStreaming

packages/dofs/src/fs/writeFile.ts:140–268  ·  view source on GitHub ↗
(
  db: Database,
  path: string,
  source: ReadableStream<Uint8Array>,
  options: WriteFileOptions,
  now: () => number,
)

Source from the content-addressed store, hash-verified

138// Failure mid-stream leaves blob rows behind; gc() reaps orphans on
139// its next pass since no node references them.
140async function writeFileStreaming(
141 db: Database,
142 path: string,
143 source: ReadableStream<Uint8Array>,
144 options: WriteFileOptions,
145 now: () => number,
146): Promise<void> {
147 const { parts, path: canonical } = canonicalizePath(path);
148 if (parts.length === 0) {
149 throw createWorkspaceError("EISDIR", "cannot write to the root directory", canonical);
150 }
151 // Reject before we stage any blob bytes so known failures do not grow
152 // orphan blob rows that gc() then has to reap.
153 assertNotReadOnly(db, canonical);
154 if (options.exclusive) {
155 const parentInode = resolveParent(db, parts, canonical);
156 const existing = db.one(
157 "SELECT 1 FROM vfs_dirents WHERE parent_inode = ? AND name = ?",
158 parentInode,
159 parts[parts.length - 1],
160 );
161 if (existing !== undefined) {
162 throw createWorkspaceError("EEXIST", `path exists: ${canonical}`, canonical);
163 }
164 }
165 const mode = (options.mode ?? 0o644) & 0o7777;
166 const mtime = now();
167
168 const chunkRefs: Array<{ hash: Uint8Array; size: number }> = [];
169 // Carry-over buffer: bytes left over from the previous source chunk
170 // that didn't fill a CHUNK_SIZE window.
171 let carry: Uint8Array | undefined;
172
173 const flush = (chunk: Uint8Array): void => {
174 const hash = sha256(chunk);
175 stageBlob(db, hash, chunk, mtime);
176 chunkRefs.push({ hash, size: chunk.byteLength });
177 };
178
179 const reader = source.getReader();
180 try {
181 while (true) {
182 const { value, done } = await reader.read();
183 if (done) break;
184 if (value === undefined || value.byteLength === 0) continue;
185 let input = value;
186 if (carry !== undefined) {
187 // Splice carry-over onto the front of this source chunk so
188 // we can re-window cleanly.
189 const merged = new Uint8Array(carry.byteLength + input.byteLength);
190 merged.set(carry, 0);
191 merged.set(input, carry.byteLength);
192 input = merged;
193 carry = undefined;
194 }
195 let offset = 0;
196 while (input.byteLength - offset >= CHUNK_SIZE) {
197 // Copy the window so the staged blob doesn't alias a

Callers 1

writeFileFunction · 0.85

Calls 15

canonicalizePathFunction · 0.85
assertNotReadOnlyFunction · 0.85
insertFileNodeFunction · 0.85
insertFileDirentFunction · 0.85
buildManifestFunction · 0.85
incrementRevFunction · 0.85
oneMethod · 0.80
resolveParentFunction · 0.70
flushFunction · 0.70
getReaderMethod · 0.65
readMethod · 0.65
setMethod · 0.65

Tested by

no test coverage detected