Skip to content
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

Update publish-snapshot.yml #119

Draft
wants to merge 29 commits into
base: release-3.1
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9c7e35d
Update publish-snapshot.yml
davitmamrikishvili Dec 18, 2024
a44ddaa
Update package_info.json
davitmamrikishvili Dec 18, 2024
d811685
Add retries
davitmamrikishvili Dec 18, 2024
5c6bb6e
Add import
davitmamrikishvili Dec 18, 2024
d889f28
Merge pull request #120 from th2-net/pypi_add-retries
davitmamrikishvili Dec 18, 2024
24e0979
Fix GetEventsById in async mode
ConnectDIY Dec 19, 2024
61da244
Fix GetEventsById in async mode
ConnectDIY Dec 19, 2024
75550e4
Add RetryLogger
davitmamrikishvili Dec 19, 2024
11cbca5
Trigger workflow
davitmamrikishvili Dec 19, 2024
06d674b
Trigger workflow
davitmamrikishvili Dec 19, 2024
2321aab
Trigger workflow
davitmamrikishvili Dec 19, 2024
ebb5bc5
Trigger workflow
davitmamrikishvili Dec 19, 2024
86a734e
Trigger workflow
davitmamrikishvili Dec 19, 2024
7c64056
Trigger workflow
davitmamrikishvili Dec 19, 2024
a8a18a0
Trigger workflow
davitmamrikishvili Dec 19, 2024
6e454cd
Trigger workflow
davitmamrikishvili Dec 19, 2024
4b85f8a
Trigger workflow
davitmamrikishvili Dec 19, 2024
1fdd24a
Trigger workflow
davitmamrikishvili Dec 19, 2024
470a370
Trigger workflow
davitmamrikishvili Dec 19, 2024
37fb9a6
Trigger workflow
davitmamrikishvili Dec 19, 2024
1330eb7
Trigger workflow
davitmamrikishvili Dec 19, 2024
25a126a
Trigger workflow
davitmamrikishvili Dec 20, 2024
0dfff46
Update publish-snapshot.yml
davitmamrikishvili Dec 20, 2024
13803c2
Trigger workflow
davitmamrikishvili Dec 20, 2024
f4924eb
Trigger workflow
davitmamrikishvili Dec 20, 2024
14697e4
Trigger workflow
davitmamrikishvili Dec 20, 2024
f8ba90b
Update publish-snapshot.yml
davitmamrikishvili Dec 20, 2024
d7d6ef1
Update publish-snapshot.yml
davitmamrikishvili Dec 20, 2024
6947561
Update publish-snapshot.yml
davitmamrikishvili Dec 20, 2024
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
4 changes: 3 additions & 1 deletion .github/workflows/publish-snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
jobs:
build-job:
name: Check and publish snapshot tarball to PyPi
uses: th2-net/.github/.github/workflows/compound-python.yml@main
uses: th2-net/.github/.github/workflows/compound-python.yml@vulnerability-scan-fix
with:
release-type: development
style-check-enabled: false
Expand All @@ -23,3 +23,5 @@ jobs:

secrets:
pypi-password: ${{ secrets.PYPI_PASSWORD }}


2 changes: 1 addition & 1 deletion package_info.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"package_name": "th2-data-services-lwdp",
"package_version": "3.1.1.0"
"package_version": "3.1.2.0"
}

2 changes: 2 additions & 0 deletions release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,5 @@ BugFixes without ticket

## Improvements
1. [TH2-5260] More details are provided in case an exception occurs in `StatusUpdateManager.update()`.
2. [TH2-5263] Retries are added to `IHTTPDataSource.check_connect()`.
3. [TH2-5264] Retries are added to `nest_asyncio.apply()`.
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ orjson>=3.10,<4
aiohttp>=3.9.5,<4
nest-asyncio>=1.6.0,<2
attrs!=24.3.0 # Temporary solution to license problem
retry>=0.9,<1
58 changes: 38 additions & 20 deletions th2_data_services/data_source/lwdp/commands/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,28 @@
_check_list_or_tuple,
_check_response_formats,
)
from th2_data_services.data_source.lwdp.utils._retry_logger import RetryLogger
from th2_data_services.data_source.lwdp.utils.iter_status_manager import StatusUpdateManager
from th2_data_services.data_source.lwdp.utils._misc import (
get_utc_datetime_now,
_get_response_format,
)
from th2_data_services.utils._json import BufferedJSONProcessor
from th2_data_services.data_source.lwdp.page import PageNotFound
from retry.api import retry_call
from retry import retry

