Skip to content

Commit

Permalink
Merge pull request #3 from Qordobacode/NOTICKET--retry-on-connection-…
Browse files Browse the repository at this point in the history
…error

Noticket  retry on connection error
  • Loading branch information
sam-writer authored Jan 7, 2020
2 parents 7ce5dcf + 6b328cc commit ee29fd8
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 12 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) (sort of. It's early days, and there may be some breaking changes released under a minor version increment).

## [0.14.0] - 2019-12-26

Boxing Day update!

### Changed

- Added named parameter `connection_retries` to `MarianClient`, default value is `10`
- Added named parameter `max_wait_time_between_connection_attempts` to `MarianClient`, default value is `300`
- When instantiating a `MarianClient` instance, if we receive a `ConnectionRefusedError`, attempt to reconnect `connection_retries` times, with exponential backoff, maxing out at `max_wait_time_between_connection_attempts`.
- This means in the default case, if Marian Server is unavailable, we will try to connect, wait 1 second, try to connect again, wait 2 seconds, try to connect again, wait 4 seconds, ... then 8, 16, 32, 64, 128, 256, 300, then actually fail, for a total wait time of 811 seconds.

## [0.13.0] - 2019-12-11

### Fixed

- `install_requires` wasn't bringing in a needed package; hardocding fixes this.

### Changed

- `build_release.sh` now accepts a second parameter: the string `minor` or `patch`. This determines how the version is bumped. As a reminder, the first parameter is the PyPi credential file location, default is `~/.pypirc`.

## [0.11.0] - 2019-12-10

### Fixed
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ else:
# >>> "Alice likes cats ."
```

## Notes

* When instantiating a `MarianClient` instance, if we receive a `ConnectionRefusedError`, we attempt to reconnect `connection_retries` times, with exponential backoff, maxing out at `max_wait_time_between_connection_attempts`.
* This means in the default case, if Marian Server is unavailable, we will try to connect, wait 1 second, try to connect again, wait 2 seconds, try to connect again, wait 4 seconds, ... then 8, 16, 32, 64, 128, 256, 300, then actually fail, for a total wait time of 811 seconds.

## License

Like Marian, this package is released under the MIT license.
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.11.0
0.14.0
20 changes: 16 additions & 4 deletions build_release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ V_MAJOR=${BASE_LIST[0]}
V_MINOR=${BASE_LIST[1]}
V_PATCH=${BASE_LIST[2]}
echo -e "Current version: $BASE_STRING"
V_MINOR=$((V_MINOR + 1))
V_PATCH=0
SUGGESTED_VERSION="$V_MAJOR.$V_MINOR.$V_PATCH"


INVENV=$(python3 -c 'import sys; print ("1" if hasattr(sys, "base_prefix") else "0")')
CREDS_LOCATION=$1
PATCH_OR_MINOR=${2:-minor}


check_credential_file_exists ()
Expand Down Expand Up @@ -46,7 +45,20 @@ update_deps ()

bump_version ()
{
echo "Bumping minor version in VERSION file"
# @TODO support "major" as well
if [ "$PATCH_OR_MINOR" = "patch" ]; then
echo "Bumping patch version in VERSION file"
V_PATCH=$((V_PATCH + 1))
elif [ "$PATCH_OR_MINOR" = "minor" ]; then
echo "Bumping minor version in VERSION file"
V_MINOR=$((V_MINOR + 1))
V_PATCH=0
else
echo "ERROR, 2nd argument should be 'patch', 'minor' or not set"
exit 1
fi

SUGGESTED_VERSION="$V_MAJOR.$V_MINOR.$V_PATCH"
echo ""
echo "$SUGGESTED_VERSION" > VERSION
}
Expand Down
41 changes: 36 additions & 5 deletions marian_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@ def __init__(self, status_code=408, error_message="WebSocketTimeoutException"):

class MarianClient:
def __init__(
self, HOST=None, PORT=None, url=None, timeout=None, retries=None, debug=False
self,
HOST=None,
PORT=None,
url=None,
timeout=None,
retries=None,
connection_retries=10,
max_wait_time_between_connection_attempts=300,
debug=False,
):
self.debug = debug

Expand Down Expand Up @@ -56,21 +64,44 @@ def __init__(
if not PORT:
PORT = 8080
self.url = f"ws://{HOST}:{PORT}/translate"
self.ws = create_connection(self.url, timeout=self.timeout)

self.reset_connection_count = 0
CONNECTED_TO_MARIAN = False
while (
self.reset_connection_count < connection_retries and not CONNECTED_TO_MARIAN
):
try:
self.ws = create_connection(self.url, timeout=self.timeout)
CONNECTED_TO_MARIAN = True
except ConnectionRefusedError:
print("Can't connect to Marian Server")
print(
f"Will try to connect {connection_retries - self.reset_connection_count} more times, with exponentially increasing time between"
)
self.exponential_backoff(
self.reset_connection_count,
MAX_BACKOFF_WAIT=max_wait_time_between_connection_attempts,
)
self.reset_connection_count += 1
print("trying to connect to Marian server again...")

# if we can't connect after that long, actually fail
if not hasattr(self, "ws"):
raise ConnectionRefusedError("Can't connect to Marian Server")

def __del__(self):
""" clean up after yourself """
if self.ws and self.ws.connected:
if hasattr(self, "ws") and self.ws.connected:
self.ws.close()

def exponential_backoff(self, tries_so_far):
def exponential_backoff(self, tries_so_far, MAX_BACKOFF_WAIT=None):
"""
don't just hammer the server, wait in between retries
the more retries, the longer the wait
"""
print(f"backing off, tries so far: {tries_so_far}")
MAX_BACKOFF_WAIT = self.timeout + 4 # just in case add some buffer
if MAX_BACKOFF_WAIT is None:
MAX_BACKOFF_WAIT = self.timeout + 4 # just in case add some buffer
sleep(min(2 ** tries_so_far, MAX_BACKOFF_WAIT))

def _ws_healthy(self):
Expand Down
2 changes: 1 addition & 1 deletion marian_client/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# CHANGES HERE HAVE NO EFFECT: ../VERSION is the source of truth
__version__ = "0.11.0"
__version__ = "0.14.0"
4 changes: 3 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
long_description=long_description,
long_description_content_type="text/markdown",
python_requires=">=3.6.4",
install_requires=install_requires,
# install_requires=install_requires,
# there is NO REASON this should be needed
install_requires=["websocket-client==0.56.0"],
tests_require=tests_require,
)

0 comments on commit ee29fd8

Please sign in to comment.