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

Load botocore i/o methods in executor #1196

Open
wants to merge 1 commit 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
44 changes: 30 additions & 14 deletions aiobotocore/client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import asyncio

from botocore.auth import resolve_auth_type
from botocore.awsrequest import prepare_request_dict
from botocore.client import (
Expand Down Expand Up @@ -41,26 +43,23 @@ async def create_client(
api_version=None,
client_config=None,
auth_token=None,
load_executor=False,
):
responses = await self._event_emitter.emit(
'choose-service-name', service_name=service_name
)
service_name = first_non_none_response(responses, default=service_name)
service_model = self._load_service_model(service_name, api_version)
try:
endpoints_ruleset_data = self._load_service_endpoints_ruleset(
service_name, api_version
)
partition_data = self._loader.load_data('partitions')
except UnknownServiceError:
endpoints_ruleset_data = None
partition_data = None
logger.info(
'No endpoints ruleset found for service %s, falling back to '
'legacy endpoint routing.',
service_name,
logger.debug(
"AioClientCreator - Method load_service_model[botocore] could generate I/O. Running in executor: %s",
load_executor,
)
Comment on lines +52 to +55
Copy link
Member

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 better to add this to the documentation instead

if load_executor:
model_data = await asyncio.get_running_loop().run_in_executor(
None, self._load_models, service_name, api_version
)

else:
model_data = self._load_models(service_name, api_version)
service_model, endpoints_ruleset_data, partition_data = model_data
cls = await self._create_client_class(service_name, service_model)
region_name, client_config = self._normalize_fips_region(
region_name, client_config
Expand Down Expand Up @@ -109,6 +108,23 @@ async def create_client(
)
return service_client

def _load_models(self, service_name, api_version):
service_model = self._load_service_model(service_name, api_version)
try:
endpoints_ruleset_data = self._load_service_endpoints_ruleset(
service_name, api_version
)
partition_data = self._loader.load_data('partitions')
except UnknownServiceError:
endpoints_ruleset_data = None
partition_data = None
logger.info(
'No endpoints ruleset found for service %s, falling back to '
'legacy endpoint routing.',
service_name,
)
return service_model, endpoints_ruleset_data, partition_data

async def _create_client_class(self, service_name, service_model):
class_attributes = self._create_methods(service_model)
py_name_to_operation_name = self._create_name_mapping(service_model)
Expand Down
28 changes: 26 additions & 2 deletions aiobotocore/session.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import asyncio
import functools

from botocore import UNSIGNED
from botocore import __version__ as botocore_version
from botocore import translate
from botocore.client import logger
from botocore.exceptions import PartialCredentialsError
from botocore.loaders import Loader
from botocore.session import EVENT_ALIASES, ServiceModel
from botocore.session import Session as _SyncSession
from botocore.session import UnknownServiceError, copy
Expand Down Expand Up @@ -37,6 +42,7 @@ def __init__(
event_hooks=None,
include_builtin_handlers=True,
profile=None,
load_executor=False,
):
if event_hooks is None:
event_hooks = AioHierarchicalEmitter()
Expand All @@ -46,6 +52,7 @@ def __init__(
)

self._set_user_agent_for_session()
self.load_executor = load_executor

def _set_user_agent_for_session(self):
# Mimic approach taken by AWS's aws-cli project
Expand Down Expand Up @@ -103,9 +110,25 @@ async def get_service_data(self, service_name, api_version=None):
Retrieve the fully merged data associated with a service.
"""
data_path = service_name
service_data = self.get_component('data_loader').load_service_model(
data_path, type_name='service-2', api_version=api_version
data_loader: Loader = self.get_component('data_loader')
logger.debug(
"AioSession - Method load_service_model[botocore] could generate I/O. Running in executor: %s",
self.load_executor,
)
Comment on lines +114 to 117
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above

if self.load_executor:
service_data = await asyncio.get_event_loop().run_in_executor(
None,
functools.partial(
data_loader.load_service_model,
data_path,
type_name='service-2',
api_version=api_version,
),
)
else:
service_data = data_loader.load_service_model(
data_path, type_name='service-2', api_version=api_version
)
service_id = EVENT_ALIASES.get(service_name, service_name)
await self._events.emit(
f'service-data-loaded.{service_id}',
Expand Down Expand Up @@ -223,6 +246,7 @@ async def _create_client(
client_config=config,
api_version=api_version,
auth_token=auth_token,
load_executor=self.load_executor,
)
monitor = self._get_internal_component('monitor')
if monitor is not None:
Expand Down