Skip to content

Commit

Permalink
Introduces autoloading strategy for service gems (#3105)
Browse files Browse the repository at this point in the history
  • Loading branch information
Schwad authored Sep 23, 2024
1 parent b27b3bc commit 94d4416
Show file tree
Hide file tree
Showing 41 changed files with 432 additions and 209 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,16 @@ jobs:

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
continue-on-error: true
with:
role-to-assume: arn:aws:iam::373952703873:role/BenchmarkReporter
role-session-name: benchmark-reporter
aws-region: us-east-1

- name: Upload benchmark report
if: ${{ env.AWS_ACCESS_KEY_ID != '' }}
run: bundle exec rake benchmark:upload-report

- name: Put benchmark metrics
if: ${{ env.AWS_ACCESS_KEY_ID != '' }}
run: bundle exec rake benchmark:put-metrics
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,18 @@ def wrap_string(str, width, indent = '')
str.gsub(/(.{1,#{width}})(\s+|\Z)/, "#{indent}\\1\n").chomp
end

def gem_lib_path(gem_name)
File.expand_path(
File.join(
__dir__,
"../../../../gems/#{gem_name}/lib/"
)
)
end

module_function :deep_copy, :operation_streaming?, :downcase_first, :wrap_string, :apig_prefix,
:eventstream_output?, :eventstream_input?, :operation_eventstreaming?, :pascal_case
:eventstream_output?, :eventstream_input?, :operation_eventstreaming?, :pascal_case,
:gem_lib_path

end
end
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,31 @@ def generated_src_warning
GENERATED_SRC_WARNING
end

# @return [String]
def module_name
@service.module_name
end

# @return [Boolean]
def customization_file_exists?
File.exist?(
File.join(
Helper.gem_lib_path(gem_name), "#{customization_file_path}.rb"
)
)
end

# @return [String]
def customization_file_path
"#{gem_name}/customizations/errors"
end

private

# @return [String]
def gem_name
"aws-sdk-#{module_name.split('::').last.downcase}"
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,30 @@ def identifiers?
@identifiers.size > 0
end

# @return [Boolean]
def customization_file_exists?
File.exist?(
File.join(
Helper.gem_lib_path(gem_name), "#{resource_customization}.rb"
)
)
end

# @return [String]
def resource_customization
"#{gem_name}/customizations/#{underscored_name}"
end

private

def gem_name
"aws-sdk-#{module_name.split('::').last.downcase}"
end

def underscored_name
class_name.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
end

def build_associations(options)
ResourceAssociation.build_list(
class_name: options.fetch(:class_name),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,25 @@ def documentation?
actions? || associations?
end

# @return [Boolean]
def customization_file_exists?
File.exist?(
File.join(
Helper.gem_lib_path(gem_name), "#{customization_file_path}.rb"
)
)
end

# @return [String]
def customization_file_path
"#{gem_name}/customizations/resource"
end

private

def gem_name
"aws-sdk-#{module_name.split('::').last.downcase}"
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class ServiceModule < View
def initialize(options)
@service = options.fetch(:service)
@prefix = options.fetch(:prefix)
@codegenerated_plugins = options.fetch(:codegenerated_plugins)
@codegenerated_plugins = options.fetch(:codegenerated_plugins) || []
end

# @return [String|nil]
Expand Down Expand Up @@ -60,55 +60,65 @@ def require_core_guard?
@service.included_in_core?
end

# @return [Array<String>]
def relative_requires
paths = Set.new
paths << "#{@prefix}/types"
paths << "#{@prefix}/client_api"
# @return [Array<Hash>] list of autoload path hashes with :path, :class_name and
# :is_plugin keys.
def autoloads
paths = []
paths << auto_load("#{@prefix}/types", :Types)
paths << auto_load("#{@prefix}/client_api", :ClientApi)

# these must be required before the client
if @codegenerated_plugins
paths += @codegenerated_plugins.map { | p| p.path }
paths += @codegenerated_plugins.map do |p|
auto_load(p.path, p.class_name.split('::').last, true)
end

paths << "#{@prefix}/client"
paths << "#{@prefix}/errors"
paths << "#{@prefix}/waiters" if @service.waiters
paths << "#{@prefix}/resource"
paths << auto_load("#{@prefix}/client", :Client)
paths << auto_load("#{@prefix}/errors", :Errors)
paths << auto_load("#{@prefix}/waiters", :Waiters) if @service.waiters
paths << auto_load("#{@prefix}/resource", :Resource)

unless @service.legacy_endpoints?
paths << "#{@prefix}/endpoint_parameters"
paths << "#{@prefix}/endpoint_provider"
paths << "#{@prefix}/endpoints"
paths << auto_load("#{@prefix}/endpoint_parameters", :EndpointParameters)
paths << auto_load("#{@prefix}/endpoint_provider", :EndpointProvider)
paths << auto_load("#{@prefix}/endpoints", :Endpoints)
end

if @service.resources && @service.resources['resources']
@service.resources['resources'].keys.each do |resource_name|
path = "#{@prefix}/#{underscore(resource_name)}"
if paths.include?(path)
raise "resource path conflict for `#{resource_name}'"
else
paths << path
end
paths << auto_load(path, resource_name)
end
end
paths << "#{@prefix}/customizations"
if @service.api['metadata']['protocolSettings'] &&
@service.api['metadata']['protocolSettings']['h2'] == 'eventstream'
paths << "#{@prefix}/async_client"
paths << "#{@prefix}/event_streams"
@service.api['metadata']['protocolSettings']['h2'] == 'eventstream'
paths << auto_load("#{@prefix}/async_client", :AsyncClient)
paths << auto_load("#{@prefix}/event_streams", :EventStreams)
elsif eventstream_shape?
paths << "#{@prefix}/event_streams"
paths << auto_load("#{@prefix}/event_streams", :EventStreams)
end
paths.to_a

paths
end

def auto_load(path, class_name, is_plugin = false)
{
file_path: path,
class_name: class_name,
is_plugin: is_plugin
}
end

def service_identifier
@prefix
end

def example_var_name
underscore(name)
end

def example_operation_name
raise "no operations found for the service" if @service.api['operations'].empty?
raise 'no operations found for the service' if @service.api['operations'].empty?

underscore(@service.api['operations'].keys.first)
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,20 @@ def eventstreams
end
end

# @return [Array<String>]
def types_customizations
Dir.glob(File.join(Helper.gem_lib_path(gem_name), "#{gem_name}/customizations/types", '*.rb')).map do |file|
filename = File.basename(file, '.rb')
"#{gem_name}/customizations/types/#{filename}"
end
end

private

def gem_name
"aws-sdk-#{module_name.split('::').last.downcase}"
end

def struct_members(shape)
return if shape['members'].nil?
members = shape['members'].map do |member_name, member_ref|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
{{#generated_src_warning}}
{{generated_src_warning}}
{{/generated_src_warning}}

module {{module_name}}
# @api private
module ClientApi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,8 @@ module {{module_name}}
{{/errors}}
end
end
{{#customization_file_exists?}}

# Load customizations if they exist
require '{{customization_file_path}}'
{{/customization_file_exists?}}
Original file line number Diff line number Diff line change
Expand Up @@ -304,3 +304,8 @@ module {{module_name}}
{{/batch_actions?}}
end
end
{{#customization_file_exists?}}

# Load customizations if they exist
require '{{resource_customization}}'
{{/customization_file_exists?}}
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,8 @@ module {{module_name}}

end
end
{{#customization_file_exists?}}

# Load customizations if they exist
require '{{customization_file_path}}'
{{/customization_file_exists?}}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ require '{{.}}'
{{/requires}}
{{/require_core_guard?}}

{{#relative_requires}}
require_relative '{{.}}'
{{/relative_requires}}

# This module provides support for {{full_name}}. This module is available in the
# `{{gem_name}}` gem.
#
Expand Down Expand Up @@ -52,7 +48,19 @@ require_relative '{{.}}'
#
# @!group service
module {{module_name}}
{{#autoloads}}
{{#is_plugin}}
module Plugins
autoload :{{class_name}}, '{{file_path}}'
end
{{/is_plugin}}
{{^is_plugin}}
autoload :{{class_name}}, '{{file_path}}'
{{/is_plugin}}
{{/autoloads}}

GEM_VERSION = '{{gem_version}}'

end

require_relative '{{service_identifier}}/customizations'
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ module {{module_name}}

end
end

{{#types_customizations}}
require "{{.}}"
{{/types_customizations}}
10 changes: 7 additions & 3 deletions gems/aws-sdk-cloudfront/lib/aws-sdk-cloudfront/customizations.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# frozen_string_literal: true

# utility classes
require 'aws-sdk-cloudfront/signer'
require 'aws-sdk-cloudfront/url_signer'
require 'aws-sdk-cloudfront/cookie_signer'
module Aws
module CloudFront
autoload :Signer, 'aws-sdk-cloudfront/signer'
autoload :UrlSigner, 'aws-sdk-cloudfront/url_signer'
autoload :CookieSigner, 'aws-sdk-cloudfront/cookie_signer'
end
end
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# frozen_string_literal: true

require 'aws-sdk-cognitoidentity/customizations/cognito_identity_credentials'
module Aws
module CognitoIdentity
autoload :CognitoIdentityCredentials, 'aws-sdk-cognitoidentity/customizations/cognito_identity_credentials'
end
end
2 changes: 2 additions & 0 deletions gems/aws-sdk-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Unreleased Changes
------------------

* Feature - Use autoloading at the service level to load service clients and resources.

3.207.0 (2024-09-20)
------------------

Expand Down
5 changes: 4 additions & 1 deletion gems/aws-sdk-core/lib/aws-defaults.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# frozen_string_literal: true

require_relative 'aws-defaults/default_configuration'
module Aws
autoload :DefaultsModeConfiguration, 'aws-defaults/default_configuration'
autoload :DefaultsModeConfigResolver, 'aws-defaults/defaults_mode_config_resolver'
end
Loading

0 comments on commit 94d4416

Please sign in to comment.