rollout.js 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. const crypto = require('node:crypto')
  2. class Rollout {
  3. constructor(config) {
  4. // The history buffer level is used to determine whether to queue changes
  5. // in Redis or persist them directly to the chunk store.
  6. // If defaults to 0 (no queuing) if not set.
  7. this.historyBufferLevel = config.has('historyBufferLevel')
  8. ? parseInt(config.get('historyBufferLevel'), 10)
  9. : 0
  10. // The forcePersistBuffer flag will ensure the buffer is fully persisted before
  11. // any persist operation. Set this to true if you want to make the persisted-version
  12. // in Redis match the endVersion of the latest chunk. This should be set to true
  13. // when downgrading from a history buffer level that queues changes in Redis
  14. // without persisting them immediately.
  15. this.forcePersistBuffer = config.has('forcePersistBuffer')
  16. ? config.get('forcePersistBuffer') === 'true'
  17. : false
  18. // Support gradual rollout of the next history buffer level
  19. // with a percentage of projects using it.
  20. this.nextHistoryBufferLevel = config.has('nextHistoryBufferLevel')
  21. ? parseInt(config.get('nextHistoryBufferLevel'), 10)
  22. : null
  23. this.nextHistoryBufferLevelRolloutPercentage = config.has(
  24. 'nextHistoryBufferLevelRolloutPercentage'
  25. )
  26. ? parseInt(config.get('nextHistoryBufferLevelRolloutPercentage'), 10)
  27. : 0
  28. }
  29. report(logger) {
  30. logger.info(
  31. {
  32. historyBufferLevel: this.historyBufferLevel,
  33. forcePersistBuffer: this.forcePersistBuffer,
  34. nextHistoryBufferLevel: this.nextHistoryBufferLevel,
  35. nextHistoryBufferLevelRolloutPercentage:
  36. this.nextHistoryBufferLevelRolloutPercentage,
  37. },
  38. this.historyBufferLevel > 0 || this.forcePersistBuffer
  39. ? 'using history buffer'
  40. : 'history buffer disabled'
  41. )
  42. }
  43. /**
  44. * Get the history buffer level for a project.
  45. * @param {string} projectId
  46. * @returns {Object} - An object containing the history buffer level and force persist buffer flag.
  47. * @property {number} historyBufferLevel - The history buffer level to use for processing changes.
  48. * @property {boolean} forcePersistBuffer - If true, forces the buffer to be persisted before any operation.
  49. */
  50. getHistoryBufferLevelOptions(projectId) {
  51. if (
  52. this.nextHistoryBufferLevel > this.historyBufferLevel &&
  53. this.nextHistoryBufferLevelRolloutPercentage > 0
  54. ) {
  55. const hash = crypto.createHash('sha1').update(projectId).digest('hex')
  56. const percentage = parseInt(hash.slice(0, 8), 16) % 100
  57. // If the project is in the rollout percentage, we use the next history buffer level.
  58. if (percentage < this.nextHistoryBufferLevelRolloutPercentage) {
  59. return {
  60. historyBufferLevel: this.nextHistoryBufferLevel,
  61. forcePersistBuffer: this.forcePersistBuffer,
  62. }
  63. }
  64. }
  65. return {
  66. historyBufferLevel: this.historyBufferLevel,
  67. forcePersistBuffer: this.forcePersistBuffer,
  68. }
  69. }
  70. }
  71. module.exports = Rollout