juspay / fencer Goto Github PK
View Code? Open in Web Editor NEWFencer is a port of https://github.com/lyft/ratelimit into Haskell.
Home Page: https://hub.docker.com/r/juspayin/fencer
License: Other
Fencer is a port of https://github.com/lyft/ratelimit into Haskell.
Home Page: https://hub.docker.com/r/juspayin/fencer
License: Other
(will expand later)
lyft/ratelimit already has an environment variable to do this, ideally we should use the same variable name. This variable should also be documented as per #11.
There are no tests for configuration parsing, hence they should be added. Given that there are no tests in the project, this will also set up the test configuration of the project.
Looks like we do not need to remove counters when rules are reloaded. The behavior of lyft/ratelimit is as follows:
So we need to:
CounterKey
Currently Fencer/Proto.hs is generated from a protobuf file in the repo. It also depends on proto3-suite. So, when updating the version of proto3-suite we might forget to rerun compile-proto-file
– this just happened to me, for instance.
Possible solutions:
Currently our closure takes about 700 MB:
$ storepath=$(nix-build)
$ nix-store --export $(nix-store -qR $storepath) > out-fencer
$ ls -lah out-fencer
-rw-r--r-- 1 yom staff 708M Sep 27 17:22 out-fencer
The biggest offenders are:
740 MB └── nix
740 MB └── store
393 MB ├─⊕ i2nf6hslid0ak8fzgpj2m082sprihi92-clang-7.1.0
133 MB ├─⊕ hfy6ibq1hwayv24yrh98f3avc47nmr00-llvm-7.1.0
63 MB ├─⊕ 0cifmxw0r6lijng796a3z3nwq67ma5b3-llvm-7.1.0-lib
27 MB ├─⊕ 5qk8vydayrvkq313s1srxhrnblhqvahk-grpc-1.2.0-e2cfe9d
27 MB ├─⊕ q959m66x0cfryybzapv7c4v0ki2jfr1a-clang-7.1.0-lib
18 MB ├─⊕ bhywddq18j79xr274n45byvqjb8fs52j-Libsystem-osx-10.12.6
11 MB ├─⊕ i7hz49am5vla34lmpkw5aqkjgd2b98hb-binutils-2.31.1
...
This primarily affects our Docker image size.
Write a manual for running lyft/ratelimit
. This should also include examples with submitting requests to the service.
We should support the same log level names lyft/ratelimit does. Currently we support "LOG_LEVEL=Info" but not "LOG_LEVEL=info".
At https://github.com/juspay/fencer/blob/master/CONTRIBUTING.md#git-policy, the branch name template is not rendered properly.
Set up the Travis continuous integration for Fencer:
.travis.yml
file,.travis.yml
file and should be only made available to jobs that actually require them,$ grpcurl -proto proto/rls.proto -plaintext -d '{"domain":"hi", "descriptors":[]}' localhost:8081 envoy.service.ratelimit.v2.RateLimitService.ShouldRateLimit
ERROR:
Code: Unknown
Message: rate limit descriptor list must not be empty
Make sure that the domainDefinitionDescriptors
field has at least one list element and that JSON parsing fails otherwise. Use the NonEmpty
list type constructor.
$ grpcurl -proto proto/rls.proto -plaintext -d '{"domain":"", "descriptors":[]}' localhost:8081 envoy.service.ratelimit.v2.RateLimitService.ShouldRateLimit
ERROR:
Code: Unknown
Message: rate limit domain must not be emptyÿ
Make sure that parsing fails if the domain id is empty.
lyft/ratelimit treats domain: mongo, key: cps_database
and domain: mongo_cps, key: database
as literally the same. I don't think we should do the same, but we should document it.
getTimestamp
will report the same timestamp twice on a leap second. We might want to use the clock
package instead, either with Monotonic
or MonotonicCoarse
timestamps.
Depends on #101.
With issue #2 a few configuration parsing tests were added. Write more of such tests.
Also:
.yml
files..foo/bar.yaml
if RUNTIME_IGNOREDOTFILES
is enabled?RUNTIME_IGNOREDOTFILES
in general is not tested by our testsuite by our testsuite, but should be.Also:
chmod 0
-ed), other files are loaded correctly and it responds to requests with OK.And more:
rls.proto
:
// A list of headers to add to the response
repeated HeaderValue headers = 3;
When are those headers returned? Do we ever have to return them? If not, add a comment in Fencer.Server
.
Currently we can't use cabal2nix because of these flags:
, configureFlags ? [], enableSharedExecutables ? true, enableSharedLibraries ? true
We can probably use overrides instead to the same effect.
grpc-haskell has recently been upgraded to support grpc-1.22. I updated .nix files in branch artyom/grpc, but lyft/ratelimit integration tests are crashing Fencer:
fencer(2509,0x70000b9b1000) malloc: *** error for object 0x7f98d3c0cae0: pointer being freed was not allocated
fencer(2509,0x70000b9b1000) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6
Filed as awakesecurity/gRPC-haskell#91.
There are a number of integration tests in Lyft's ratelimit implementation in Go. They should be rewritten in Haskell in Juspay's implementation of ratelimit. In particular, the following tests should be rewritten:
https://github.com/lyft/ratelimit/blob/master/test/service/ratelimit_test.go#L88-L212
After doing docker load -i fencer.tar.gz
we can see the time that it shows as 49 years ago
or you can do this to get the exact time:
$ docker inspect -f '{{ .Created }}' juspay/fencer
1970-01-01T00:00:01Z
Currently nix-build
builds with withHoogle
. What I'd like is for nix-build
to have withHoogle = false
by default.
Cachix is for developers as well as for the CI, so even if shell-only dependencies are useless for CI, we should still build them and push to Cachix.
Currently it's possible the a .Test
module will export some tests but not all of them will be used in test/Main.hs
.
To prevent this, let's use a different scheme for test exports:
-- | Tests for "Fencer.Logic".
module Fencer.Logic.Test (tests) where
tests :: TestTree
tests = testGroup "Logic tests" [test_logicLimitUnitChange]
-- test/Main.hs
module Main (main) where
import qualified Fencer.Logic.Test
import qualified Fencer.Rules.Test
import qualified Fencer.Server.Test
import qualified Fencer.Types.Test
tests :: TestTree
tests = testGroup "All tests"
[ Fencer.Types.Test.tests
, Fencer.Logic.Test.tests
, Fencer.Rules.Test.tests
-- 'after' is needed to avoid running the 'logic' and 'server' tests
-- concurrently. Running them concurrently is problematic because
-- both create a server (binding the same port) so if they create it
-- at the same time, one of the test groups will fail. The 'after'
-- function makes the 'server' tests run after the 'logic' tests.
, after AllFinish "test_logic" Fencer.Server.Test.tests
]
In a comment to a pull request, @neongreen suggested several changes to the test that checks the counter logic. Implement what has been suggested there.
Currently the implementation allows for intermediate rule keys to have rate limits, even though in the domain logic it makes sense only for leaf keys to have rate limits. Fix the logic to allow only leaf rule keys to have rate limits and add a test if necessary.
In tests we write to /dev/null
to make sure the testing output isn't garbled. However, Windows don't have such a file. Therefore, a suggestion is to use a temporary file (created with e.g. the platform-agnostic temporary
package) to replace /dev/null
.
limitRemaining
is returned if it's not zero:
[:~/monadfix/juspay/fencer] master+* ± grpcurl -proto proto/rls.proto -plaintext -d '{"domain":"mongo_cps", "descriptors":[{"entries":[{"key":"database","value":"default"}]}]}' localhost:8081 envoy.service.ratelimit.v2.RateLimitService.ShouldRateLimit
{
"overallCode": "OK",
"statuses": [
{
"code": "OK",
"currentLimit": {
"requestsPerUnit": 2,
"unit": "MINUTE"
},
"limitRemaining": 1
}
]
}
limitRemaining
is omitted if it's zero:
[:~/monadfix/juspay/fencer] master+* ± grpcurl -proto proto/rls.proto -plaintext -d '{"domain":"mongo_cps", "descriptors":[{"entries":[{"key":"database","value":"default"}]}]}' localhost:8081 envoy.service.ratelimit.v2.RateLimitService.ShouldRateLimit
{
"overallCode": "OK",
"statuses": [
{
"code": "OK",
"currentLimit": {
"requestsPerUnit": 2,
"unit": "MINUTE"
}
}
]
}
I think our behavior is nicer (and unlikely to break any consumers), but we should document the difference.
The Contribution Guidelines could use instructions for how to add a Git hook for Hlint. Add them.
The only server test we have so far Fencer.Server.Test.test_responseNoRules
non-deterministically fails with:
When no rules have been loaded, all requests error out: FAIL
test/Fencer/Server/Test.hs:44:
Got wrong gRPC error response
expected: ClientIOError (GRPCIOBadStatusCode StatusUnknown (StatusDetails {unStatusDetails = "rate limit descriptor list must not be empty"}))
but got: ClientIOError (GRPCIOBadStatusCode StatusUnavailable (StatusDetails {unStatusDetails = "Endpoint read failed"}))
or with:
When no rules have been loaded, all requests error out: FAIL
test/Fencer/Server/Test.hs:48:
Expected an error response, got a normal response: status = StatusOk, result = RateLimitResponse {rateLimitResponseOverallCode = Enumerated {enumerated = Right RateLimitResponse_CodeOK}, rateLimitResponseStatuses = [], rateLimitResponseHeaders = []}
or with:
Got wrong gRPC error response
expected: ClientIOError (GRPCIOBadStatusCode StatusUnknown (StatusDetails {unStatusDetails = "rate limit descriptor list must not be empty"}))
but got: ClientIOError GRPCIOTimeout
Pin down the root cause and why it fails only sometimes.
Modify fencer.nix and .gitlab-ci.yml so that the CI runs the tests. Add a testHaskellDepends
section to fencer.nix, which should hopefully run the tests automatically.
It takes several minutes to download doc packages and build the Hoogle index, we should skip that.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.