DrainManager.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import logger from '@overleaf/logger'
  2. export default {
  3. startDrainTimeWindow(io, minsToDrain, callback) {
  4. const drainPerMin = io.sockets.clients().length / minsToDrain
  5. // enforce minimum drain rate
  6. this.startDrain(io, Math.max(drainPerMin / 60, 4), callback)
  7. },
  8. startDrain(io, rate, callback) {
  9. // Clear out any old interval
  10. clearInterval(this.interval)
  11. logger.info({ rate }, 'starting drain')
  12. if (rate === 0) {
  13. return
  14. }
  15. let pollingInterval
  16. if (rate < 1) {
  17. // allow lower drain rates
  18. // e.g. rate=0.1 will drain one client every 10 seconds
  19. pollingInterval = 1000 / rate
  20. rate = 1
  21. } else {
  22. pollingInterval = 1000
  23. }
  24. this.interval = setInterval(() => {
  25. const requestedAllClientsToReconnect = this.reconnectNClients(io, rate)
  26. if (requestedAllClientsToReconnect && callback) {
  27. callback()
  28. callback = undefined
  29. }
  30. }, pollingInterval)
  31. },
  32. RECONNECTED_CLIENTS: {},
  33. reconnectNClients(io, N) {
  34. let drainedCount = 0
  35. for (const client of io.sockets.clients()) {
  36. if (!this.RECONNECTED_CLIENTS[client.id]) {
  37. this.RECONNECTED_CLIENTS[client.id] = true
  38. logger.debug(
  39. { clientId: client.id },
  40. 'Asking client to reconnect gracefully'
  41. )
  42. client.emit('reconnectGracefully')
  43. drainedCount++
  44. }
  45. const haveDrainedNClients = drainedCount === N
  46. if (haveDrainedNClients) {
  47. break
  48. }
  49. }
  50. if (drainedCount < N) {
  51. logger.info('All clients have been told to reconnectGracefully')
  52. return true
  53. }
  54. return false
  55. },
  56. }