EventLogger.test.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import { vi, expect, describe, beforeEach, afterEach, it } from 'vitest'
  2. import sinon from 'sinon'
  3. import tk from 'timekeeper'
  4. const modulePath = '../../../app/js/EventLogger'
  5. describe('EventLogger', function () {
  6. beforeEach(async function (ctx) {
  7. ctx.start = Date.now()
  8. tk.freeze(new Date(ctx.start))
  9. vi.doMock('@overleaf/metrics', () => ({
  10. default: (ctx.metrics = { inc: sinon.stub() }),
  11. }))
  12. ctx.EventLogger = (await import(modulePath)).default
  13. ctx.channel = 'applied-ops'
  14. ctx.id_1 = 'random-hostname:abc-1'
  15. ctx.message_1 = 'message-1'
  16. ctx.id_2 = 'random-hostname:abc-2'
  17. ctx.message_2 = 'message-2'
  18. })
  19. afterEach(function () {
  20. tk.reset()
  21. })
  22. describe('checkEventOrder', function () {
  23. describe('when the events are in order', function () {
  24. beforeEach(function (ctx) {
  25. ctx.EventLogger.checkEventOrder(ctx.channel, ctx.id_1, ctx.message_1)
  26. ctx.status = ctx.EventLogger.checkEventOrder(
  27. ctx.channel,
  28. ctx.id_2,
  29. ctx.message_2
  30. )
  31. })
  32. it('should accept events in order', function (ctx) {
  33. expect(ctx.status).to.be.undefined
  34. })
  35. it('should increment the valid event metric', function (ctx) {
  36. ctx.metrics.inc
  37. .calledWith(`event.${ctx.channel}.valid`)
  38. .should.equals(true)
  39. })
  40. })
  41. describe('when there is a duplicate events', function () {
  42. beforeEach(function (ctx) {
  43. ctx.EventLogger.checkEventOrder(ctx.channel, ctx.id_1, ctx.message_1)
  44. ctx.status = ctx.EventLogger.checkEventOrder(
  45. ctx.channel,
  46. ctx.id_1,
  47. ctx.message_1
  48. )
  49. })
  50. it('should return "duplicate" for the same event', function (ctx) {
  51. expect(ctx.status).to.equal('duplicate')
  52. })
  53. it('should increment the duplicate event metric', function (ctx) {
  54. ctx.metrics.inc
  55. .calledWith(`event.${ctx.channel}.duplicate`)
  56. .should.equals(true)
  57. })
  58. })
  59. describe('when there are out of order events', function () {
  60. beforeEach(function (ctx) {
  61. ctx.EventLogger.checkEventOrder(ctx.channel, ctx.id_1, ctx.message_1)
  62. ctx.EventLogger.checkEventOrder(ctx.channel, ctx.id_2, ctx.message_2)
  63. ctx.status = ctx.EventLogger.checkEventOrder(
  64. ctx.channel,
  65. ctx.id_1,
  66. ctx.message_1
  67. )
  68. })
  69. it('should return "out-of-order" for the event', function (ctx) {
  70. expect(ctx.status).to.equal('out-of-order')
  71. })
  72. it('should increment the out-of-order event metric', function (ctx) {
  73. ctx.metrics.inc
  74. .calledWith(`event.${ctx.channel}.out-of-order`)
  75. .should.equals(true)
  76. })
  77. })
  78. describe('after MAX_STALE_TIME_IN_MS', function () {
  79. it('should flush old entries', function (ctx) {
  80. let status
  81. ctx.EventLogger.MAX_EVENTS_BEFORE_CLEAN = 10
  82. ctx.EventLogger.checkEventOrder(ctx.channel, ctx.id_1, ctx.message_1)
  83. for (let i = 1; i <= 8; i++) {
  84. status = ctx.EventLogger.checkEventOrder(
  85. ctx.channel,
  86. ctx.id_1,
  87. ctx.message_1
  88. )
  89. expect(status).to.equal('duplicate')
  90. }
  91. // the next event should flush the old entries aboce
  92. ctx.EventLogger.MAX_STALE_TIME_IN_MS = 1000
  93. tk.freeze(new Date(ctx.start + 5 * 1000))
  94. // because we flushed the entries this should not be a duplicate
  95. ctx.EventLogger.checkEventOrder(ctx.channel, 'other-1', ctx.message_2)
  96. status = ctx.EventLogger.checkEventOrder(
  97. ctx.channel,
  98. ctx.id_1,
  99. ctx.message_1
  100. )
  101. expect(status).to.be.undefined
  102. })
  103. })
  104. })
  105. })