You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 9bd1f41
Browse filesBrowse the repository at this point in the historyBrowse files
`src/bridge/native-fs.ts`, `src/bridge/mobile-cloud-sync.ts`, and tests. No
6
+
native code, no Capacitor config and no app-core change.
7
+
8
+
## Why
9
+
10
+
A Discord report (yeminn) had phones sitting in "Syncing..." through a long
11
+
first Cloud sync. Measured on an API 37 emulator, a pull costs the same per
12
+
file at 600, 2,500 and 5,000 notes, and that cost is almost all Capacitor
13
+
bridge round trips: about 16 per pulled file at about 1 ms each, 10.3 s of a
14
+
10.7 s 600-note sync. So the lever for big first syncs is calls per file.
15
+
16
+
## What changed
17
+
18
+
Five calls per pulled file were redundant. Each is gone only where it could
19
+
not have guarded a file.
20
+
21
+
| Call | Where | Why it cannot lose a file |
22
+
|---|---|---|
23
+
|`deleteFile(backup)` on every write |`NativeCloudSyncContent.write`| A backup exists only when an original was moved aside (`before`). A new file never makes one, so the delete always failed into its `.catch`. Replacing a file still deletes its backup. |
24
+
|`stat(temporary)` after publishing | same | A rename that resolved moved the temporary onto the path. Capacitor's local rename either `renameTo`s or copies and then deletes the source, rejecting if that delete fails; SAF moves the document. Every path that did not publish still checks and removes the temporary. |
25
+
|`readdir(.zennotes/sync)` on every write |`assertReady`| Recovery files are now relisted only when one may have appeared: after a write that failed, after a backup that would not delete, and after any staged publish (which keeps its own backups). The first write, every scan and every staged download still list first. A completed write that removed its backup leaves nothing to find. |
26
+
|`Filesystem.getUri` before every `inspect` (local tier) |`NativeFs.readForSync`|`getUri` names a file by the root's URI plus the path with each segment escaped exactly as `encodeURIComponent` does. The root is resolved once at open, and the shortcut is used only for the same `Directory` it was resolved in; otherwise, and before open, it asks `getUri` as before. Checked on the emulator for 13 awkward names: identical strings and identical bytes. SAF vaults still stat for their document URI. |
27
+
|`mkdir(parent)` before every rename |`hostVault` in `mobile-cloud-sync.ts`| Each sync operation remembers the folders it has made. A rename into a folder that went missing fails before it changes anything (Capacitor checks the parent first; SAF makes it), and the cache forgets that folder so the next rename makes it again. The next sync starts with an empty cache. |
28
+
29
+
Kept as they were: the pre-publish `stat(path)` (a new file must still be
30
+
absent), both verifies (the temporary before publishing, the path after),
31
+
the original's verify before it moves aside, and every rollback.
32
+
33
+
One stricter behavior: a staged publish (large or referenced files) whose
34
+
rollback copy would not delete now stops the next write in the same run
35
+
with "Cloud sync needs recovery". Before, the run went on and the next sync's
36
+
scan stopped at the same file, so the user lands in the same place one step
37
+
sooner, the same way an inline write's leftover backup already behaved.
0 commit comments