Cache.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.Cache = void 0;
  4. const noop = () => { };
  5. class Cache {
  6. constructor(method = noop) {
  7. this.method = method;
  8. this.ttl = 10000; // Time how long item is kept in cache without refreshing.
  9. this.evictionTime = 20000; // After this time item is evicted from cache.
  10. this.gcPeriod = 30000; // How often to run GC.
  11. this.maxEntries = 100000;
  12. this.entries = 0; // Number of values in cache.
  13. this.map = new Map();
  14. this.runGC = () => {
  15. const now = Date.now();
  16. for (const key of this.map.keys()) {
  17. const entry = this.map.get(key);
  18. if (entry && now - entry.t >= this.evictionTime) {
  19. this.map.delete(key);
  20. this.entries--;
  21. }
  22. }
  23. this.scheduleGC();
  24. };
  25. this.stopGC = () => {
  26. clearTimeout(this.timer);
  27. };
  28. }
  29. put(key, value) {
  30. const entry = {
  31. t: Date.now(),
  32. value,
  33. };
  34. if (this.map.get(key)) {
  35. this.map.set(key, entry);
  36. }
  37. else {
  38. this.map.set(key, entry);
  39. this.entries++;
  40. }
  41. if (this.entries > this.maxEntries) {
  42. for (const iterationKey of this.map.keys()) {
  43. if (key !== iterationKey) {
  44. this.map.delete(iterationKey);
  45. this.entries--;
  46. break;
  47. }
  48. }
  49. }
  50. }
  51. async getFromSource(key) {
  52. const value = await this.method(key);
  53. this.put(key, value);
  54. return value;
  55. }
  56. async get(key) {
  57. const entry = this.map.get(key);
  58. if (entry) {
  59. const now = Date.now();
  60. if (now - entry.t <= this.ttl) {
  61. return entry.value;
  62. }
  63. else if (now - entry.t <= this.evictionTime) {
  64. this.getFromSource(key).catch(noop);
  65. return entry.value;
  66. }
  67. else {
  68. this.map.delete(key);
  69. this.entries--;
  70. return await this.getFromSource(key);
  71. }
  72. }
  73. else {
  74. return await this.getFromSource(key);
  75. }
  76. }
  77. getSync(key) {
  78. const entry = this.map.get(key);
  79. if (!entry)
  80. return null;
  81. const now = Date.now();
  82. if (now - entry.t <= this.ttl) {
  83. return entry.value;
  84. }
  85. else if (now - entry.t <= this.evictionTime) {
  86. this.getFromSource(key).catch(noop);
  87. return entry.value;
  88. }
  89. return null;
  90. }
  91. exists(key) {
  92. const entry = this.map.get(key);
  93. if (!entry)
  94. return false;
  95. const now = Date.now();
  96. return now - entry.t <= this.evictionTime;
  97. }
  98. scheduleGC() {
  99. this.timer = setTimeout(this.runGC, this.gcPeriod);
  100. this.timer.unref();
  101. }
  102. startGC() {
  103. this.scheduleGC();
  104. }
  105. retire(key, newTime = 0) {
  106. const entry = this.map.get(key);
  107. if (!entry)
  108. return false;
  109. entry.t = newTime;
  110. return true;
  111. }
  112. remove(key) {
  113. const success = this.map.delete(key);
  114. if (success)
  115. this.entries--;
  116. return success;
  117. }
  118. }
  119. exports.Cache = Cache;