Skip to content

Commit a3fea2a

Browse files
authored
Chore: Bring back RateLimiter. (#6671)
We deleted the tensorboard.uploader.util.RateLImiter in #6638. However it is used internally and needs to be returned. This is therefore a partial rollback of #6638.
1 parent d379d08 commit a3fea2a

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

tensorboard/uploader/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ py_test(
211211
name = "util_test",
212212
srcs = ["util_test.py"],
213213
deps = [
214+
":test_util",
214215
":util",
215216
"//tensorboard:expect_grpc_installed",
216217
"//tensorboard:expect_protobuf_installed",

tensorboard/uploader/util.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,28 @@
1919
import errno
2020
import os
2121
import os.path
22+
import time
23+
24+
25+
class RateLimiter:
26+
"""Helper class for rate-limiting using a fixed minimum interval."""
27+
28+
def __init__(self, interval_secs):
29+
"""Constructs a RateLimiter that permits a tick() every
30+
`interval_secs`."""
31+
self._time = time # Use property for ease of testing.
32+
self._interval_secs = interval_secs
33+
self._last_called_secs = 0
34+
35+
def tick(self):
36+
"""Blocks until it has been at least `interval_secs` since last
37+
tick()."""
38+
wait_secs = (
39+
self._last_called_secs + self._interval_secs - self._time.time()
40+
)
41+
if wait_secs > 0:
42+
self._time.sleep(wait_secs)
43+
self._last_called_secs = self._time.time()
2244

2345

2446
def get_user_config_directory():

tensorboard/uploader/util_test.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,35 @@
2222
from unittest import mock
2323

2424
from google.protobuf import timestamp_pb2
25+
from tensorboard.uploader import test_util
2526
from tensorboard.uploader import util
2627
from tensorboard import test as tb_test
2728

2829

30+
class RateLimiterTest(tb_test.TestCase):
31+
def test_rate_limiting(self):
32+
rate_limiter = util.RateLimiter(10)
33+
fake_time = test_util.FakeTime(current=1000)
34+
with mock.patch.object(rate_limiter, "_time", fake_time):
35+
self.assertEqual(1000, fake_time.time())
36+
# No sleeping for initial tick.
37+
rate_limiter.tick()
38+
self.assertEqual(1000, fake_time.time())
39+
# Second tick requires a full sleep.
40+
rate_limiter.tick()
41+
self.assertEqual(1010, fake_time.time())
42+
# Third tick requires a sleep just to make up the remaining second.
43+
fake_time.sleep(9)
44+
self.assertEqual(1019, fake_time.time())
45+
rate_limiter.tick()
46+
self.assertEqual(1020, fake_time.time())
47+
# Fourth tick requires no sleep since we have no remaining seconds.
48+
fake_time.sleep(11)
49+
self.assertEqual(1031, fake_time.time())
50+
rate_limiter.tick()
51+
self.assertEqual(1031, fake_time.time())
52+
53+
2954
class GetUserConfigDirectoryTest(tb_test.TestCase):
3055
def test_windows(self):
3156
with mock.patch.object(os, "name", "nt"):

0 commit comments

Comments
 (0)