Event = dict
nest_asyncio.apply() # This patch allows nested use of asyncio.run() in environments with an existing event loop.
retry_call(
# This patch allows nested use of asyncio.run() in environments with an existing event loop.
# This Retry mechanism is required as workaround because we often face
# "Only one usage of each socket address (protocol/network address/port)
# is normally permitted" issue on Windows.
nest_asyncio.apply,
delay=5,
tries=10,
logger=RetryLogger(nest_asyncio.apply),
)

# Available stream formats:
# 1) str
Expand Down Expand Up @@ -627,24 +639,26 @@ def handle(self, data_source: DataSource) -> dict: # noqa: D102
else:
return response.json()

async def async_handle(self, data_source: DataSource) -> dict: # noqa: D102
async def async_handle(self, data_source: DataSource, session=None) -> dict: # noqa: D102
api: API = data_source.source_api
url = api.get_url_find_event_by_id(self._id)

async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
json_response = await response.text()
if session is None:
session = aiohttp.ClientSession()

if response.status == 404 and self._stub_status:
stub = data_source.event_stub_builder.build(
{data_source.event_struct.EVENT_ID: self._id}
)
return stub
elif response.status == 404:
# LOG logger.error(f"Unable to find the message. Id: {self._id}")
raise EventNotFound(self._id, "Unable to find the event")
else:
return orjson.loads(json_response)
async with session.get(url) as response:
json_response = await response.text()

if response.status == 404 and self._stub_status:
stub = data_source.event_stub_builder.build(
{data_source.event_struct.EVENT_ID: self._id}
)
return stub
elif response.status == 404:
# LOG logger.error(f"Unable to find the message. Id: {self._id}")
raise EventNotFound(self._id, "Unable to find the event")
else:
return orjson.loads(json_response)


class GetEventsById(IHTTPCommand):
Expand All @@ -671,6 +685,7 @@ def __init__(self, ids: List[str], use_stub=False):
self._ids: ids = ids
self._stub_status = use_stub

@retry(tries=5, delay=5, logger=RetryLogger("handle"))
def handle(self, data_source: DataSource) -> List[dict]: # noqa: D102
# return self._sync_handle(data_source)
return asyncio.run(self._async_handle(data_source))
Expand All @@ -685,13 +700,16 @@ def _sync_handle(self, data_source: DataSource) -> List[dict]: # noqa: D102

async def _async_handle(self, data_source: DataSource) -> List[dict]: # noqa: D102
coros = []
for event_id in self._ids:
co_event = GetEventById(event_id, use_stub=self._stub_status).async_handle(data_source)
coros.append(co_event)
async with aiohttp.ClientSession() as session:
for event_id in self._ids:
co_event = GetEventById(event_id, use_stub=self._stub_status).async_handle(
data_source, session
)
coros.append(co_event)

events = await asyncio.gather(*coros)
events = await asyncio.gather(*coros)

return events
return events


class GetEventsByPage(IHTTPCommand):
Expand Down
6 changes: 6 additions & 0 deletions th2_data_services/data_source/lwdp/interfaces/data_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
from th2_data_services.data_source.lwdp.interfaces.source_api import IHTTPSourceAPI
from th2_data_services.data_source.lwdp.struct import IEventStruct, IMessageStruct
from th2_data_services.data_source.lwdp.stub_builder import IEventStub, IMessageStub
from th2_data_services.data_source.lwdp.utils._retry_logger import RetryLogger
from retry import retry

CommandT = TypeVar("CommandT", bound="ILwDPCommand")
EventStructT = TypeVar("EventStructT", bound="IEventStruct")
Expand Down Expand Up @@ -110,6 +112,10 @@ class IHTTPDataSource(
def command(self, cmd):
"""Execute the transmitted HTTP command."""

@retry(tries=5, delay=5, logger=RetryLogger("check_connect"))
# This Retry mechanism is required as workaround because we often face
# "Only one usage of each socket address (protocol/network address/port)
# is normally permitted" issue on Windows
def check_connect(self, timeout: Tuple[int, float], certification: bool = True) -> None:
"""Checks whether url is working.

Expand Down
36 changes: 36 additions & 0 deletions th2_data_services/data_source/lwdp/utils/_retry_logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright 2024 Exactpro (Exactpro Systems Limited)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


class RetryLogger:
def __init__(self, name):
"""Initialize the RetryLogger.

Args:
name (Union[str, Callable]): The name of the function being retried.
If a function is provided, its __name__ attribute will be used.
"""
if callable(name):
name = name.__name__
self._name = name

def warning(self, fmt, error, delay):
"""Log a warning message when a function execution fails and will be retried.

Args:
fmt: Format string for the warning message (unused).
error: The error that caused the function to fail.
delay: Number of seconds before the next retry attempt.
"""
print(f"Function {self._name} failed with {error}. Retrying in {delay} seconds.")
Loading