Skip to content

Instantly share code, notes, and snippets.

@vincentml
Created February 5, 2016 01:34
Show Gist options
  • Save vincentml/444cf2c0362a337c1cc9 to your computer and use it in GitHub Desktop.
Save vincentml/444cf2c0362a337c1cc9 to your computer and use it in GitHub Desktop.
Throttle pause for BaseX
(:~ Throttling module for BaseX
:
: Only one method for now, may add alterate throttling methods in future.
:
:)
module namespace _ = "throttle";
declare namespace store = 'java.util.HashMap';
declare variable $_:store := store:new();
(:~ Throttle that creates a pause if called more than a certain number of times within a certain number of milliseconds
: For example, when calling an API to ensure no more than 3 requests are made per second between repetitive calls: throttle:throttle('apiname',3,1000,1000)
:)
declare function _:throttle ($name as xs:string, $numberToAllow as xs:integer, $withinMSeconds as xs:integer, $pauseMSeconds as xs:integer) {
if (not(store:contains-key($_:store, concat('last-',$name)))) then (
prof:void(store:put($_:store, concat('last-',$name), prof:current-ms())),
prof:void(store:put($_:store, concat('count-',$name), 1))
) else if (prof:current-ms() - store:get($_:store, concat('last-',$name)) < $withinMSeconds and store:get($_:store, concat('count-',$name)) >= $numberToAllow) then (
prof:sleep($pauseMSeconds),
prof:void(store:put($_:store, concat('last-',$name), prof:current-ms())),
prof:void(store:put($_:store, concat('count-',$name), 1))
) else (
prof:void(store:put($_:store, concat('count-',$name), 1 + store:get($_:store,concat('count-',$name))))
)
};
declare %unit:test function _:throttle-test() {
let $data := for $n in 1 to 5
return (
_:throttle('test',2,1000,3000),
<i><n>{$n}</n><t>{floor(prof:current-ms() div 1000)}</t><c>{store:get($_:store,'count-test')}</c><l>{store:get($_:store,'last-test')}</l></i>
)
return (
unit:assert(count(distinct-values($data/t)) eq 3),
unit:assert(count($data[c = 1]) eq 3),
unit:assert($data[2]/t - $data[1]/t < 1),
unit:assert($data[3]/t - $data[2]/t >= 3),
unit:assert($data[4]/t - $data[3]/t < 1),
unit:assert($data[5]/t - $data[4]/t >= 3),
prof:dump($data)
)
};
(:~
Example:
import module namespace throttle = "throttle" at "throttle.xqm";
let $start := prof:current-ms()
for $n in 1 to 16
return (
throttle:throttle('example', 4, 1000, 3000),
$n || ' second ' || round((prof:current-ms() - $start) div 1000)
)
Output:
1 second 0
2 second 0
3 second 0
4 second 0
5 second 3
6 second 3
7 second 3
8 second 3
9 second 6
10 second 6
11 second 6
12 second 6
13 second 9
14 second 9
15 second 9
16 second 9
:)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment