Explorar o código

[web] extend history debugging with estimate on snapshot size (#32502)

GitOrigin-RevId: 6ee75d227c0d093e4698324f6cc018b077076730
Jakob Ackermann hai 4 meses
pai
achega
9f8f77e56f

+ 13 - 0
libraries/overleaf-editor-core/lib/file.js

@@ -123,6 +123,19 @@ class File {
     return rawFileData
   }
 
+  /**
+   * @returns {Record<string, number>}
+   */
+  toStats() {
+    const stats = this.data.toStats()
+    if (!_.isEmpty(this.metadata)) {
+      stats.nMeta = 1
+      // Note: Buffer does not exist in frontend. Use string length instead.
+      stats.metaSize = JSON.stringify(this.metadata).length
+    }
+    return stats
+  }
+
   /**
    * Hexadecimal SHA-1 hash of the file's content, if known.
    *

+ 10 - 0
libraries/overleaf-editor-core/lib/file_data/binary_file_data.js

@@ -33,6 +33,16 @@ class BinaryFileData extends FileData {
     return new BinaryFileData(raw.hash, raw.byteLength)
   }
 
+  /**
+   * @returns {Record<string, number>}
+   */
+  toStats() {
+    return {
+      hashes: 1,
+      byteLength: this.byteLength,
+    }
+  }
+
   /**
    * @inheritdoc
    * @returns {RawBinaryFileData}

+ 9 - 0
libraries/overleaf-editor-core/lib/file_data/hash_file_data.js

@@ -54,6 +54,15 @@ class HashFileData extends FileData {
     return raw
   }
 
+  /**
+   * @returns {Record<string, number>}
+   */
+  toStats() {
+    return {
+      hashes: 1 + (this.rangesHash ? 1 : 0),
+    }
+  }
+
   /**
    * @inheritdoc
    * @returns {string}

+ 9 - 0
libraries/overleaf-editor-core/lib/file_data/hollow_binary_file_data.js

@@ -36,6 +36,15 @@ class HollowBinaryFileData extends FileData {
     return { byteLength: this.byteLength }
   }
 
+  /**
+   * @returns {Record<string, number>}
+   */
+  toStats() {
+    return {
+      byteLength: this.byteLength,
+    }
+  }
+
   /** @inheritdoc */
   getByteLength() {
     return this.byteLength

+ 9 - 0
libraries/overleaf-editor-core/lib/file_data/hollow_string_file_data.js

@@ -42,6 +42,15 @@ class HollowStringFileData extends FileData {
     return { stringLength: this.stringLength }
   }
 
+  /**
+   * @returns {Record<string, number>}
+   */
+  toStats() {
+    return {
+      stringLength: this.stringLength,
+    }
+  }
+
   /** @inheritdoc */
   getStringLength() {
     return this.stringLength

+ 7 - 0
libraries/overleaf-editor-core/lib/file_data/index.js

@@ -81,6 +81,13 @@ class FileData {
     throw new Error('FileData: toRaw not implemented')
   }
 
+  /**
+   * @returns {Record<string, number>}
+   */
+  toStats() {
+    throw new Error('FileData: toStats not implemented')
+  }
+
   /**
    * @see File#getHash
    * @return {string | null | undefined}

+ 19 - 0
libraries/overleaf-editor-core/lib/file_data/lazy_string_file_data.js

@@ -71,6 +71,25 @@ class LazyStringFileData extends FileData {
     return raw
   }
 
+  /**
+   * @returns {Record<string, number>}
+   */
+  toStats() {
+    return {
+      hashes: 1 + (this.rangesHash ? 1 : 0),
+      stringLength: this.stringLength,
+      nOperations: this.operations.length,
+      operationsSize:
+        this.operations.length > 0
+          ? this.operations.reduce(
+              // Note: Buffer does not exist in frontend. Use string length instead.
+              (sum, op) => sum + JSON.stringify(op.toJSON()).length,
+              0
+            )
+          : 0,
+    }
+  }
+
   /** @inheritdoc */
   getHash() {
     if (this.operations.length) return null

+ 21 - 0
libraries/overleaf-editor-core/lib/file_data/string_file_data.js

@@ -58,6 +58,27 @@ class StringFileData extends FileData {
     return raw
   }
 
+  /**
+   * @returns {Record<string, number>}
+   */
+  toStats() {
+    // Note: Buffer does not exist in frontend. Use string length instead.
+    return {
+      nContent: 1,
+      contentSize: this.content.length,
+      nComments: this.comments.length,
+      commentsSize:
+        this.comments.length > 0
+          ? JSON.stringify(this.comments.toRaw()).length
+          : 0,
+      nTrackedChanges: this.trackedChanges.length,
+      trackedChangesSize:
+        this.trackedChanges.length > 0
+          ? JSON.stringify(this.trackedChanges.toRaw()).length
+          : 0,
+    }
+  }
+
   /** @inheritdoc */
   isEditable() {
     return true

+ 12 - 0
libraries/overleaf-editor-core/lib/file_map.js

@@ -126,6 +126,18 @@ class FileMap {
     return _.mapValues(this.files, fileToRaw)
   }
 
+  /**
+   * @returns {Map<string, Record<string, number>>}
+   */
+  toStats() {
+    const sizes = new Map()
+    for (const [path, file] of Object.entries(this.files)) {
+      if (!file) continue
+      sizes.set(path, file.toStats())
+    }
+    return sizes
+  }
+
   /**
    * Create the given file.
    *

+ 2 - 2
services/web/frontend/js/infrastructure/project-snapshot.ts

@@ -256,7 +256,7 @@ export class ProjectSnapshot {
 /**
  * Blob store that fetches blobs from the history service
  */
-class SimpleBlobStore {
+export class SimpleBlobStore {
   private projectId: string
 
   constructor(projectId: string) {
@@ -280,7 +280,7 @@ async function flushHistory(projectId: string) {
   await postJSON(`/project/${projectId}/flush`)
 }
 
-async function fetchLatestChunk(projectId: string): Promise<Chunk> {
+export async function fetchLatestChunk(projectId: string): Promise<Chunk> {
   const response = await getJSON<{ chunk: RawChunk }>(
     `/project/${projectId}/latest/history`
   )