pack.coffee 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. Settings = require "settings-sharelatex"
  2. fs = require("fs")
  3. {db, ObjectId} = require "./app/coffee/mongojs"
  4. async = require("async")
  5. BSON=db.bson.BSON
  6. util = require 'util'
  7. _ = require 'underscore'
  8. PackManager = require "./app/coffee/PackManager.coffee"
  9. lineReader = require "line-reader"
  10. cli = require "cli"
  11. options = cli.parse {
  12. 'update': ['u', 'find documents to pack from database']
  13. 'dry-run': ['n', 'do not write to database'],
  14. 'fast': [false, 'no delays on writes']
  15. }
  16. DB_WRITE_DELAY = if options.fast then 0 else 2000
  17. DOCUMENT_PACK_DELAY = if options.fast then 0 else 1000
  18. packDocHistory = (doc_id, callback) ->
  19. util.log "starting pack operation for #{doc_id}"
  20. getDocHistory doc_id, (err, docs) ->
  21. return callback(err) if err?
  22. origDocs = 0
  23. origPacks = 0
  24. for d in docs
  25. if d.pack? then origPacks++ else origDocs++
  26. PackManager.convertDocsToPacks docs, (err, packs) ->
  27. return callback(err) if err?
  28. total = 0
  29. for p in packs
  30. total = total + p.pack.length
  31. util.log "docs #{origDocs} packs #{origPacks} => packs #{packs.length} of #{total} ops"
  32. if packs.length
  33. if options['dry-run']
  34. util.log 'dry-run, skipping write packs'
  35. return callback()
  36. savePacks packs, (err) ->
  37. return callback(err) if err?
  38. # check the history again
  39. getDocHistory doc_id, callback
  40. else
  41. util.log "no packs to write"
  42. callback null, null
  43. # retrieve document ops/packs and check them
  44. getDocHistory = (doc_id, callback) ->
  45. db.docHistory.find({doc_id:ObjectId(doc_id)}).sort {v:1}, (err, docs) ->
  46. return callback(err) if err?
  47. # for safety, do a consistency check of the history
  48. util.log "checking history for #{doc_id}"
  49. PackManager.checkHistory docs, (err) ->
  50. return callback(err) if err?
  51. callback(err, docs)
  52. #PackManager.deleteExpiredPackOps docs, (err) ->
  53. # return callback(err) if err?
  54. # callback err, docs
  55. safeInsert = (packObj, callback) ->
  56. if shutdownRequested
  57. return callback('shutdown')
  58. PackManager.insertPack packObj, (err, result) ->
  59. setTimeout () ->
  60. callback(err,result)
  61. , DB_WRITE_DELAY
  62. savePacks = (packs, callback) ->
  63. async.eachSeries packs, safeInsert, (err, result) ->
  64. if err?
  65. util.log "error writing packs"
  66. callback err, result
  67. else
  68. util.log "done writing packs"
  69. callback()
  70. readFile = (file, callback) ->
  71. ids = []
  72. lineReader.eachLine file, (line) ->
  73. result = line.match(/[0-9a-f]{24}/)
  74. if result?
  75. ids.push result[0]
  76. .then () ->
  77. callback(null, ids)
  78. shutdownRequested = false
  79. process.on 'SIGINT', () ->
  80. util.log "Gracefully shutting down from SIGINT"
  81. shutdownRequested = true
  82. processUpdates = (pending) ->
  83. async.eachSeries pending, (doc_id, callback) ->
  84. packDocHistory doc_id, (err, result) ->
  85. if err?
  86. console.log "ERROR:", err, result
  87. return callback(err)
  88. else if not options['dry-run'] && doneFile?
  89. fs.appendFileSync doneFile, doc_id + '\n'
  90. if shutdownRequested
  91. return callback('shutdown')
  92. setTimeout () ->
  93. callback(err, result)
  94. , DOCUMENT_PACK_DELAY
  95. , (err, results) ->
  96. if err?
  97. console.log 'error:', err
  98. util.log 'closing db'
  99. db.close()
  100. if options['update']
  101. util.log 'checking for updates'
  102. db.docHistoryStats.find({
  103. update_count: {$gt : PackManager.MIN_COUNT}
  104. }).sort({
  105. update_count:-1
  106. }).limit 1000, (error, results) ->
  107. if err?
  108. utils.log 'error', error
  109. db.close()
  110. return
  111. util.log "found #{results.length} documents to pack"
  112. pending = _.pluck results, 'doc_id'
  113. processUpdates pending
  114. else
  115. todoFile = cli.args[1]
  116. doneFile = cli.args[2]
  117. util.log "reading from #{todoFile}"
  118. util.log "logging progress to #{doneFile}"
  119. fs.appendFileSync doneFile, '# starting pack run at ' + new Date() + '\n'
  120. readFile todoFile, (err, todo) ->
  121. readFile doneFile, (err, done) ->
  122. pending = _.difference todo, done
  123. processUpdates pending