| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- Settings = require "settings-sharelatex"
- async = require "async"
- _ = require "underscore"
- {db, ObjectId, BSON} = require "./mongojs"
- fs = require "fs"
- Metrics = require "metrics-sharelatex"
- Metrics.initialize("track-changes")
- logger = require "logger-sharelatex"
- logger.initialize("track-changes-packworker")
- if Settings.sentry?.dsn?
- logger.initializeErrorReporting(Settings.sentry.dsn)
- DAYS = 24 * 3600 * 1000
- LockManager = require "./LockManager"
- PackManager = require "./PackManager"
- # this worker script is forked by the main process to look for
- # document histories which can be archived
- source = process.argv[2]
- DOCUMENT_PACK_DELAY = Number(process.argv[3]) || 1000
- TIMEOUT = Number(process.argv[4]) || 30*60*1000
- COUNT = 0 # number processed
- TOTAL = 0 # total number to process
- if !source.match(/^[0-9]+$/)
- file = fs.readFileSync source
- result = for line in file.toString().split('\n')
- [project_id, doc_id] = line.split(' ')
- {doc_id, project_id}
- pending = _.filter result, (row) -> row?.doc_id?.match(/^[a-f0-9]{24}$/)
- else
- LIMIT = Number(process.argv[2]) || 1000
- shutDownRequested = false
- shutDownTimer = setTimeout () ->
- logger.log "pack timed out, requesting shutdown"
- # start the shutdown on the next pack
- shutDownRequested = true
- # do a hard shutdown after a further 5 minutes
- hardTimeout = setTimeout () ->
- logger.error "HARD TIMEOUT in pack archive worker"
- process.exit()
- , 5*60*1000
- hardTimeout.unref()
- , TIMEOUT
- logger.log "checking for updates, limit=#{LIMIT}, delay=#{DOCUMENT_PACK_DELAY}, timeout=#{TIMEOUT}"
- # work around for https://github.com/mafintosh/mongojs/issues/224
- db.close = (callback) ->
- this._getServer (err, server) ->
- return callback(err) if err?
- server = if server.destroy? then server else server.topology
- server.destroy(true, true)
- callback()
- finish = () ->
- if shutDownTimer?
- logger.log 'cancelling timeout'
- clearTimeout shutDownTimer
- logger.log 'closing db'
- db.close () ->
- logger.log 'closing LockManager Redis Connection'
- LockManager.close () ->
- logger.log {processedCount: COUNT, allCount: TOTAL}, 'ready to exit from pack archive worker'
- hardTimeout = setTimeout () ->
- logger.error 'hard exit from pack archive worker'
- process.exit(1)
- , 5*1000
- hardTimeout.unref()
- process.on 'exit', (code) ->
- logger.log {code}, 'pack archive worker exited'
- processUpdates = (pending) ->
- async.eachSeries pending, (result, callback) ->
- {_id, project_id, doc_id} = result
- COUNT++
- logger.log {project_id, doc_id}, "processing #{COUNT}/#{TOTAL}"
- if not project_id? or not doc_id?
- logger.log {project_id, doc_id}, "skipping pack, missing project/doc id"
- return callback()
- handler = (err, result) ->
- if err? and err.code is "InternalError" and err.retryable
- logger.warn {err, result}, "ignoring S3 error in pack archive worker"
- # Ignore any s3 errors due to random problems
- err = null
- if err?
- logger.error {err, result}, "error in pack archive worker"
- return callback(err)
- if shutDownRequested
- logger.warn "shutting down pack archive worker"
- return callback(new Error("shutdown"))
- setTimeout () ->
- callback(err, result)
- , DOCUMENT_PACK_DELAY
- if not _id?
- PackManager.pushOldPacks project_id, doc_id, handler
- else
- PackManager.processOldPack project_id, doc_id, _id, handler
- , (err, results) ->
- if err? and err.message != "shutdown"
- logger.error {err}, 'error in pack archive worker processUpdates'
- finish()
- # find the packs which can be archived
- ObjectIdFromDate = (date) ->
- id = Math.floor(date.getTime() / 1000).toString(16) + "0000000000000000";
- return ObjectId(id)
- # new approach, two passes
- # find packs to be marked as finalised:true, those which have a newer pack present
- # then only consider finalised:true packs for archiving
- if pending?
- logger.log "got #{pending.length} entries from #{source}"
- processUpdates pending
- else
- oneWeekAgo = new Date(Date.now() - 7 * DAYS)
- db.docHistory.find({
- expiresAt: {$exists: false}
- project_id: {$exists: true}
- v_end: {$exists: true}
- _id: {$lt: ObjectIdFromDate(oneWeekAgo)}
- last_checked: {$lt: oneWeekAgo}
- }, {_id:1, doc_id:1, project_id:1}).sort({
- last_checked:1
- }).limit LIMIT, (err, results) ->
- if err?
- logger.log {err}, 'error checking for updates'
- finish()
- return
- pending = _.uniq results, false, (result) -> result.doc_id.toString()
- TOTAL = pending.length
- logger.log "found #{TOTAL} documents to archive"
- processUpdates pending
|