| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- /* eslint-disable
- no-unused-vars,
- */
- // TODO: This file was created by bulk-decaffeinate.
- // Fix any style issues and re-enable lint.
- /*
- * decaffeinate suggestions:
- * DS101: Remove unnecessary use of Array.from
- * DS102: Remove unnecessary code created because of implicit returns
- * DS207: Consider shorter variations of null checks
- * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
- */
- let ShareJsDB
- const logger = require('@overleaf/logger')
- const Metrics = require('@overleaf/metrics')
- const Keys = require('./UpdateKeys')
- const RedisManager = require('./RedisManager')
- const Errors = require('./Errors')
- const TRANSFORM_UPDATES_COUNT_BUCKETS = [
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 50, 75, 100,
- // prepare buckets for full-project history/larger buffer experiments
- 150, 200, 300, 400,
- ]
- module.exports = ShareJsDB = class ShareJsDB {
- constructor(projectId, docId, lines, version) {
- this.project_id = projectId
- this.doc_id = docId
- this.lines = lines
- this.version = version
- this.appliedOps = {}
- // ShareJS calls this detacted from the instance, so we need
- // bind it to keep our context that can access @appliedOps
- this.writeOp = this._writeOp.bind(this)
- this.startTimeShareJsDB = performance.now()
- }
- getOps(docKey, start, end, callback) {
- if (start === end || (start === this.version && end === null)) {
- const status = 'is-up-to-date'
- Metrics.inc('transform-updates', 1, {
- status,
- path: 'sharejs',
- })
- Metrics.histogram(
- 'transform-updates.count',
- 0,
- TRANSFORM_UPDATES_COUNT_BUCKETS,
- { path: 'sharejs', status }
- )
- return callback(null, [])
- }
- // In redis, lrange values are inclusive.
- if (end != null) {
- end--
- } else {
- end = -1
- }
- const [projectId, docId] = Array.from(Keys.splitProjectIdAndDocId(docKey))
- const timer = new Metrics.Timer(
- 'transform-updates.timing',
- 1,
- { path: 'sharejs' },
- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 50, 100, 200, 500, 1000]
- )
- RedisManager.getPreviousDocOps(docId, start, end, (err, ops) => {
- let status
- if (err) {
- if (err instanceof Errors.OpRangeNotAvailableError) {
- status = 'out-of-range'
- } else {
- status = 'error'
- }
- } else {
- if (ops.length === 0) {
- status = 'fetched-zero'
- // The sharejs processing is happening under a lock.
- // In case there are no other ops available, something bypassed the lock (or we overran it).
- logger.warn(
- {
- projectId,
- docId,
- start,
- end,
- timeSinceShareJsDBInit:
- performance.now() - this.startTimeShareJsDB,
- },
- 'found zero docOps while transforming update'
- )
- } else {
- status = 'fetched'
- }
- Metrics.histogram(
- 'transform-updates.count',
- ops.length,
- TRANSFORM_UPDATES_COUNT_BUCKETS,
- { path: 'sharejs', status }
- )
- }
- timer.done({ status })
- Metrics.inc('transform-updates', 1, { status, path: 'sharejs' })
- callback(err, ops)
- })
- }
- _writeOp(docKey, opData, callback) {
- if (this.appliedOps[docKey] == null) {
- this.appliedOps[docKey] = []
- }
- this.appliedOps[docKey].push(opData)
- return callback()
- }
- getSnapshot(docKey, callback) {
- if (
- docKey !== Keys.combineProjectIdAndDocId(this.project_id, this.doc_id)
- ) {
- return callback(
- new Errors.NotFoundError(
- `unexpected doc_key ${docKey}, expected ${Keys.combineProjectIdAndDocId(
- this.project_id,
- this.doc_id
- )}`
- )
- )
- } else {
- return callback(null, {
- snapshot: this.lines.join('\n'),
- v: parseInt(this.version, 10),
- type: 'text',
- })
- }
- }
- // To be able to remove a doc from the ShareJS memory
- // we need to called Model::delete, which calls this
- // method on the database. However, we will handle removing
- // it from Redis ourselves
- delete(docName, dbMeta, callback) {
- return callback()
- }
- }
|