[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
This commit is contained in:
Jakob Ackermann
2026-04-15 08:22:13 +02:00
committed by Copybot
parent 917d2700c8
commit 5a6c066847
25 changed files with 786 additions and 32 deletions

View File

@@ -163,6 +163,80 @@ class MeteredStream extends Transform {
}
}
class IncrementalResponse {
#res
#ac
#timeout
#logger
#label
#info
constructor({ res, timeout, label, info, logger }) {
this.#res = res
this.#logger = logger
this.#label = label
this.#info = info
this.#ac = new AbortController()
this.#timeout = setTimeout(() => {
this.#logger.warn({ ...this.#info, timeout }, `${this.#label}: aborting`)
this.sendUpdate(
`error: ${label}: aborting after ${this.#humanReadableTimeout(timeout)}`
)
this.#ac.abort()
}, timeout)
}
signal() {
return this.#ac.signal
}
end() {
this.#ac.abort()
clearTimeout(this.#timeout)
try {
this.#res.end()
} catch {
try {
this.#res.destroy()
} catch {}
}
}
sendUpdate(msg) {
try {
this.#res.write(msg + '\n')
} catch (err) {
this.#ac.abort()
this.#logger.warn(
{ err, ...this.#info },
`${this.#label}: failed to send progress update`
)
}
}
fail(err) {
const aborted = this.#ac.signal.aborted
this.#ac.abort()
if (!aborted) {
this.#logger.err({ err, ...this.#info }, `${this.#label}: error`)
this.sendUpdate(`error: ${this.#label}`)
}
this.end()
}
#humanReadableTimeout(timeout) {
let ms = timeout
const minutes = Math.floor(ms / 60_000)
ms -= minutes * 60_000
const seconds = Math.floor(ms / 1_000)
ms -= seconds * 1_000
let t = ''
if (minutes) t += `${minutes}min`
if (seconds) t += `${seconds}s`
if (ms) t += `${ms}ms`
return t
}
}
// Export our classes
module.exports = {
@@ -174,4 +248,5 @@ module.exports = {
MeteredStream,
SizeExceededError,
AbortError,
IncrementalResponse,
}