Commit Graph
57 Commits
Author SHA1 Message Date
Jakob AckermannandClaude Opus 5 04871d6049 [editor-core] extract more shared utils (#36954)
* [editor-core] share the blob hash and the doc-vs-file rule

The git blob hash and the rule that decides whether a file is a doc or a binary
file both have to reach the same answer in every service that writes to history,
so they move into overleaf-editor-core rather than being spelled out again on
each side.

blob_utils takes over lib/blob_string_length.js: hashing and the string-length
rule answered two halves of the same question -- what history needs to know
about content before it can store it -- and each carried the same warning about
staying off index.js, which is bundled for the browser. One module states it
once, and blobForFile joins them, describing content on disk as the blob it
amounts to. The hashing functions are flat rather than a namespace of their own:
in a module that also holds the string-length rule, a bare fromStream says
nothing about what it makes. history-v1's blob store and recover_zip follow the
module to its new name.

file_type_detector holds the doc-vs-file rule, Node-only and deep-imported for
the same reason. It takes textExtensions, editableFilenames and maxDocLength as
configuration rather than reading settings: the limit is web's 2 MiB and not
editor-core's own 3 MiB, and the surrogate check covers both halves of a pair
where editor-core's covers the high half.

buildSetContentOperations' test spelled the blob header out for itself, with the
separator as a literal NUL byte, which had git reading the file as binary. It
hashes through blobHashFromString now, so it does not spell the header at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* [editor-core] name the client a change came from on the origin itself

`EditorOrigin` carried an `editorId` that only an editor change could have. What
the id is for -- recognising a change again, so history does not apply a resend
twice and the client does not apply its own change back -- is a property of the
client that submitted it rather than of what it did, so it moves onto `Origin` as
an optional `historyClientId` and `EditorOrigin` goes.

- `Origin` takes `(kind, historyClientId)` and answers `getHistoryClientId()`;
  `dropHistoryClientId()` is what the chunk store uses to strip the id from all
  but a client's latest change, which now leaves the rest of the origin alone --
  a restore that a client submitted stays a restore.
- `toRaw` is built a layer at a time: the base writes the kind and the id, a
  subclass spreads that and adds the fields it owns.
- The named kinds are their own schemas and discriminate on `kind`, so a payload
  claiming one is checked against that shape and the error says what it got
  wrong. The catch-all cannot join them -- its kind is any string -- so it sits
  alongside and is refined to refuse the named kinds, which it used to swallow:
  `{kind: 'restore'}` validated as a kind and nothing else, then read back as a
  restore that recorded nothing about what it restored.
- `lib/origin/*.js` gains `// @ts-check`. Without it the annotations in there
  were decorative: the lazily required subclasses were `any`, so nothing handed
  to them was checked, and `fromRaw` narrows with `in` to drop the catch-all
  variant, which a kind check cannot.

The callers that stamp the id -- real-time's handshake flag, web's applyChange
body -- come with the rest of the branch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* [editor-core] recognise a change a writer that is not an editor placed

The counterpart of `isSameEditorChange` for writers that are not an editor
client: an integration that commits a batch on a user's behalf has to recognise
that batch coming back, because a lost response does not say whether the commit
landed and resubmitting one that did applies its removes twice.

It compares the same three fields, and for the same reason -- a rebase rewrites a
change's operations but leaves its origin, authors and timestamp alone -- with
the timestamp compared as a point in time rather than as a string, so that two
spellings of the same instant cannot read as different changes. github-sync is
the first caller, and comes with the rest of the branch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* [editor-core] load an editable file's content, or say it has none

Only an editable file has content: any other kind is bytes addressed by hash, and
hollow data records the size of content it does not have. Both answer
`getContent()` with null, so every caller that wants the content of a doc loaded
it, checked the data's class, and reached for its own error when the check failed.
`File#loadEager` does that once and answers the data that always has the content.

`buildSetContentOperations` takes a `ReadWriteBlobStore` -- everything but
looking a blob up by hash, which is all it takes to build operations over content
-- so a caller holding a store that cannot answer `getBlob` can still use it. Its
metadata argument is `FileMetadata` rather than `Object`, which is what the schema
already says a file's metadata is.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* [editor-core] say that a pair of operations that do not fit is unprocessable

compose and transform threw a bare Error when the two operations do not describe
the same content. Everything that answers a client for these -- history-v1's
import routes, the git-bridge push, project-history's resync -- decides on
UnprocessableError, so a bare Error reached them as an internal failure: a 500,
which reads as worth retrying, for a pair that fails the same way every time.
A client that resubmits on a 500 resubmits forever.

The guards that cannot be reached through the API keep their bare Error: a
TextOperation composed with something that is not one, and the branch whose
message says it should not happen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* [history-v1] hash blobs with the rule editor-core holds

storage/lib/blob_hash.js was a bluebird-era implementation of the same git blob
hash editor-core holds, exported from the storage barrel and used across the
storage layer, the api and the tests. All of it reads the shared rule now, and
the test that existed only to check the copy is gone -- editor-core's suite
covers the same non-ASCII case.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
GitOrigin-RevId: 5a0c1e9a06170a0164c01a26a7bb2d205726d531
2026-09-17 12:07:15 +00:00
Anna Claire Fields b8339c5b4a history-v1: handle ERR_STREAM_PREMATURE_CLOSE in streamZip (#36135)
GitOrigin-RevId: 963b65583da58034afe304206f6e0c66e9186b06
2026-09-17 11:49:33 +00:00
Jakob Ackermann 49969f6e0d [history-v1] adopt strict zod types and extend test coverage (#36089)
GitOrigin-RevId: 7bdffe2c05c7c17be6eb3e4296d8df05d650c53e
2026-09-17 11:49:08 +00:00
Jakob Ackermann a77a4782cc [history-v1] add setContent endpoint (#35799)
* [history-v1] add setContent endpoint

* [history-v1] refactor setContent to return a change+v

* [history-v1] make typescript happy

GitOrigin-RevId: e2cb0281367c01aa9cd842f250f2016d591ec0fc
2026-09-17 11:39:09 +00:00
Jakob AckermannandBrian Gough 84c6a68eae [web] enforce size limit on individual files when cloning project (#35211)
* [web] enforce size limit on individual files when cloning project

Co-authored-by: Brian Gough <brian.gough@overleaf.com>

* [web] improve test coverage

* [agents] speed up running frontend tests

* [web] gracefully handle project too large error

---------

Co-authored-by: Brian Gough <brian.gough@overleaf.com>
GitOrigin-RevId: c7b35a3a9688e15a9bb51c61816da82d39e0d29d
2026-09-17 11:20:03 +00:00
Jakob Ackermann d610f404e7 [history-v1] increase timeout for downloading the latest content as zip (#34045)
Remove the default timeout as it's too low and a big footgun.

GitOrigin-RevId: 42e26a2a288ad3e38252bc98b909a4bc8b10f70c
2026-05-28 08:06:47 +00:00
Jakob Ackermann 7c50dc9990 [history-v1] add endpoint for downloading latest zip (#33181)
* [history-v1] add endpoint for downloading latest zip

* [web] address review feedback

* [web] tests: do not overwrite db.projects.overleaf, extend it

* [web] set includeReferer flag from downloading zip

GitOrigin-RevId: e63e549f004230086f82eccf03b43fd62bde6071
2026-05-13 08:06:53 +00:00
Jakob Ackermann 5a6c066847 [web] allow admins to clone projects with ranges and entire history (#32739)
* [web] add consistent aria-label to editing/reviewing toggle

* [docstore] add endpoint for getting all docs with ranges

* [history-v1] fix schema of chunkId when deleting old history chunk

* [web] skip duplicate project lookup for resolving rootDocPath

* [web] ignore new limits for root doc path when making debug copy

* [web] allow admins to clone projects with ranges and entire history

* [web] fix tests

* [history-v1] re-order params for cloning project

* [web] fix duplicate import of logger after merge

* [project-history] re-order params for cloning project history metadata

GitOrigin-RevId: 7fa35b4f90885dd453150a348d491ba0ec8de412
2026-04-15 08:05:49 +00:00
Anna Claire Fields ee4b5f515c Handle ERR_STREAM_UNABLE_TO_PIPE alongside ERR_STREAM_PREMATURE_CLOSE (#31174)
GitOrigin-RevId: bbf49237b177d7a58a9b13efc6f38f5eecfb745c
2026-02-03 09:05:50 +00:00
Tim Down 64da16f0d1 Merge pull request #28670 from overleaf/td-rename-validate-req
Rename validateReq to parseReq

GitOrigin-RevId: a935aaa3f89495e164ce5d10b0bd80436571440f
2026-01-15 09:05:09 +00:00
Anna Claire Fields 65c164c73d Merge pull request #30053 from overleaf/acf-migration4-controllers-and-params
(4) Update controllers and tests for Zod migration

GitOrigin-RevId: 876fd64f96e1f5d7244ac1d45053c7db9857d46b
2025-12-16 09:06:44 +00:00
Eric Mc Sween 98069966ba Merge pull request #28672 from overleaf/em-reapply-restore-optimization
Reapply file restore optimization

GitOrigin-RevId: c4479141d890e3e0af746f406a0186bf21f3d918
2025-09-25 08:05:25 +00:00
Domagoj Kriskovic e9b1c63ed7 Revert "File restore optimization - using snapshot timestamp and file paths (#28546)"
This reverts commit 376a53e1f927cb56544e6782b47d80345655038c.

GitOrigin-RevId: 8e4ab1d4042fec8df1b62ab1c5418d873dc6f5eb
2025-09-24 08:06:06 +00:00
Domagoj KriskovicandEric Mc Sween 005eba7502 File restore optimization - using snapshot timestamp and file paths (#28546)
* Use snapshot timestamp, remove request for paths at version

* Add timestamp to core Snapshot object

* Avoid mutating function argument

* Explain assumption about editable files

* snapshot.toRaw() in getContentAtVersion

* fix project-history acceptance test

* fix history_v1 test

* fix web tests

* Include the snapshot timestamp in stored chunks

---------

Co-authored-by: Eric Mc Sween <5454374+emcsween@users.noreply.github.com>
GitOrigin-RevId: 376a53e1f927cb56544e6782b47d80345655038c
2025-09-24 08:06:02 +00:00
Mathias Jakobsen 6c6048002b Merge pull request #28595 from overleaf/revert-28594-revert-28533-mj-blob-ranges-maxsize
[web+history-v1] Retry: Use range request for binary blobs in project snapshot

GitOrigin-RevId: defc279c9918695135962d65603a2941c5c4b033
2025-09-22 08:05:23 +00:00
Mathias Jakobsen 67d10e96bd Merge pull request #28594 from overleaf/revert-28533-mj-blob-ranges-maxsize
Revert "[web+history-v1] Use range request for binary blobs in project snapshot"

GitOrigin-RevId: 580491611a1b43104846f8509dd1e920f8077c9c
2025-09-22 08:05:15 +00:00
Mathias Jakobsen 6c79ce97cc Merge pull request #28533 from overleaf/mj-blob-ranges-maxsize
[web+history-v1] Use range request for binary blobs in project snapshot

GitOrigin-RevId: e72a2d481bf163b3e85361b42e30e82cf867f1cf
2025-09-22 08:05:04 +00:00
Brian Gough fd82788e61 Merge pull request #28506 from overleaf/bg-size-limits
add size check when cloning project (logging only)

GitOrigin-RevId: 1f56ed80a2d05b28c44fab8532d751ad8e758943
2025-09-18 08:05:52 +00:00
Brian Gough 386e133766 Merge pull request #28436 from overleaf/bg-load-changes-directly-from-redis-buffer
load changes directly from redis buffer for getChanges requests

GitOrigin-RevId: 99673c47a137ff4222d331fa88eb6e5103270551
2025-09-12 08:07:35 +00:00
Jakob Ackermann f8d69d05af [web] display project history blob size on admin pages (#28351)
* [history-v1] add endpoint for getting blob stats of projects

* [web] display project history blob size on admin pages

* [web] break down history storage size by text and binary blob

GitOrigin-RevId: bfa4d56cf2c503d03005c13a0f7ac38158156cd2
2025-09-10 08:06:19 +00:00
Brian Gough 8fab1b54a3 Merge pull request #27025 from overleaf/bg-delete-redis-buffer-when-project-deleted
delete redis buffer when project deleted

GitOrigin-RevId: eef7b6fdeb04cb556ae47794379d83e659f89b2e
2025-07-11 08:06:08 +00:00
Jakob Ackermann cf472f54d0 [history-v1] use POST requests for expiring redis buffer from cron (#26568)
* [history-v1] use POST requests for expiring redis buffer from cron

(cherry picked from commit 15780ac54e36b96e1aed9fd9eb6dfe9d4fbf842f)

* [history-v1] remove double claim of expire job

GitOrigin-RevId: 8b2eab07006a5819a47eed3f646b2a4d75f86e5b
2025-07-08 08:05:47 +00:00
Eric Mc Sween a38eefd2ab Merge pull request #26559 from overleaf/em-redis-buffer-delete
Delete project from redis buffer when expiring

GitOrigin-RevId: 66c48adc388a4a4e0b1b54b581dc945a38a41356
2025-06-30 08:05:20 +00:00
Andrew Rumble 392037efd6 Improve types and export functions we want to use
GitOrigin-RevId: 25fd93214f88c425bee23d43de113cf754f89524
2025-06-25 08:06:18 +00:00
Eric Mc Sween 1042092144 Merge pull request #26547 from overleaf/em-revert-expiry-post
Revert "use POST requests for expiring redis buffer from cron"

GitOrigin-RevId: 95e9fd1be7b73699d6fac24035437d467c273d0a
2025-06-19 08:06:58 +00:00
Eric Mc Sween 150dfd6cba Merge pull request #26539 from overleaf/jpa-post
[history-v1] use POST requests for expiring redis buffer from cron

GitOrigin-RevId: 51c9a25b998e581ed20c0e113bd4989537a1e6ef
2025-06-19 08:06:50 +00:00
Eric Mc Sween f68bf5a69f Merge pull request #26477 from overleaf/em-redis-buffer-resync
Handle invalid content hash when persisting changes

GitOrigin-RevId: 5259190396c8c261cad1abcd5de66314c1e871fb
2025-06-18 08:06:17 +00:00
Eric Mc Sween 0f330ef6a3 Merge pull request #26393 from overleaf/bg-history-redis-gradual-rollout
add gradual rollout mechanism for history-v1 rollout

GitOrigin-RevId: 5fa69f5c3874bd5df1f31fdd3115e4ba6a0dab51
2025-06-17 08:06:00 +00:00
Brian Gough 92731848ac Merge pull request #26352 from overleaf/bg-history-redis-add-flush-endpoint
add flush endpoint to history-v1

GitOrigin-RevId: b2ca60f7d040459f9c542e4e87147b9eecc9f596
2025-06-13 08:06:37 +00:00
Brian Gough 8a90173aa7 Merge pull request #26271 from overleaf/bg-history-redis-deployment-refactor
introduce history-v1 buffering levels

GitOrigin-RevId: 7709935a5ceb19ef6c5723ded647217b7399759a
2025-06-12 08:05:39 +00:00
Brian Gough b290e93441 Merge pull request #26270 from overleaf/bg-history-redis-commit-change-manager
replace redis logic in persistChanges with new commitChanges method

GitOrigin-RevId: e06f9477b9d5548fa92ef87fb6e1f4f672001a35
2025-06-11 08:07:45 +00:00
Brian Gough cb350ecc65 Merge pull request #25907 from overleaf/bg-history-redis-persist-buffer
add a `persistBuffer` method to history-v1

GitOrigin-RevId: 71a34e48e9ebe378e2f765f3216023e505a58a5d
2025-06-04 08:06:06 +00:00
Jakob Ackermann 4aaf411cd2 [misc] improve logging in history system (#26086)
* [project-history] tag all the errors

* [history-v1] log warnings for unexpected cases

GitOrigin-RevId: 3189fa487eee88985688ff990ec101daad0d13b1
2025-06-04 08:05:50 +00:00
Eric Mc Sween c18b3f95b2 Merge pull request #25492 from overleaf/em-paginate-changes-1
Paginate history changes endpoint

GitOrigin-RevId: 2b48044d64244404efcd2e090b682c1f571a5567
2025-05-22 08:08:09 +00:00
Miguel Serrano 85533a36e9 [history-v1] Disable backups on CE/SP (#25591)
Disables backup when `backupStore` is not present,
as it's the case for CE/SP

GitOrigin-RevId: a920f041c639e599084fa97d2ef2643a01da70e3
2025-05-19 12:26:30 +00:00
Eric Mc Sween 391fca9e83 Merge pull request #25361 from overleaf/em-load-latest-raw
Rename loadLatestRaw() to getLatestChunkMetadata()

GitOrigin-RevId: e089dcfa57cbbc43df8666b51eca0d81d595a5a7
2025-05-09 08:06:14 +00:00
Eric Mc Sween 5717ea7f5c Merge pull request #25306 from overleaf/em-redis-buffer-read-operations
Add changes from Redis when reading chunks from the chunk store

GitOrigin-RevId: c0ebf0669b91eb2efc5d1091d025e81efdff9fe4
2025-05-09 08:06:09 +00:00
Brian Gough 6eada92966 Merge pull request #25406 from overleaf/em-content-hash-validation-resync
Resync project when content hash validation fails

GitOrigin-RevId: ea9b5a78f89c55276fd67835bc262717bc778e92
2025-05-09 08:05:12 +00:00
Brian Gough 4464320757 Merge pull request #25224 from overleaf/em-disable-chunk-buffer
Bypass chunk buffer when loading the latest chunk

GitOrigin-RevId: 98a15b496b0d52802f9b61cefb60a7b8df653fb2
2025-05-02 08:05:17 +00:00
Brian Gough cedc96bdd7 Merge pull request #24906 from overleaf/bg-history-redis-read-cache
implement read cache for history-v1 chunks

GitOrigin-RevId: 128de7e9380fd489f68d5045d3333a27018845c2
2025-04-16 08:06:18 +00:00
Eric Mc Sween 397a546095 Merge pull request #24895 from overleaf/em-fix-history-changes
Properly serialize changes returned by the history changes endpoint

GitOrigin-RevId: a85fd8aede9316100d2cec901c1ab9b7d1faa9bb
2025-04-15 08:06:19 +00:00
Eric Mc Sween 3aa579f232 Merge pull request #24736 from overleaf/em-history-get-changes
Endpoint for getting history changes

GitOrigin-RevId: b96afed0492522d62df9c24390f76e5490afbb44
2025-04-11 08:05:48 +00:00
Eric Mc Sween 0e9c310d1d Merge pull request #24390 from overleaf/em-enforce-content-hash-validation
Enforce content hash validation in history

GitOrigin-RevId: 90de21ea86ddc6548001059c41139a2af5b27060
2025-03-24 10:50:01 +00:00
Eric Mc Sween e145667a81 Merge pull request #23282 from overleaf/em-async-await-persist-changes
Convert the history changes import code to async/await

GitOrigin-RevId: 6421fcaaf3bac69a3404754f935b4902979b4689
2025-02-07 09:05:44 +00:00
Jakob Ackermann 81aab1e159 [misc] fix logger.error(err) and logger.warn(err) calls (#23369)
* [misc] fix logger.error(err) calls

The signature is "logger.error({ err }, 'MESSAGE')".

* [project-history] remove duplicate logger.err calls in health check

The call-site is already logging any errors. Also, the logger.err call
signature was not quite right.

* [web] log userId when removeDropbox/removeGithub hook fails

* [misc] fix logger.warn(err) calls

The signature is "logger.warn({ err }, 'MESSAGE')".

* [misc] fix logger.error(OError.tag(err)) calls

* [web] make eslint happy

GitOrigin-RevId: 7f528113a3f7e9f6293b7d2d45adc079380325bb
2025-02-06 09:04:31 +00:00
3a4c5a0d0f [history-v1] add readOnly lookup for raw chunks (#23318)
* [history-v1] add readOnly lookup for raw chunks

Co-authored-by: Eric Mc Sween <eric.mcsween@overleaf.com>

* [history-v1] reduce min poolsize for readOnly pool to 0

Co-authored-by: Brian Gough <brian.gough@overleaf.com>

---------

Co-authored-by: Eric Mc Sween <eric.mcsween@overleaf.com>
Co-authored-by: Brian Gough <brian.gough@overleaf.com>
GitOrigin-RevId: a711c4ee4f3ea3775bd090e620d1ef52689fa1f4
2025-02-04 09:04:52 +00:00
Jakob Ackermann c6c623da78 [project-history] script for fixing-up files/metadata with bulk resync (#23184)
* [history-v1] add cheap endpoint for checking time of last history write

The /raw endpoint skips the GCS lookup for the chunk.

* [project-history] script for fixing-up files/metadata with bulk resync

* [project-history] upgrade structure only resync when full sync is needed

* [project-history] start resync and process resync updates under lock

* [project-history] stop retrying during graceful shutdown

GitOrigin-RevId: 73184d5786e1d40f5b7e21f387fc37cf43f0ac2d
2025-02-03 09:05:43 +00:00
Andrew Rumble a92a37bc3c Merge pull request #22466 from overleaf/ar-backup-files-when-inserting
[history-v1] backup files when inserting

GitOrigin-RevId: e636bce178604978c6d41c083bf671795d20b5a1
2024-12-13 09:04:54 +00:00
Andrew Rumble 52254b5695 Merge pull request #22459 from overleaf/revert-22392-ar-backup-files-when-inserting
Revert "[history-v1] backup files when inserting"

GitOrigin-RevId: f21d49dbc8909ab93bdde78c321672124bb13697
2024-12-12 09:05:27 +00:00
Andrew Rumble 6404e3047d Merge pull request #22392 from overleaf/ar-backup-files-when-inserting
[history-v1] backup files when inserting

GitOrigin-RevId: 1649b2828899d67ee37c0ac331917c6d5424c803
2024-12-12 09:05:11 +00:00