add mcp
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import os
|
||||
import pickle
|
||||
import random
|
||||
import sqlite3
|
||||
import time
|
||||
from datetime import datetime, date, timezone
|
||||
from typing import Tuple, Dict, List, Optional
|
||||
import getpass
|
||||
@@ -15,6 +17,80 @@ import json
|
||||
GITLAB_URL_DEFAULT = "https://mmgit.eltex-co.ru"
|
||||
COOKIE_FILE_DEFAULT = "cookies.pkl"
|
||||
|
||||
THROTTLE_DEFAULTS = {
|
||||
"min_delay": 0.4,
|
||||
"max_delay": 1.8,
|
||||
"burst_pause_every": 12,
|
||||
"burst_pause_min": 3.0,
|
||||
"burst_pause_max": 8.0,
|
||||
"file_delay_multiplier": 1.5,
|
||||
}
|
||||
|
||||
|
||||
class RequestThrottler:
|
||||
"""Paces API calls with jitter and occasional longer pauses."""
|
||||
|
||||
def __init__(self, **opts):
|
||||
self.min_delay = opts["min_delay"]
|
||||
self.max_delay = opts["max_delay"]
|
||||
self.burst_pause_every = opts["burst_pause_every"]
|
||||
self.burst_pause_min = opts["burst_pause_min"]
|
||||
self.burst_pause_max = opts["burst_pause_max"]
|
||||
self.file_delay_multiplier = opts["file_delay_multiplier"]
|
||||
self._request_count = 0
|
||||
self._last_request_at = 0.0
|
||||
|
||||
def wait(self, endpoint: str = "") -> None:
|
||||
self._request_count += 1
|
||||
if self.burst_pause_every and self._request_count % self.burst_pause_every == 0:
|
||||
delay = random.uniform(self.burst_pause_min, self.burst_pause_max)
|
||||
else:
|
||||
delay = random.uniform(self.min_delay, self.max_delay)
|
||||
|
||||
if endpoint.startswith("/files/"):
|
||||
delay *= self.file_delay_multiplier
|
||||
|
||||
elapsed = time.monotonic() - self._last_request_at
|
||||
if elapsed < delay:
|
||||
time.sleep(delay - elapsed)
|
||||
self._last_request_at = time.monotonic()
|
||||
|
||||
|
||||
def _parse_throttle_config(config: dict) -> Optional[dict]:
|
||||
throttle = config.get("throttle")
|
||||
if not throttle:
|
||||
return None
|
||||
if throttle is True:
|
||||
return dict(THROTTLE_DEFAULTS)
|
||||
if isinstance(throttle, dict):
|
||||
if not throttle.get("enabled", True):
|
||||
return None
|
||||
opts = dict(THROTTLE_DEFAULTS)
|
||||
opts.update({k: v for k, v in throttle.items() if k != "enabled"})
|
||||
return opts
|
||||
return None
|
||||
|
||||
|
||||
def apply_throttle(d: Driver, config: dict) -> None:
|
||||
opts = _parse_throttle_config(config)
|
||||
if not opts:
|
||||
return
|
||||
|
||||
throttler = RequestThrottler(**opts)
|
||||
client = d.client
|
||||
original_make_request = client.make_request
|
||||
|
||||
def throttled_make_request(method, endpoint, options=None, params=None, data=None, files=None, basepath=None):
|
||||
throttler.wait(endpoint)
|
||||
return original_make_request(method, endpoint, options, params, data, files, basepath)
|
||||
|
||||
client.make_request = throttled_make_request
|
||||
print(
|
||||
"Request throttling enabled "
|
||||
f"(delay {opts['min_delay']}-{opts['max_delay']}s, "
|
||||
f"pause every {opts['burst_pause_every']} requests)"
|
||||
)
|
||||
|
||||
|
||||
def connect(host: str, login_token: str = None, username: str = None, password: str = None) -> Driver:
|
||||
d = Driver({
|
||||
@@ -568,6 +644,7 @@ if __name__ == '__main__':
|
||||
config.get("username", None),
|
||||
config.get("password", None),
|
||||
)
|
||||
apply_throttle(d, config)
|
||||
except Exception as e:
|
||||
# If token-based authentication failed, drop the token and ask
|
||||
# the user to rerun the script so that fresh credentials can be
|
||||
|
||||
Reference in New Issue
Block a user