Skip to content

Commit a766c5a

Browse files
committed
Test failing on eventual consistency
4 out of 10 (40%) left to reach consistency: DeltaCrdt.get(config.crdt_name, {"project2", "#{Node.self()}"}) #=> {4, 1746007259}
1 parent e885516 commit a766c5a

File tree

2 files changed

+33
-27
lines changed

2 files changed

+33
-27
lines changed

lib/lightning/rate_limiters.ex

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,9 @@ defmodule Lightning.RateLimiters do
2525
defmodule Webhook do
2626
@moduledoc false
2727

28-
# Use ReplicatedRateLimiter instead
29-
use Hammer,
30-
backend: Hammer.ETS,
31-
algorithm: :leaky_bucket,
32-
table: :webhook_limiter
28+
use ReplicatedRateLimiter,
29+
default_capacity: 10,
30+
default_refill: 2
3331
end
3432

3533
@spec hit({:failure_email, String.t(), String.t()}) :: Mail.hit_result()
@@ -51,7 +49,9 @@ defmodule Lightning.RateLimiters do
5149
# 10 requests for a second, then 2 requests per second
5250
# Over a long enough period of time, this will allow 2 requests per second.
5351
# allow?("webhook_#{project_id}", 10, 2)
54-
Webhook.hit(project_id, 2, 10)
52+
# capacity and refill is by design a module attribute
53+
# TODO: passing it here might eliminate the need for macro for easier maintainance
54+
Webhook.allow?("webhook_#{project_id}")
5555
end
5656

5757
def child_spec(opts) do

test/replicated_rate_limiter_test.exs

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ defmodule ReplicatedRateLimiterTest do
44

55
defmodule CrdtEts do
66
use ReplicatedRateLimiter,
7-
default_capacity: 1_000,
8-
default_refill: 200
7+
default_capacity: 10,
8+
default_refill: 2
99
end
1010

1111
defmodule AnotherRateLimiter do
@@ -17,50 +17,56 @@ defmodule ReplicatedRateLimiterTest do
1717

1818
config = CrdtEts.config() |> Map.new()
1919

20-
# Test using the main module's allow? function
21-
result = CrdtEts.allow?("test_key")
22-
assert match?({:allow, 999}, result)
20+
# Check one time (default cost is 1)
21+
assert match?({:allow, 9}, CrdtEts.allow?("project1"))
2322

2423
before = System.system_time(:second)
2524

26-
# Make several calls to hit the limit
27-
Enum.each(1..10, fn _ -> CrdtEts.allow?("test_key_2", 5, 1) end)
25+
# Make several calls to hit the limit (default capacity is 10)
26+
Enum.each(1..9, fn _ -> CrdtEts.allow?("project2") end)
2827

29-
assert {0, last_updated} =
30-
DeltaCrdt.get(config.crdt_name, {"test_key_2", "#{Node.self()}"}),
31-
"CRDT should have 0 tokens"
28+
assert_eventually(
29+
DeltaCrdt.get(config.crdt_name, {"project2", "#{Node.self()}"}) |> dbg |> elem(0) == 0,
30+
1_000
31+
)
3232

33-
assert {0, ^last_updated} =
34-
CrdtEts.to_list("test_key_2"),
33+
assert {0, last_updated} =
34+
CrdtEts.to_list("project2"),
3535
"ETS should be the same as CRDT"
3636

3737
assert before <= last_updated
3838

3939
# This should be denied since we consumed all tokens
40-
assert {:deny, 1000} = CrdtEts.allow?("test_key_2", 5, 1)
40+
assert {:deny, 1000} = CrdtEts.allow?("project2", 10, 2)
4141

42-
# Another node enters the dungeon
42+
# Node2 enters the dungeon
4343
{:ok, test_crdt} =
4444
DeltaCrdt.start_link(DeltaCrdt.AWLWWMap)
4545

4646
DeltaCrdt.set_neighbours(config.crdt_name, [test_crdt])
4747
DeltaCrdt.set_neighbours(test_crdt, [config.crdt_name])
4848

49-
# and updates the bucket
49+
# a time has passed and the bucket is refilled by Node2
5050
DeltaCrdt.put(
5151
test_crdt,
52-
{"test_key_2", "another_node"},
53-
{10, System.system_time(:second) + 1}
52+
{"project2", "another_node"},
53+
{10, System.system_time(:second)}
5454
)
5555

56+
# Node2 consumes all the credits except one
57+
Enum.each(1..9, fn i ->
58+
DeltaCrdt.put(
59+
test_crdt,
60+
{"project2", "another_node"},
61+
{10-i, System.system_time(:second)})
62+
end)
63+
5664
# Wait for the bucket to be updated
5765
assert_eventually(
58-
CrdtEts.to_list("test_key_2")
59-
|> Tuple.to_list()
60-
|> List.first() == 10
66+
CrdtEts.to_list("project2") |> elem(0) == 1
6167
)
6268

63-
assert {:allow, 4} = CrdtEts.allow?("test_key_2", 5, 1)
69+
assert {:allow, 4} = CrdtEts.allow?("project2", 10, 2)
6470
end
6571

6672
test "can start multiple rate limiters" do

0 commit comments

Comments
 (0)