From 5b0d3d1429cfc369bd6bcd1d0f21ac8f46645c7f Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Mon, 9 Oct 2017 16:31:01 +0100 Subject: [PATCH] simplify rate-limit checking code --- .../Features/Compile/CompileManager.coffee | 47 ++++++------------- services/web/config/settings.defaults.coffee | 5 ++ .../coffee/Compile/CompileManagerTests.coffee | 16 +++---- 3 files changed, 28 insertions(+), 40 deletions(-) diff --git a/services/web/app/coffee/Features/Compile/CompileManager.coffee b/services/web/app/coffee/Features/Compile/CompileManager.coffee index 756222121a..9e50b280e2 100755 --- a/services/web/app/coffee/Features/Compile/CompileManager.coffee +++ b/services/web/app/coffee/Features/Compile/CompileManager.coffee @@ -18,7 +18,7 @@ module.exports = CompileManager = timer.done() _callback(args...) - @_checkIfAutoCompileLimitHasBeenHit options.isAutoCompile, (err, canCompile)-> + @_checkIfAutoCompileLimitHasBeenHit options.isAutoCompile, "everyone", (err, canCompile)-> if !canCompile return callback null, "autocompile-backoff", [] logger.log project_id: project_id, user_id: user_id, "compiling project" @@ -34,8 +34,8 @@ module.exports = CompileManager = return callback(error) if error? for key, value of limits options[key] = value - # Put a lower limit on autocompiles for free users - CompileManager._checkIfFreeAutoCompileLimitHasBeenHit options.isAutoCompile, limits.compileGroup, (err, canCompile)-> + # Put a lower limit on autocompiles for free users, based on compileGroup + CompileManager._checkCompileGroupAutoCompileLimit options.isAutoCompile, limits.compileGroup, (err, canCompile)-> if !canCompile return callback null, "autocompile-backoff", [] # only pass user_id down to clsi if this is a per-user compile @@ -76,44 +76,27 @@ module.exports = CompileManager = else return callback null, true - _checkIfAutoCompileLimitHasBeenHit: (isAutoCompile, callback = (err, canCompile)->)-> + _checkCompileGroupAutoCompileLimit: (isAutoCompile, compileGroup, callback = (err, canCompile)->)-> + if compileGroup is "default" + CompileManager._checkIfAutoCompileLimitHasBeenHit isAutoCompile, compileGroup, callback + else + Metrics.inc "auto-compile-#{compileGroup}" + return callback(null, true) # always allow priority group users to compile + + _checkIfAutoCompileLimitHasBeenHit: (isAutoCompile, compileGroup, callback = (err, canCompile)->)-> if !isAutoCompile return callback(null, true) - Metrics.inc "auto-compile" + Metrics.inc "auto-compile-#{compileGroup}" opts = endpointName:"auto_compile" timeInterval:20 - subjectName:"everyone" - throttle: 200 + subjectName:compileGroup + throttle: Settings?.rateLimit?.autoCompile?[compileGroup] || 25 rateLimiter.addCount opts, (err, canCompile)-> if err? canCompile = false - logger.log canCompile:canCompile, opts:opts, "checking if auto compile limit has been hit" if !canCompile - Metrics.inc "auto-compile-rate-limited" - callback err, canCompile - - - _checkIfFreeAutoCompileLimitHasBeenHit: (isAutoCompile, compileGroup, callback = (err, canCompile)->)-> - if !isAutoCompile - return callback(null, true) - - if compileGroup is "priority" - Metrics.inc "auto-compile-priority" - return callback(null, true) - - Metrics.inc "auto-compile-free" - opts = - endpointName:"auto_compile" - timeInterval:20 - subjectName:"free" - throttle: 100 - rateLimiter.addCount opts, (err, canCompile)-> - if err? - canCompile = false - logger.log canCompile:canCompile, opts:opts, "checking if free users auto compile limit has been hit" - if !canCompile - Metrics.inc "auto-compile-free-rate-limited" + Metrics.inc "auto-compile-#{compileGroup}-limited" callback err, canCompile _ensureRootDocumentIsSet: (project_id, callback = (error) ->) -> diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee index 2456590709..94e9ae5007 100644 --- a/services/web/config/settings.defaults.coffee +++ b/services/web/config/settings.defaults.coffee @@ -437,3 +437,8 @@ module.exports = settings = # name : "all projects", # url: "/templates/all" #}] + + rateLimits: + autoCompile: + everyone: 100 + standard: 25 diff --git a/services/web/test/UnitTests/coffee/Compile/CompileManagerTests.coffee b/services/web/test/UnitTests/coffee/Compile/CompileManagerTests.coffee index 21327a50c9..195da8b850 100644 --- a/services/web/test/UnitTests/coffee/Compile/CompileManagerTests.coffee +++ b/services/web/test/UnitTests/coffee/Compile/CompileManagerTests.coffee @@ -44,7 +44,7 @@ describe "CompileManager", -> describe "succesfully", -> beforeEach -> - @CompileManager._checkIfAutoCompileLimitHasBeenHit = (_, cb)-> cb(null, true) + @CompileManager._checkIfAutoCompileLimitHasBeenHit = (isAutoCompile, compileGroup, cb)-> cb(null, true) @CompileManager.compile @project_id, @user_id, {}, @callback it "should check the project has not been recently compiled", -> @@ -84,7 +84,7 @@ describe "CompileManager", -> describe "when the project has been recently compiled", -> it "should return", (done)-> - @CompileManager._checkIfAutoCompileLimitHasBeenHit = (_, cb)-> cb(null, true) + @CompileManager._checkIfAutoCompileLimitHasBeenHit = (isAutoCompile, compileGroup, cb)-> cb(null, true) @CompileManager._checkIfRecentlyCompiled = sinon.stub().callsArgWith(2, null, true) @CompileManager.compile @project_id, @user_id, {}, (err, status)-> status.should.equal "too-recently-compiled" @@ -92,7 +92,7 @@ describe "CompileManager", -> describe "should check the rate limit", -> it "should return", (done)-> - @CompileManager._checkIfAutoCompileLimitHasBeenHit = sinon.stub().callsArgWith(1, null, false) + @CompileManager._checkIfAutoCompileLimitHasBeenHit = sinon.stub().callsArgWith(2, null, false) @CompileManager.compile @project_id, @user_id, {}, (err, status)-> status.should.equal "autocompile-backoff" done() @@ -222,14 +222,14 @@ describe "CompileManager", -> describe "_checkIfAutoCompileLimitHasBeenHit", -> it "should be able to compile if it is not an autocompile", (done)-> - @ratelimiter.addCount.callsArgWith(1, null, true) - @CompileManager._checkIfAutoCompileLimitHasBeenHit false, (err, canCompile)=> + @ratelimiter.addCount.callsArgWith(2, null, true) + @CompileManager._checkIfAutoCompileLimitHasBeenHit false, "everyone", (err, canCompile)=> canCompile.should.equal true done() it "should be able to compile if rate limit has remianing", (done)-> @ratelimiter.addCount.callsArgWith(1, null, true) - @CompileManager._checkIfAutoCompileLimitHasBeenHit true, (err, canCompile)=> + @CompileManager._checkIfAutoCompileLimitHasBeenHit true, "everyone", (err, canCompile)=> args = @ratelimiter.addCount.args[0][0] args.throttle.should.equal 25 args.subjectName.should.equal "everyone" @@ -240,13 +240,13 @@ describe "CompileManager", -> it "should be not able to compile if rate limit has no remianing", (done)-> @ratelimiter.addCount.callsArgWith(1, null, false) - @CompileManager._checkIfAutoCompileLimitHasBeenHit true, (err, canCompile)=> + @CompileManager._checkIfAutoCompileLimitHasBeenHit true, "everyone", (err, canCompile)=> canCompile.should.equal false done() it "should return false if there is an error in the rate limit", (done)-> @ratelimiter.addCount.callsArgWith(1, "error") - @CompileManager._checkIfAutoCompileLimitHasBeenHit true, (err, canCompile)=> + @CompileManager._checkIfAutoCompileLimitHasBeenHit true, "everyone", (err, canCompile)=> canCompile.should.equal false done()