@zeitar/throttle 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/LICENSE.md +24 -0
  2. package/README.md +204 -0
  3. package/dist/CompoundLimiter.d.ts +33 -0
  4. package/dist/CompoundLimiter.d.ts.map +1 -0
  5. package/dist/CompoundLimiter.js +62 -0
  6. package/dist/CompoundLimiter.js.map +1 -0
  7. package/dist/CompoundRateLimiterFactory.d.ts +19 -0
  8. package/dist/CompoundRateLimiterFactory.d.ts.map +1 -0
  9. package/dist/CompoundRateLimiterFactory.js +29 -0
  10. package/dist/CompoundRateLimiterFactory.js.map +1 -0
  11. package/dist/LimiterInterface.d.ts +32 -0
  12. package/dist/LimiterInterface.d.ts.map +1 -0
  13. package/dist/LimiterInterface.js +3 -0
  14. package/dist/LimiterInterface.js.map +1 -0
  15. package/dist/LimiterStateInterface.d.ts +16 -0
  16. package/dist/LimiterStateInterface.d.ts.map +1 -0
  17. package/dist/LimiterStateInterface.js +3 -0
  18. package/dist/LimiterStateInterface.js.map +1 -0
  19. package/dist/RateLimit.d.ts +43 -0
  20. package/dist/RateLimit.d.ts.map +1 -0
  21. package/dist/RateLimit.js +68 -0
  22. package/dist/RateLimit.js.map +1 -0
  23. package/dist/RateLimiterFactory.d.ts +83 -0
  24. package/dist/RateLimiterFactory.d.ts.map +1 -0
  25. package/dist/RateLimiterFactory.js +115 -0
  26. package/dist/RateLimiterFactory.js.map +1 -0
  27. package/dist/RateLimiterFactoryInterface.d.ts +17 -0
  28. package/dist/RateLimiterFactoryInterface.d.ts.map +1 -0
  29. package/dist/RateLimiterFactoryInterface.js +3 -0
  30. package/dist/RateLimiterFactoryInterface.js.map +1 -0
  31. package/dist/Reservation.d.ts +29 -0
  32. package/dist/Reservation.d.ts.map +1 -0
  33. package/dist/Reservation.js +44 -0
  34. package/dist/Reservation.js.map +1 -0
  35. package/dist/__tests__/CompoundLimiter.test.d.ts +2 -0
  36. package/dist/__tests__/CompoundLimiter.test.d.ts.map +1 -0
  37. package/dist/__tests__/CompoundLimiter.test.js +231 -0
  38. package/dist/__tests__/CompoundLimiter.test.js.map +1 -0
  39. package/dist/__tests__/CompoundRateLimiterFactory.test.d.ts +2 -0
  40. package/dist/__tests__/CompoundRateLimiterFactory.test.d.ts.map +1 -0
  41. package/dist/__tests__/CompoundRateLimiterFactory.test.js +213 -0
  42. package/dist/__tests__/CompoundRateLimiterFactory.test.js.map +1 -0
  43. package/dist/__tests__/RateLimit.test.d.ts +2 -0
  44. package/dist/__tests__/RateLimit.test.d.ts.map +1 -0
  45. package/dist/__tests__/RateLimit.test.js +108 -0
  46. package/dist/__tests__/RateLimit.test.js.map +1 -0
  47. package/dist/__tests__/RateLimiterFactory.test.d.ts +2 -0
  48. package/dist/__tests__/RateLimiterFactory.test.d.ts.map +1 -0
  49. package/dist/__tests__/RateLimiterFactory.test.js +323 -0
  50. package/dist/__tests__/RateLimiterFactory.test.js.map +1 -0
  51. package/dist/__tests__/Reservation.test.d.ts +2 -0
  52. package/dist/__tests__/Reservation.test.d.ts.map +1 -0
  53. package/dist/__tests__/Reservation.test.js +110 -0
  54. package/dist/__tests__/Reservation.test.js.map +1 -0
  55. package/dist/errors/InvalidIntervalError.d.ts +10 -0
  56. package/dist/errors/InvalidIntervalError.d.ts.map +1 -0
  57. package/dist/errors/InvalidIntervalError.js +18 -0
  58. package/dist/errors/InvalidIntervalError.js.map +1 -0
  59. package/dist/errors/MaxWaitDurationExceededError.d.ts +15 -0
  60. package/dist/errors/MaxWaitDurationExceededError.d.ts.map +1 -0
  61. package/dist/errors/MaxWaitDurationExceededError.js +24 -0
  62. package/dist/errors/MaxWaitDurationExceededError.js.map +1 -0
  63. package/dist/errors/RateLimitExceededError.d.ts +27 -0
  64. package/dist/errors/RateLimitExceededError.d.ts.map +1 -0
  65. package/dist/errors/RateLimitExceededError.js +42 -0
  66. package/dist/errors/RateLimitExceededError.js.map +1 -0
  67. package/dist/errors/ReserveNotSupportedError.d.ts +10 -0
  68. package/dist/errors/ReserveNotSupportedError.d.ts.map +1 -0
  69. package/dist/errors/ReserveNotSupportedError.js +18 -0
  70. package/dist/errors/ReserveNotSupportedError.js.map +1 -0
  71. package/dist/index.d.ts +35 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +58 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/policy/FixedWindowLimiter.d.ts +36 -0
  76. package/dist/policy/FixedWindowLimiter.d.ts.map +1 -0
  77. package/dist/policy/FixedWindowLimiter.js +105 -0
  78. package/dist/policy/FixedWindowLimiter.js.map +1 -0
  79. package/dist/policy/NoLimiter.d.ts +23 -0
  80. package/dist/policy/NoLimiter.d.ts.map +1 -0
  81. package/dist/policy/NoLimiter.js +34 -0
  82. package/dist/policy/NoLimiter.js.map +1 -0
  83. package/dist/policy/Rate.d.ts +69 -0
  84. package/dist/policy/Rate.d.ts.map +1 -0
  85. package/dist/policy/Rate.js +121 -0
  86. package/dist/policy/Rate.js.map +1 -0
  87. package/dist/policy/SlidingWindow.d.ts +74 -0
  88. package/dist/policy/SlidingWindow.d.ts.map +1 -0
  89. package/dist/policy/SlidingWindow.js +130 -0
  90. package/dist/policy/SlidingWindow.js.map +1 -0
  91. package/dist/policy/SlidingWindowLimiter.d.ts +41 -0
  92. package/dist/policy/SlidingWindowLimiter.d.ts.map +1 -0
  93. package/dist/policy/SlidingWindowLimiter.js +127 -0
  94. package/dist/policy/SlidingWindowLimiter.js.map +1 -0
  95. package/dist/policy/TokenBucket.d.ts +63 -0
  96. package/dist/policy/TokenBucket.d.ts.map +1 -0
  97. package/dist/policy/TokenBucket.js +92 -0
  98. package/dist/policy/TokenBucket.js.map +1 -0
  99. package/dist/policy/TokenBucketLimiter.d.ts +38 -0
  100. package/dist/policy/TokenBucketLimiter.d.ts.map +1 -0
  101. package/dist/policy/TokenBucketLimiter.js +114 -0
  102. package/dist/policy/TokenBucketLimiter.js.map +1 -0
  103. package/dist/policy/Window.d.ts +58 -0
  104. package/dist/policy/Window.d.ts.map +1 -0
  105. package/dist/policy/Window.js +105 -0
  106. package/dist/policy/Window.js.map +1 -0
  107. package/dist/policy/__tests__/FixedWindowLimiter.test.d.ts +2 -0
  108. package/dist/policy/__tests__/FixedWindowLimiter.test.d.ts.map +1 -0
  109. package/dist/policy/__tests__/FixedWindowLimiter.test.js +180 -0
  110. package/dist/policy/__tests__/FixedWindowLimiter.test.js.map +1 -0
  111. package/dist/policy/__tests__/NoLimiter.test.d.ts +2 -0
  112. package/dist/policy/__tests__/NoLimiter.test.d.ts.map +1 -0
  113. package/dist/policy/__tests__/NoLimiter.test.js +40 -0
  114. package/dist/policy/__tests__/NoLimiter.test.js.map +1 -0
  115. package/dist/policy/__tests__/Rate.test.d.ts +2 -0
  116. package/dist/policy/__tests__/Rate.test.d.ts.map +1 -0
  117. package/dist/policy/__tests__/Rate.test.js +162 -0
  118. package/dist/policy/__tests__/Rate.test.js.map +1 -0
  119. package/dist/policy/__tests__/SlidingWindow.test.d.ts +2 -0
  120. package/dist/policy/__tests__/SlidingWindow.test.d.ts.map +1 -0
  121. package/dist/policy/__tests__/SlidingWindow.test.js +257 -0
  122. package/dist/policy/__tests__/SlidingWindow.test.js.map +1 -0
  123. package/dist/policy/__tests__/SlidingWindowLimiter.test.d.ts +2 -0
  124. package/dist/policy/__tests__/SlidingWindowLimiter.test.d.ts.map +1 -0
  125. package/dist/policy/__tests__/SlidingWindowLimiter.test.js +201 -0
  126. package/dist/policy/__tests__/SlidingWindowLimiter.test.js.map +1 -0
  127. package/dist/policy/__tests__/TokenBucket.test.d.ts +2 -0
  128. package/dist/policy/__tests__/TokenBucket.test.d.ts.map +1 -0
  129. package/dist/policy/__tests__/TokenBucket.test.js +171 -0
  130. package/dist/policy/__tests__/TokenBucket.test.js.map +1 -0
  131. package/dist/policy/__tests__/TokenBucketLimiter.test.d.ts +2 -0
  132. package/dist/policy/__tests__/TokenBucketLimiter.test.d.ts.map +1 -0
  133. package/dist/policy/__tests__/TokenBucketLimiter.test.js +175 -0
  134. package/dist/policy/__tests__/TokenBucketLimiter.test.js.map +1 -0
  135. package/dist/policy/__tests__/Window.test.d.ts +2 -0
  136. package/dist/policy/__tests__/Window.test.d.ts.map +1 -0
  137. package/dist/policy/__tests__/Window.test.js +193 -0
  138. package/dist/policy/__tests__/Window.test.js.map +1 -0
  139. package/dist/storage/InMemoryStorage.d.ts +34 -0
  140. package/dist/storage/InMemoryStorage.d.ts.map +1 -0
  141. package/dist/storage/InMemoryStorage.js +62 -0
  142. package/dist/storage/InMemoryStorage.js.map +1 -0
  143. package/dist/storage/LockInterface.d.ts +41 -0
  144. package/dist/storage/LockInterface.d.ts.map +1 -0
  145. package/dist/storage/LockInterface.js +19 -0
  146. package/dist/storage/LockInterface.js.map +1 -0
  147. package/dist/storage/StorageInterface.d.ts +29 -0
  148. package/dist/storage/StorageInterface.d.ts.map +1 -0
  149. package/dist/storage/StorageInterface.js +3 -0
  150. package/dist/storage/StorageInterface.js.map +1 -0
  151. package/dist/storage/__tests__/InMemoryStorage.test.d.ts +2 -0
  152. package/dist/storage/__tests__/InMemoryStorage.test.d.ts.map +1 -0
  153. package/dist/storage/__tests__/InMemoryStorage.test.js +154 -0
  154. package/dist/storage/__tests__/InMemoryStorage.test.js.map +1 -0
  155. package/dist/util/TimeUtil.d.ts +35 -0
  156. package/dist/util/TimeUtil.d.ts.map +1 -0
  157. package/dist/util/TimeUtil.js +87 -0
  158. package/dist/util/TimeUtil.js.map +1 -0
  159. package/dist/util/__tests__/TimeUtil.test.d.ts +2 -0
  160. package/dist/util/__tests__/TimeUtil.test.d.ts.map +1 -0
  161. package/dist/util/__tests__/TimeUtil.test.js +132 -0
  162. package/dist/util/__tests__/TimeUtil.test.js.map +1 -0
  163. package/package.json +59 -0
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const TokenBucket_1 = require("../TokenBucket");
4
+ const Rate_1 = require("../Rate");
5
+ describe('TokenBucket', () => {
6
+ describe('constructor', () => {
7
+ it('should create a bucket with default values', () => {
8
+ const rate = Rate_1.Rate.perSecond(1);
9
+ const bucket = new TokenBucket_1.TokenBucket('test-bucket', 10, rate);
10
+ expect(bucket.getId()).toBe('test-bucket');
11
+ expect(bucket.getBurstSize()).toBe(10);
12
+ expect(bucket.getRate()).toBe(rate);
13
+ });
14
+ it('should initialize with full tokens by default', () => {
15
+ const rate = Rate_1.Rate.perSecond(1);
16
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate);
17
+ const now = Date.now() / 1000;
18
+ expect(bucket.getAvailableTokens(now)).toBe(10);
19
+ });
20
+ it('should accept custom initial tokens', () => {
21
+ const rate = Rate_1.Rate.perSecond(1);
22
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate, 5);
23
+ const now = Date.now() / 1000;
24
+ expect(bucket.getAvailableTokens(now)).toBe(5);
25
+ });
26
+ it('should accept custom timer', () => {
27
+ const rate = Rate_1.Rate.perSecond(1);
28
+ const timer = 1000;
29
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate, 5, timer);
30
+ expect(bucket.getTimer()).toBe(timer);
31
+ });
32
+ });
33
+ describe('getAvailableTokens', () => {
34
+ it('should return initial tokens when no time has passed', () => {
35
+ const rate = Rate_1.Rate.perSecond(1);
36
+ const now = 1000;
37
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate, 5, now);
38
+ expect(bucket.getAvailableTokens(now)).toBe(5);
39
+ });
40
+ it('should add tokens based on elapsed time', () => {
41
+ const rate = Rate_1.Rate.perSecond(1); // 1 token per second
42
+ const now = 1000;
43
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate, 5, now);
44
+ // After 3 seconds, should have 5 + 3 = 8 tokens
45
+ expect(bucket.getAvailableTokens(now + 3)).toBe(8);
46
+ });
47
+ it('should cap tokens at burst size', () => {
48
+ const rate = Rate_1.Rate.perSecond(1);
49
+ const now = 1000;
50
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate, 5, now);
51
+ // After 100 seconds, should cap at 10 (burst size)
52
+ expect(bucket.getAvailableTokens(now + 100)).toBe(10);
53
+ });
54
+ it('should handle fractional refills correctly', () => {
55
+ const rate = Rate_1.Rate.perSecond(2); // 2 tokens per second
56
+ const now = 1000;
57
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate, 0, now);
58
+ // After 2.5 seconds, should have floor(2.5 * 2) = 5 tokens
59
+ expect(bucket.getAvailableTokens(now + 2.5)).toBe(5);
60
+ });
61
+ it('should use current time when not provided', () => {
62
+ const rate = Rate_1.Rate.perSecond(1);
63
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate, 10);
64
+ const tokens = bucket.getAvailableTokens();
65
+ expect(tokens).toBeGreaterThanOrEqual(0);
66
+ expect(tokens).toBeLessThanOrEqual(10);
67
+ });
68
+ });
69
+ describe('setTokens and setTimer', () => {
70
+ it('should update tokens', () => {
71
+ const rate = Rate_1.Rate.perSecond(1);
72
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate, 5);
73
+ bucket.setTokens(3);
74
+ const now = Date.now() / 1000;
75
+ expect(bucket.getAvailableTokens(now)).toBe(3);
76
+ });
77
+ it('should update timer', () => {
78
+ const rate = Rate_1.Rate.perSecond(1);
79
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate, 5, 1000);
80
+ bucket.setTimer(2000);
81
+ expect(bucket.getTimer()).toBe(2000);
82
+ });
83
+ });
84
+ describe('getExpirationTime', () => {
85
+ it('should calculate expiration based on refill time', () => {
86
+ const rate = Rate_1.Rate.perSecond(1); // 1 token per second
87
+ const now = 1000;
88
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate, 0, now);
89
+ // With 0 tokens and burst size 10, needs 10 seconds to refill
90
+ // Expiration = ceil(1000 + 10) = 1010
91
+ expect(bucket.getExpirationTime()).toBe(1010);
92
+ });
93
+ it('should handle partial buckets', () => {
94
+ const rate = Rate_1.Rate.perSecond(2); // 2 tokens per second
95
+ const now = 1000;
96
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate, 5, now);
97
+ // With 5 tokens, needs 5 more tokens = 2.5 seconds
98
+ // Rate.calculateTimeForTokens(10) = ceil(10 * 1 / 2) = 5
99
+ // Expiration = ceil(1000 + 5) = 1005
100
+ expect(bucket.getExpirationTime()).toBe(1005);
101
+ });
102
+ });
103
+ describe('toJSON and fromJSON', () => {
104
+ it('should serialize to JSON', () => {
105
+ const rate = Rate_1.Rate.perSecond(2);
106
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate, 5, 1000);
107
+ const json = bucket.toJSON();
108
+ expect(json).toEqual({
109
+ id: 'test',
110
+ tokens: 5,
111
+ burstSize: 10,
112
+ timer: 1000,
113
+ rate: {
114
+ interval: 1,
115
+ amount: 2,
116
+ },
117
+ });
118
+ });
119
+ it('should deserialize from JSON', () => {
120
+ const json = {
121
+ id: 'test-bucket',
122
+ tokens: 7,
123
+ burstSize: 15,
124
+ timer: 2000,
125
+ rate: {
126
+ interval: 60,
127
+ amount: 10,
128
+ },
129
+ };
130
+ const bucket = TokenBucket_1.TokenBucket.fromJSON(json);
131
+ expect(bucket.getId()).toBe('test-bucket');
132
+ expect(bucket.getBurstSize()).toBe(15);
133
+ expect(bucket.getTimer()).toBe(2000);
134
+ expect(bucket.getRate().getInterval()).toBe(60);
135
+ expect(bucket.getRate().getAmount()).toBe(10);
136
+ expect(bucket.getAvailableTokens(2000)).toBe(7);
137
+ });
138
+ it('should round-trip serialize/deserialize', () => {
139
+ const rate = Rate_1.Rate.perHour(100);
140
+ const bucket = new TokenBucket_1.TokenBucket('round-trip', 50, rate, 25, 5000);
141
+ const json = bucket.toJSON();
142
+ const restored = TokenBucket_1.TokenBucket.fromJSON(json);
143
+ expect(restored.getId()).toBe(bucket.getId());
144
+ expect(restored.getBurstSize()).toBe(bucket.getBurstSize());
145
+ expect(restored.getTimer()).toBe(bucket.getTimer());
146
+ expect(restored.getAvailableTokens(5000)).toBe(bucket.getAvailableTokens(5000));
147
+ });
148
+ });
149
+ describe('edge cases', () => {
150
+ it('should handle zero tokens', () => {
151
+ const rate = Rate_1.Rate.perSecond(1);
152
+ const bucket = new TokenBucket_1.TokenBucket('test', 10, rate, 0);
153
+ const now = Date.now() / 1000;
154
+ expect(bucket.getAvailableTokens(now)).toBe(0);
155
+ });
156
+ it('should handle burst size of 1', () => {
157
+ const rate = Rate_1.Rate.perSecond(1);
158
+ const bucket = new TokenBucket_1.TokenBucket('test', 1, rate, 1);
159
+ const now = Date.now() / 1000;
160
+ expect(bucket.getAvailableTokens(now)).toBe(1);
161
+ });
162
+ it('should handle very fast refill rates', () => {
163
+ const rate = Rate_1.Rate.perSecond(1000);
164
+ const now = 1000;
165
+ const bucket = new TokenBucket_1.TokenBucket('test', 100, rate, 0, now);
166
+ // After 0.1 seconds, should have 100 tokens (rate is 1000/s)
167
+ expect(bucket.getAvailableTokens(now + 0.1)).toBe(100);
168
+ });
169
+ });
170
+ });
171
+ //# sourceMappingURL=TokenBucket.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenBucket.test.js","sourceRoot":"","sources":["../../../src/policy/__tests__/TokenBucket.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=TokenBucketLimiter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenBucketLimiter.test.d.ts","sourceRoot":"","sources":["../../../src/policy/__tests__/TokenBucketLimiter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const TokenBucketLimiter_1 = require("../TokenBucketLimiter");
4
+ const Rate_1 = require("../Rate");
5
+ const InMemoryStorage_1 = require("../../storage/InMemoryStorage");
6
+ const MaxWaitDurationExceededError_1 = require("../../errors/MaxWaitDurationExceededError");
7
+ describe('TokenBucketLimiter', () => {
8
+ let storage;
9
+ beforeEach(() => {
10
+ storage = new InMemoryStorage_1.InMemoryStorage();
11
+ });
12
+ describe('consume', () => {
13
+ it('should accept requests when tokens are available', async () => {
14
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(1), storage);
15
+ const result = await limiter.consume(5);
16
+ expect(result.isAccepted()).toBe(true);
17
+ expect(result.getRemainingTokens()).toBe(5);
18
+ expect(result.getLimit()).toBe(10);
19
+ });
20
+ it('should reject requests when tokens are exhausted', async () => {
21
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(1), storage);
22
+ await limiter.consume(10);
23
+ const result = await limiter.consume(1);
24
+ expect(result.isAccepted()).toBe(false);
25
+ expect(result.getRemainingTokens()).toBe(0);
26
+ });
27
+ it('should decrement tokens on each consumption', async () => {
28
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(1), storage);
29
+ const r1 = await limiter.consume(3);
30
+ const r2 = await limiter.consume(2);
31
+ const r3 = await limiter.consume(4);
32
+ expect(r1.getRemainingTokens()).toBe(7);
33
+ expect(r2.getRemainingTokens()).toBe(5);
34
+ expect(r3.getRemainingTokens()).toBe(1);
35
+ });
36
+ it('should refill tokens over time', async () => {
37
+ jest.useFakeTimers();
38
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(2), storage);
39
+ await limiter.consume(10);
40
+ // Wait 3 seconds, should refill 6 tokens
41
+ jest.advanceTimersByTime(3000);
42
+ const result = await limiter.consume(5);
43
+ expect(result.isAccepted()).toBe(true);
44
+ jest.useRealTimers();
45
+ });
46
+ it('should cap refilled tokens at burst size', async () => {
47
+ jest.useFakeTimers();
48
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(1), storage);
49
+ await limiter.consume(5);
50
+ // Wait 100 seconds, should cap at 10 tokens
51
+ jest.advanceTimersByTime(100000);
52
+ const result = await limiter.consume(10);
53
+ expect(result.isAccepted()).toBe(true);
54
+ jest.useRealTimers();
55
+ });
56
+ it('should provide retry time when rate limited', async () => {
57
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(1), storage);
58
+ await limiter.consume(10);
59
+ const result = await limiter.consume(5);
60
+ expect(result.isAccepted()).toBe(false);
61
+ expect(result.getRetryAfter().getTime()).toBeGreaterThan(Date.now());
62
+ });
63
+ it('should handle fractional tokens consumption', async () => {
64
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(2), storage);
65
+ const r1 = await limiter.consume(1);
66
+ const r2 = await limiter.consume(1);
67
+ expect(r1.isAccepted()).toBe(true);
68
+ expect(r2.isAccepted()).toBe(true);
69
+ });
70
+ });
71
+ describe('reserve', () => {
72
+ it('should reserve tokens when available', async () => {
73
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(1), storage);
74
+ const reservation = await limiter.reserve(5);
75
+ expect(reservation.getWaitDuration()).toBe(0);
76
+ expect(reservation.getRateLimit().isAccepted()).toBe(true);
77
+ expect(reservation.getRateLimit().getRemainingTokens()).toBe(5);
78
+ });
79
+ it('should calculate wait time when tokens not available', async () => {
80
+ jest.useFakeTimers();
81
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(1), storage);
82
+ await limiter.consume(10);
83
+ const reservation = await limiter.reserve(5);
84
+ expect(reservation.getWaitDuration()).toBeGreaterThan(0);
85
+ expect(reservation.getRateLimit().isAccepted()).toBe(true);
86
+ jest.useRealTimers();
87
+ });
88
+ it('should throw error when exceeding maxTime', async () => {
89
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(1), storage);
90
+ await limiter.consume(10);
91
+ await expect(limiter.reserve(5, 1)).rejects.toThrow(MaxWaitDurationExceededError_1.MaxWaitDurationExceededError);
92
+ });
93
+ it('should throw error when requesting more than burst size', async () => {
94
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(1), storage);
95
+ await expect(limiter.reserve(15)).rejects.toThrow('Cannot reserve 15 tokens, burst size is 10');
96
+ });
97
+ it('should wait for correct duration based on rate', async () => {
98
+ jest.useFakeTimers();
99
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(2), storage);
100
+ await limiter.consume(10);
101
+ const reservation = await limiter.reserve(4);
102
+ // Need 4 tokens at 2 per second = 2 seconds
103
+ const waitDuration = reservation.getWaitDuration();
104
+ expect(waitDuration).toBeGreaterThanOrEqual(1900);
105
+ expect(waitDuration).toBeLessThanOrEqual(2100);
106
+ jest.useRealTimers();
107
+ });
108
+ });
109
+ describe('reset', () => {
110
+ it('should reset the limiter state', async () => {
111
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(1), storage);
112
+ await limiter.consume(10);
113
+ await limiter.reset();
114
+ const result = await limiter.consume(10);
115
+ expect(result.isAccepted()).toBe(true);
116
+ });
117
+ it('should start fresh after reset', async () => {
118
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(1), storage);
119
+ await limiter.consume(5);
120
+ await limiter.reset();
121
+ const result = await limiter.consume(1);
122
+ expect(result.getRemainingTokens()).toBe(9);
123
+ });
124
+ });
125
+ describe('multiple limiters', () => {
126
+ it('should maintain separate state for different IDs', async () => {
127
+ const limiter1 = new TokenBucketLimiter_1.TokenBucketLimiter('user1', 10, Rate_1.Rate.perSecond(1), storage);
128
+ const limiter2 = new TokenBucketLimiter_1.TokenBucketLimiter('user2', 10, Rate_1.Rate.perSecond(1), storage);
129
+ await limiter1.consume(8);
130
+ await limiter2.consume(3);
131
+ const r1 = await limiter1.consume(1);
132
+ const r2 = await limiter2.consume(1);
133
+ expect(r1.getRemainingTokens()).toBe(1);
134
+ expect(r2.getRemainingTokens()).toBe(6);
135
+ });
136
+ });
137
+ describe('concurrent requests', () => {
138
+ it('should handle sequential requests correctly', async () => {
139
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(1), storage);
140
+ const results = [];
141
+ for (let i = 0; i < 15; i++) {
142
+ results.push(await limiter.consume(1));
143
+ }
144
+ const accepted = results.filter(r => r.isAccepted());
145
+ const rejected = results.filter(r => !r.isAccepted());
146
+ expect(accepted.length).toBe(10);
147
+ expect(rejected.length).toBe(5);
148
+ });
149
+ });
150
+ describe('edge cases', () => {
151
+ it('should handle burst size of 1', async () => {
152
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 1, Rate_1.Rate.perSecond(1), storage);
153
+ const r1 = await limiter.consume(1);
154
+ const r2 = await limiter.consume(1);
155
+ expect(r1.isAccepted()).toBe(true);
156
+ expect(r2.isAccepted()).toBe(false);
157
+ });
158
+ it('should handle very fast refill rates', async () => {
159
+ jest.useFakeTimers();
160
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 100, Rate_1.Rate.perSecond(1000), storage);
161
+ await limiter.consume(100);
162
+ jest.advanceTimersByTime(100); // 0.1 seconds
163
+ const result = await limiter.consume(50);
164
+ expect(result.isAccepted()).toBe(true);
165
+ jest.useRealTimers();
166
+ });
167
+ it('should handle default parameters', async () => {
168
+ const limiter = new TokenBucketLimiter_1.TokenBucketLimiter('test', 10, Rate_1.Rate.perSecond(1), storage);
169
+ const result = await limiter.consume(); // Default 1 token
170
+ expect(result.isAccepted()).toBe(true);
171
+ expect(result.getRemainingTokens()).toBe(9);
172
+ });
173
+ });
174
+ });
175
+ //# sourceMappingURL=TokenBucketLimiter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenBucketLimiter.test.js","sourceRoot":"","sources":["../../../src/policy/__tests__/TokenBucketLimiter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Window.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Window.test.d.ts","sourceRoot":"","sources":["../../../src/policy/__tests__/Window.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const Window_1 = require("../Window");
4
+ describe('Window', () => {
5
+ describe('constructor', () => {
6
+ it('should create a window with default values', () => {
7
+ const window = new Window_1.Window('test-window', 60, 100);
8
+ expect(window.getId()).toBe('test-window');
9
+ expect(window.getInterval()).toBe(60);
10
+ expect(window.getHitCount()).toBe(0);
11
+ });
12
+ it('should accept custom initial hit count', () => {
13
+ const window = new Window_1.Window('test', 60, 100, 50);
14
+ expect(window.getHitCount()).toBe(50);
15
+ });
16
+ it('should accept custom timer', () => {
17
+ const timer = 1000;
18
+ const window = new Window_1.Window('test', 60, 100, 0, timer);
19
+ expect(window.getTimer()).toBe(timer);
20
+ });
21
+ });
22
+ describe('add', () => {
23
+ it('should add hits to the same window', () => {
24
+ const now = 1000;
25
+ const window = new Window_1.Window('test', 60, 100, 0, now);
26
+ window.add(5, now + 10);
27
+ expect(window.getHitCount()).toBe(5);
28
+ window.add(3, now + 20);
29
+ expect(window.getHitCount()).toBe(8);
30
+ });
31
+ it('should reset hits when moving to a new window', () => {
32
+ const now = 1000;
33
+ const window = new Window_1.Window('test', 60, 100, 50, now);
34
+ // Move to new window (60+ seconds later)
35
+ window.add(10, now + 70);
36
+ expect(window.getHitCount()).toBe(10);
37
+ });
38
+ it('should align timer to window boundary on reset', () => {
39
+ const now = 1000;
40
+ const intervalInSeconds = 60;
41
+ const window = new Window_1.Window('test', intervalInSeconds, 100, 0, now);
42
+ // Move to new window
43
+ const newTime = now + 125; // 2+ windows later
44
+ window.add(5, newTime);
45
+ // Timer should be aligned to window boundary
46
+ const expectedTimer = Math.floor(newTime / intervalInSeconds) * intervalInSeconds;
47
+ expect(window.getTimer()).toBe(expectedTimer);
48
+ });
49
+ it('should use current time when not provided', () => {
50
+ const window = new Window_1.Window('test', 60, 100);
51
+ window.add(5);
52
+ expect(window.getHitCount()).toBe(5);
53
+ });
54
+ it('should handle exact window boundary', () => {
55
+ const now = 1000;
56
+ const window = new Window_1.Window('test', 60, 100, 10, now);
57
+ // Exactly at window boundary
58
+ window.add(5, now + 60);
59
+ expect(window.getHitCount()).toBe(5); // Should reset
60
+ });
61
+ });
62
+ describe('getAvailableTokens', () => {
63
+ it('should return max tokens for empty window', () => {
64
+ const now = 1000;
65
+ const window = new Window_1.Window('test', 60, 100, 0, now);
66
+ expect(window.getAvailableTokens(now)).toBe(100);
67
+ });
68
+ it('should return remaining tokens in current window', () => {
69
+ const now = 1000;
70
+ const window = new Window_1.Window('test', 60, 100, 30, now);
71
+ expect(window.getAvailableTokens(now + 10)).toBe(70); // 100 - 30
72
+ });
73
+ it('should return max tokens in new window', () => {
74
+ const now = 1000;
75
+ const window = new Window_1.Window('test', 60, 100, 90, now);
76
+ // Move to new window
77
+ expect(window.getAvailableTokens(now + 70)).toBe(100);
78
+ });
79
+ it('should return 0 when window is full', () => {
80
+ const now = 1000;
81
+ const window = new Window_1.Window('test', 60, 100, 100, now);
82
+ expect(window.getAvailableTokens(now + 10)).toBe(0);
83
+ });
84
+ it('should not return negative tokens', () => {
85
+ const now = 1000;
86
+ const window = new Window_1.Window('test', 60, 100, 150, now); // Over limit
87
+ expect(window.getAvailableTokens(now + 10)).toBe(0);
88
+ });
89
+ it('should use current time when not provided', () => {
90
+ const window = new Window_1.Window('test', 60, 100, 50);
91
+ const available = window.getAvailableTokens();
92
+ expect(available).toBeGreaterThanOrEqual(0);
93
+ expect(available).toBeLessThanOrEqual(100);
94
+ });
95
+ });
96
+ describe('calculateTimeForTokens', () => {
97
+ it('should return 0 when tokens are already available', () => {
98
+ const now = 1000;
99
+ const window = new Window_1.Window('test', 60, 100, 20, now);
100
+ // Need 50 tokens, have 80 available
101
+ expect(window.calculateTimeForTokens(50, now)).toBe(0);
102
+ });
103
+ it('should calculate wait time for next window', () => {
104
+ const now = 1000;
105
+ const window = new Window_1.Window('test', 60, 100, 90, now);
106
+ // Need 50 tokens, only have 10 available, need to wait for next window
107
+ const waitTime = window.calculateTimeForTokens(50, now + 10);
108
+ expect(waitTime).toBe(50); // 60 - 10 seconds remaining in window
109
+ });
110
+ it('should handle exact window end', () => {
111
+ const now = 1000;
112
+ const window = new Window_1.Window('test', 60, 100, 100, now);
113
+ // At window end, new window starts
114
+ expect(window.calculateTimeForTokens(50, now + 60)).toBe(0);
115
+ });
116
+ it('should use current time when not provided', () => {
117
+ const window = new Window_1.Window('test', 60, 100, 100);
118
+ const waitTime = window.calculateTimeForTokens(50);
119
+ expect(waitTime).toBeGreaterThanOrEqual(0);
120
+ });
121
+ });
122
+ describe('getExpirationTime', () => {
123
+ it('should calculate expiration as timer plus interval', () => {
124
+ const now = 1000;
125
+ const window = new Window_1.Window('test', 60, 100, 0, now);
126
+ expect(window.getExpirationTime()).toBe(1060); // ceil(1000 + 60)
127
+ });
128
+ it('should round up expiration time', () => {
129
+ const now = 1000.5;
130
+ const window = new Window_1.Window('test', 60, 100, 0, now);
131
+ expect(window.getExpirationTime()).toBe(1061); // ceil(1000.5 + 60)
132
+ });
133
+ });
134
+ describe('toJSON and fromJSON', () => {
135
+ it('should serialize to JSON', () => {
136
+ const window = new Window_1.Window('test', 60, 100, 50, 1000);
137
+ const json = window.toJSON();
138
+ expect(json).toEqual({
139
+ id: 'test',
140
+ hitCount: 50,
141
+ intervalInSeconds: 60,
142
+ maxSize: 100,
143
+ timer: 1000,
144
+ });
145
+ });
146
+ it('should deserialize from JSON', () => {
147
+ const json = {
148
+ id: 'test-window',
149
+ hitCount: 75,
150
+ intervalInSeconds: 120,
151
+ maxSize: 200,
152
+ timer: 2000,
153
+ };
154
+ const window = Window_1.Window.fromJSON(json);
155
+ expect(window.getId()).toBe('test-window');
156
+ expect(window.getHitCount()).toBe(75);
157
+ expect(window.getInterval()).toBe(120);
158
+ expect(window.getTimer()).toBe(2000);
159
+ });
160
+ it('should round-trip serialize/deserialize', () => {
161
+ const window = new Window_1.Window('round-trip', 300, 1000, 500, 5000);
162
+ const json = window.toJSON();
163
+ const restored = Window_1.Window.fromJSON(json);
164
+ expect(restored.getId()).toBe(window.getId());
165
+ expect(restored.getHitCount()).toBe(window.getHitCount());
166
+ expect(restored.getInterval()).toBe(window.getInterval());
167
+ expect(restored.getTimer()).toBe(window.getTimer());
168
+ });
169
+ });
170
+ describe('edge cases', () => {
171
+ it('should handle interval of 1 second', () => {
172
+ const now = 1000;
173
+ const window = new Window_1.Window('test', 1, 10, 0, now);
174
+ window.add(5, now);
175
+ expect(window.getAvailableTokens(now)).toBe(5);
176
+ // Next second is new window
177
+ expect(window.getAvailableTokens(now + 1)).toBe(10);
178
+ });
179
+ it('should handle max size of 1', () => {
180
+ const now = 1000;
181
+ const window = new Window_1.Window('test', 60, 1, 0, now);
182
+ window.add(1, now);
183
+ expect(window.getAvailableTokens(now)).toBe(0);
184
+ });
185
+ it('should handle very large intervals', () => {
186
+ const now = 1000;
187
+ const window = new Window_1.Window('test', 86400, 10000, 5000, now); // 1 day interval
188
+ expect(window.getAvailableTokens(now + 1000)).toBe(5000);
189
+ expect(window.getAvailableTokens(now + 86400)).toBe(10000); // New window
190
+ });
191
+ });
192
+ });
193
+ //# sourceMappingURL=Window.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Window.test.js","sourceRoot":"","sources":["../../../src/policy/__tests__/Window.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { LimiterStateInterface } from '../LimiterStateInterface';
2
+ import type { StorageInterface } from './StorageInterface';
3
+ /**
4
+ * In-memory storage implementation for rate limiter state.
5
+ *
6
+ * This storage is non-persistent and will be lost when the process restarts.
7
+ * Suitable for single-instance applications or testing.
8
+ */
9
+ export declare class InMemoryStorage implements StorageInterface {
10
+ private readonly storage;
11
+ /**
12
+ * Save a state object to memory.
13
+ */
14
+ save(state: LimiterStateInterface): Promise<void>;
15
+ /**
16
+ * Fetch a state object from memory.
17
+ *
18
+ * Automatically cleans up expired entries.
19
+ */
20
+ fetch(id: string): Promise<LimiterStateInterface | null>;
21
+ /**
22
+ * Delete a state object from memory.
23
+ */
24
+ delete(id: string): Promise<void>;
25
+ /**
26
+ * Clear all stored state (useful for testing).
27
+ */
28
+ clear(): void;
29
+ /**
30
+ * Get the number of stored entries (useful for testing).
31
+ */
32
+ size(): number;
33
+ }
34
+ //# sourceMappingURL=InMemoryStorage.d.ts.map