Skip to main content

max / goingson

backup: serialize exports directly to the writer Avoid holding the full serialized JSON in memory alongside the already-in-memory export. write_backup streams into the gzip encoder via serde_json::to_writer; write_json streams into a buffered file writer via to_writer_pretty. Removes the second full-dataset copy on both export paths. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-11 00:52 UTC
Commit: 64b973bc5fdeb0f6303b8cd712cd4c8193e5b413
Parent: 2ff4ea7
1 file changed, +9 insertions, -5 deletions
@@ -3,7 +3,7 @@
3 3 //! Provides compressed JSON backup creation and restoration for all GoingsOn data.
4 4
5 5 use std::fs::File;
6 - use std::io::{Read, Write};
6 + use std::io::{BufWriter, Read, Write};
7 7 use std::path::Path;
8 8
9 9 use chrono::{DateTime, Utc};
@@ -159,8 +159,9 @@ pub fn write_backup<P: AsRef<Path>>(export: &FullExport, path: P) -> Result<u64,
159 159 let file = File::create(&tmp_path)?;
160 160 let mut encoder = GzEncoder::new(file, Compression::default());
161 161
162 - let json = serde_json::to_vec(export)?;
163 - encoder.write_all(&json)?;
162 + // Serialize straight into the compressor so we never hold the full
163 + // serialized JSON in memory alongside the already-in-memory export.
164 + serde_json::to_writer(&mut encoder, export)?;
164 165 encoder.finish()?;
165 166
166 167 // Prevents corrupt backups if the process crashes mid-write
@@ -211,10 +212,13 @@ pub fn read_backup<P: AsRef<Path>>(path: P) -> Result<FullExport, BackupError> {
211 212 ///
212 213 /// The size of the file in bytes.
213 214 pub fn write_json<P: AsRef<Path>>(export: &FullExport, path: P) -> Result<u64, BackupError> {
214 - let json = serde_json::to_string_pretty(export)?;
215 215 let dest = path.as_ref();
216 216 let tmp = dest.with_extension("json.tmp");
217 - std::fs::write(&tmp, &json)?;
217 + // Stream the serialized JSON directly to the file through a buffered
218 + // writer instead of building the whole pretty-printed string in memory.
219 + let mut writer = BufWriter::new(File::create(&tmp)?);
220 + serde_json::to_writer_pretty(&mut writer, export)?;
221 + writer.flush()?;
218 222 std::fs::rename(&tmp, dest)?;
219 223
220 224 let metadata = std::fs::metadata(dest)?;