-
Notifications
You must be signed in to change notification settings - Fork 60
feat(gooddata-pipelines): Process workspace backup sequentially #1138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
79dbe0e to
ba0d8ab
Compare
| return 0.0 | ||
|
|
||
| def __enter__(self) -> "RateLimiter": | ||
| self.wait_if_needed() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be great if we could use the rate limiter as a decorator instead of context manager... My assumption is that it could be more versatile (for handling the methods from gooddata_sdk) and less verbose (we could wrap functions/methods with @rate_limiter instead of the with ... blocks and the rate limiter would not have to be a part of the instanced object (like the BackupManager). WDYT?
| self, | ||
| calls_per_second: float = 1.0, | ||
| name: Optional[str] = None, | ||
| logger: Optional[Any] = None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can reuse the LoggerLike protocol from gooddata-pipelines/gooddata_pipelines/logger/logger.py here as the logger type
|
|
||
| self.calls_per_second = calls_per_second | ||
| self.min_interval = 1.0 / calls_per_second | ||
| self.name = name or "RateLimiter" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is necessary
| from typing import Any, Optional | ||
|
|
||
|
|
||
| class RateLimiter: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be great if this had some tests
| if time_since_last_call < self.min_interval: | ||
| sleep_time = self.min_interval - time_since_last_call | ||
|
|
||
| if self.logger: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a second thought, I'd consider if it's worth logging every wait and if the logger is needed - it has a potential for being super spammy (1000 workspaces, say 3-5 waits per each?)
| self._lock = threading.Lock() | ||
| self._last_call_time = 0.0 | ||
|
|
||
| def wait_if_needed(self) -> float: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this method have a return value? If I see it correctly, it is not stored or read anywhere...
e3020ad to
bfe8f11
Compare
bfe8f11 to
1d466f5
Compare
No description provided.