Skip to content

Ratelimit soap requests #14

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions example.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
The resource will be toggled when the test starts, and after this you can set it
using '1' and '2'. 'q' to quit
"""

import logging
import sys

Expand All @@ -15,12 +16,13 @@

_LOGGER = logging.getLogger(__name__)


def main():
"""Do the test"""

logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logging.basicConfig(stream=sys.stdout, level=logging.WARNING)
# set log level below to debug for further troubleshooting
logging.getLogger("ihcsdk").setLevel( logging.INFO)
logging.getLogger("ihcsdk").setLevel(logging.WARNING)

starttime = datetime.now()

Expand Down Expand Up @@ -51,6 +53,8 @@ def gettime():
print("Url response like a IHC controller - now authenticating")

ihc = IHCController(url, username, password)
ihc.client.connection.min_interval = 0.05
ihc.client.connection.logtiming = True
if not ihc.authenticate():
print("Authenticate failed")
exit()
Expand All @@ -69,6 +73,7 @@ def gettime():
print("log: " + log)

info = ihc.client.get_system_info()
print("System info: ")
print(info)

runtimevalue = ihc.get_runtime_value(resid)
Expand All @@ -78,10 +83,14 @@ def gettime():
print("Runtime value: " + str(runtimevalue))

ihc.client.enable_runtime_notification(resid)

logging.basicConfig(level=logging.DEBUG)

changes = ihc.client.wait_for_resource_value_changes(10)
print(repr(changes))

ihc.add_notify_event(resid, on_ihc_change, True)
ihc.add_notify_event(2728463, on_ihc_change, True)

while True:
i = input()
Expand All @@ -96,7 +105,6 @@ def gettime():
if i == "q":
break
ihc.disconnect()
ihc.client.connection.session.close()


main()
2 changes: 1 addition & 1 deletion ihcsdk/ihcclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ def __get_value(resource_value):
case "WSBooleanValue":
result = resource_value.find("./ns2:value", IHCSoapClient.ihcns).text == "true"
case "WSIntegerValue":
result = int( resource_value.find("./ns2:integer", IHCSoapClient.ihcns).text)
result = int(resource_value.find("./ns2:integer", IHCSoapClient.ihcns).text)
case "WSFloatingPointValue":
result = round(float(resource_value.find("./ns2:floatingPointValue", IHCSoapClient.ihcns).text), 2)
case "WSEnumValue":
Expand Down
23 changes: 21 additions & 2 deletions ihcsdk/ihcconnection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
# pylint: disable=too-few-public-methods
import logging
import requests
import time
import xml.etree.ElementTree

from urllib.parse import urlparse
from urllib3.util import Retry
from requests.adapters import HTTPAdapter

_LOGGER = logging.getLogger(__name__)



class IHCConnection(object):
"""Implements a http connection to the controller"""

Expand All @@ -35,6 +35,10 @@ def __init__(self, url: str):
allowed_methods={"POST"},
)
self.session.mount("http://", HTTPAdapter(max_retries=self.retries))
# default minimum time between calls in seconds (0 will not rate limit)
self.min_interval: float = 0.0
self.last_call_time:float = 0
self.logtiming = False

def cert_verify(self):
return None
Expand All @@ -50,6 +54,7 @@ def soap_action(self, service, action, payloadbody):
"SOAPAction": action,
}
try:
self.rateLimit()
_LOGGER.debug("soap payload %s", payload)
self.last_exception = None
response = self.session.post(
Expand All @@ -75,3 +80,17 @@ def soap_action(self, service, action, payloadbody):
self.last_exception = exp
self.last_response = response
return False

def rateLimit( self):
""" Rate limit the calls to this function."""
current_time: float = time.time()
time_since_last_call: float = current_time - self.last_call_time
if self.logtiming:
_LOGGER.warning("time since last call %f sec", time_since_last_call)
# If not enough time has passed, sleep for the remaining time
if time_since_last_call < self.min_interval:
sleep_time:float = self.min_interval - time_since_last_call
_LOGGER.debug("Ratelimiting for %f sec", sleep_time)
time.sleep(sleep_time)
# Update the last call time and call the function
self.last_call_time = time.time()
4 changes: 4 additions & 0 deletions ihcsdk/ihccontroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ def disconnect(self):
TODO call disconnect on ihcclient
"""
self._notifyrunning = False
# wait for notify thread to finish
while self._notifythread.is_alive():
time.sleep(0.1) # Optional sleep to prevent busy waiting
self.client.connection.session.close()

def get_runtime_value(self, ihcid: int):
"""Get runtime value with re-authenticate if needed"""
Expand Down
2 changes: 2 additions & 0 deletions requerements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
requests
cryptography
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

setup(
name="ihcsdk",
version="2.8.9",
version="2.8.10",
description="IHC Python SDK",
long_description=(
"SDK for connection to the LK IHC Controller. "
Expand Down