MCPcopy Create free account
hub / github.com/bearlyai/OpenADE / handleSave

Function handleSave

projects/electron/src/modules/code/yjsStorage.ts:128–208  ·  view source on GitHub ↗

* Save a YJS document to disk. * Uses atomic write (temp file + rename) to prevent corruption. * Merges incoming data with existing disk state to never lose data. * Serializes saves per document to prevent race conditions.

(id: string, data: Uint8Array)

Source from the content-addressed store, hash-verified

126 * Serializes saves per document to prevent race conditions.
127 */
128async function handleSave(id: string, data: Uint8Array): Promise<void> {
129 // Chain this save after any pending save for the same document
130 const prevSave = saveQueues.get(id) ?? Promise.resolve()
131
132 const currentSave = prevSave.then(async () => {
133 await ensureStorageDir()
134
135 const filePath = getDocPath(id)
136 const tempPath = `${filePath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`
137
138 let doc: Y.Doc | null = null
139 try {
140 // Load existing state if present
141 let existingData: Buffer | null = null
142 try {
143 existingData = await fs.readFile(filePath)
144 } catch (error) {
145 if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
146 throw error
147 }
148 // File doesn't exist yet, that's fine
149 }
150
151 // Fast path: if incoming data exactly matches existing, skip the save
152 if (existingData && existingData.length === data.length) {
153 let identical = true
154 for (let i = 0; i < data.length; i++) {
155 if (existingData[i] !== data[i]) {
156 identical = false
157 break
158 }
159 }
160 if (identical) {
161 logger.debug(`[YjsStorage] Skipped save (unchanged): ${id} (${data.length} bytes)`)
162 return
163 }
164 }
165
166 // Merge with existing data to never lose updates
167 doc = new Y.Doc()
168
169 if (existingData) {
170 Y.applyUpdate(doc, new Uint8Array(existingData))
171 }
172
173 // Apply incoming update (merges with existing via CRDT)
174 Y.applyUpdate(doc, data)
175
176 // Encode merged state
177 const mergedState = Y.encodeStateAsUpdate(doc)
178
179 // Atomic write: write to temp file, then rename
180 await fs.writeFile(tempPath, mergedState)
181 await fs.rename(tempPath, filePath)
182
183 logger.debug(`[YjsStorage] Saved document: ${id} (${mergedState.length} bytes)`)
184 } catch (error) {
185 // Clean up temp file if it exists

Callers 1

saveYjsDocumentFunction · 0.70

Calls 8

ensureStorageDirFunction · 0.85
getDocPathFunction · 0.85
readFileMethod · 0.80
writeFileMethod · 0.80
destroyMethod · 0.80
getMethod · 0.65
deleteMethod · 0.65
setMethod · 0.65

Tested by

no test coverage detected