w3c_api 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +16 -1
- data/.rubocop_todo.yml +23 -32
- data/README.adoc +297 -827
- data/Rakefile +3 -3
- data/demo/rate_limiting_demo.rb +135 -0
- data/demo/test_embed_functionality.rb +88 -0
- data/demo/test_improved_embed_functionality.rb +92 -0
- data/examples/rate_limiting_stress_test.rb +239 -0
- data/exe/w3c_api +1 -1
- data/lib/w3c_api/cli.rb +29 -28
- data/lib/w3c_api/client.rb +30 -7
- data/lib/w3c_api/commands/affiliation.rb +15 -12
- data/lib/w3c_api/commands/ecosystem.rb +22 -15
- data/lib/w3c_api/commands/group.rb +32 -25
- data/lib/w3c_api/commands/output_formatter.rb +1 -1
- data/lib/w3c_api/commands/participation.rb +11 -9
- data/lib/w3c_api/commands/series.rb +11 -9
- data/lib/w3c_api/commands/specification.rb +59 -45
- data/lib/w3c_api/commands/specification_version.rb +21 -12
- data/lib/w3c_api/commands/translation.rb +7 -6
- data/lib/w3c_api/commands/user.rb +36 -24
- data/lib/w3c_api/embed.rb +40 -0
- data/lib/w3c_api/hal.rb +374 -164
- data/lib/w3c_api/models/account.rb +3 -3
- data/lib/w3c_api/models/affiliation.rb +8 -7
- data/lib/w3c_api/models/affiliation_index.rb +3 -2
- data/lib/w3c_api/models/call_for_translation.rb +4 -3
- data/lib/w3c_api/models/chair_index.rb +2 -2
- data/lib/w3c_api/models/charter.rb +5 -5
- data/lib/w3c_api/models/charter_index.rb +3 -2
- data/lib/w3c_api/models/connected_account.rb +2 -2
- data/lib/w3c_api/models/deliverer_index.rb +3 -2
- data/lib/w3c_api/models/ecosystem.rb +8 -6
- data/lib/w3c_api/models/ecosystem_index.rb +3 -2
- data/lib/w3c_api/models/editor_index.rb +2 -2
- data/lib/w3c_api/models/evangelist_index.rb +3 -2
- data/lib/w3c_api/models/group.rb +16 -13
- data/lib/w3c_api/models/group_index.rb +2 -2
- data/lib/w3c_api/models/groups.rb +2 -2
- data/lib/w3c_api/models/participant_index.rb +3 -2
- data/lib/w3c_api/models/participation.rb +6 -5
- data/lib/w3c_api/models/participation_index.rb +3 -2
- data/lib/w3c_api/models/photo.rb +1 -1
- data/lib/w3c_api/models/serie.rb +6 -4
- data/lib/w3c_api/models/serie_index.rb +3 -2
- data/lib/w3c_api/models/spec_version.rb +10 -7
- data/lib/w3c_api/models/spec_version_index.rb +3 -2
- data/lib/w3c_api/models/spec_version_predecessor_index.rb +3 -2
- data/lib/w3c_api/models/spec_version_successor_index.rb +3 -2
- data/lib/w3c_api/models/specification.rb +17 -9
- data/lib/w3c_api/models/specification_index.rb +3 -2
- data/lib/w3c_api/models/team_contact_index.rb +3 -2
- data/lib/w3c_api/models/testimonial.rb +2 -2
- data/lib/w3c_api/models/translation.rb +4 -4
- data/lib/w3c_api/models/translation_index.rb +3 -2
- data/lib/w3c_api/models/user.rb +16 -11
- data/lib/w3c_api/models/user_index.rb +2 -2
- data/lib/w3c_api/models.rb +52 -37
- data/lib/w3c_api/version.rb +1 -1
- data/lib/w3c_api.rb +8 -7
- metadata +10 -19
data/Rakefile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rspec/core/rake_task"
|
5
5
|
|
6
6
|
RSpec::Core::RakeTask.new(:spec)
|
7
7
|
|
8
|
-
require
|
8
|
+
require "rubocop/rake_task"
|
9
9
|
|
10
10
|
RuboCop::RakeTask.new
|
11
11
|
|
@@ -0,0 +1,135 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "../lib/w3c_api"
|
5
|
+
|
6
|
+
# Demo script to demonstrate rate limiting functionality
|
7
|
+
puts "W3C API Rate Limiting Demo"
|
8
|
+
puts "=" * 40
|
9
|
+
|
10
|
+
puts "\nThis demo shows how to use the built-in rate limiting features"
|
11
|
+
puts "of the W3C API client to handle API rate limits gracefully."
|
12
|
+
|
13
|
+
# Create a client instance
|
14
|
+
client = W3cApi::Client.new
|
15
|
+
|
16
|
+
# Demo 1: Default rate limiting (enabled by default)
|
17
|
+
puts "\n1. Default Rate Limiting Configuration:"
|
18
|
+
puts " - Max retries: 3"
|
19
|
+
puts " - Base delay: 1.0s"
|
20
|
+
puts " - Max delay: 60.0s"
|
21
|
+
puts " - Backoff factor: 2.0"
|
22
|
+
|
23
|
+
begin
|
24
|
+
start_time = Time.now
|
25
|
+
|
26
|
+
puts "\n Making API requests with default rate limiting..."
|
27
|
+
|
28
|
+
# Fetch specifications
|
29
|
+
specs = client.specifications(items: 3)
|
30
|
+
puts " ✓ Retrieved #{specs.links.specifications.length} specifications"
|
31
|
+
|
32
|
+
# Fetch a specific specification
|
33
|
+
spec_detail = client.specification("html5")
|
34
|
+
puts " ✓ Retrieved specification: #{spec_detail.title}"
|
35
|
+
|
36
|
+
end_time = Time.now
|
37
|
+
puts " ⏱️ Total time: #{(end_time - start_time).round(2)}s"
|
38
|
+
rescue StandardError => e
|
39
|
+
puts " ✗ Error: #{e.message}"
|
40
|
+
end
|
41
|
+
|
42
|
+
# Demo 2: Custom rate limiting configuration
|
43
|
+
puts "\n2. Custom Rate Limiting Configuration:"
|
44
|
+
puts " Configuring more aggressive rate limiting for APIs with strict limits"
|
45
|
+
|
46
|
+
begin
|
47
|
+
# Configure custom rate limiting
|
48
|
+
W3cApi::Hal.instance.configure_rate_limiting(
|
49
|
+
max_retries: 5, # More retry attempts
|
50
|
+
base_delay: 0.5, # Shorter initial delay
|
51
|
+
max_delay: 30.0, # Lower maximum delay
|
52
|
+
backoff_factor: 1.5, # Gentler backoff
|
53
|
+
)
|
54
|
+
|
55
|
+
puts " ✓ Rate limiting reconfigured"
|
56
|
+
|
57
|
+
start_time = Time.now
|
58
|
+
|
59
|
+
# Make requests with custom configuration
|
60
|
+
groups = client.groups(items: 3)
|
61
|
+
puts " ✓ Retrieved #{groups.links.groups.length} groups"
|
62
|
+
|
63
|
+
end_time = Time.now
|
64
|
+
puts " ⏱️ Total time: #{(end_time - start_time).round(2)}s"
|
65
|
+
rescue StandardError => e
|
66
|
+
puts " ✗ Error: #{e.message}"
|
67
|
+
end
|
68
|
+
|
69
|
+
# Demo 3: Temporarily disable rate limiting
|
70
|
+
puts "\n3. Temporarily Disabling Rate Limiting:"
|
71
|
+
puts " Useful for bulk operations where you control the rate manually"
|
72
|
+
|
73
|
+
begin
|
74
|
+
# Disable rate limiting
|
75
|
+
W3cApi::Hal.instance.disable_rate_limiting
|
76
|
+
puts " ✓ Rate limiting disabled"
|
77
|
+
|
78
|
+
start_time = Time.now
|
79
|
+
|
80
|
+
# Make requests without rate limiting
|
81
|
+
series = client.series(items: 3)
|
82
|
+
puts " ✓ Retrieved #{series.links.series.length} series"
|
83
|
+
|
84
|
+
end_time = Time.now
|
85
|
+
puts " ⏱️ Total time: #{(end_time - start_time).round(2)}s"
|
86
|
+
rescue StandardError => e
|
87
|
+
puts " ✗ Error: #{e.message}"
|
88
|
+
end
|
89
|
+
|
90
|
+
# Demo 4: Re-enable rate limiting
|
91
|
+
puts "\n4. Re-enabling Rate Limiting:"
|
92
|
+
|
93
|
+
begin
|
94
|
+
# Re-enable rate limiting with default settings
|
95
|
+
W3cApi::Hal.instance.enable_rate_limiting
|
96
|
+
puts " ✓ Rate limiting re-enabled with default settings"
|
97
|
+
|
98
|
+
start_time = Time.now
|
99
|
+
|
100
|
+
ecosystems = client.ecosystems
|
101
|
+
puts " ✓ Retrieved #{ecosystems.links.ecosystems.length} ecosystems"
|
102
|
+
|
103
|
+
end_time = Time.now
|
104
|
+
puts " ⏱️ Total time: #{(end_time - start_time).round(2)}s"
|
105
|
+
rescue StandardError => e
|
106
|
+
puts " ✗ Error: #{e.message}"
|
107
|
+
end
|
108
|
+
|
109
|
+
# Demo 5: Check rate limiting status
|
110
|
+
puts "\n5. Checking Rate Limiting Status:"
|
111
|
+
|
112
|
+
if W3cApi::Hal.instance.rate_limiting_enabled?
|
113
|
+
puts " ✓ Rate limiting is currently ENABLED"
|
114
|
+
else
|
115
|
+
puts " ⚠️ Rate limiting is currently DISABLED"
|
116
|
+
end
|
117
|
+
|
118
|
+
puts "\n#{'=' * 40}"
|
119
|
+
puts "Rate Limiting Demo Completed! 🎉"
|
120
|
+
|
121
|
+
puts "\n📚 Key Takeaways:"
|
122
|
+
puts "• Rate limiting is enabled by default for reliable API access"
|
123
|
+
puts "• You can customize retry behavior for different API requirements"
|
124
|
+
puts "• Rate limiting can be temporarily disabled for bulk operations"
|
125
|
+
puts "• The system automatically handles 429 and 5xx errors with exponential backoff"
|
126
|
+
puts "• Retry-After headers from the server are automatically respected"
|
127
|
+
|
128
|
+
puts "\n🔧 Common Use Cases:"
|
129
|
+
puts "• Default settings work well for most applications"
|
130
|
+
puts "• Increase max_retries for critical operations"
|
131
|
+
puts "• Decrease delays for APIs with generous rate limits"
|
132
|
+
puts "• Disable temporarily for bulk data processing"
|
133
|
+
|
134
|
+
puts "\n📖 For more information, see the rate limiting documentation"
|
135
|
+
puts " in the lutaml-hal library or the W3C API documentation."
|
@@ -0,0 +1,88 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require_relative "lib/w3c_api"
|
6
|
+
|
7
|
+
def test_link_realization(groups_with_embed)
|
8
|
+
return unless groups_with_embed.respond_to?(:links) && groups_with_embed.links.respond_to?(:groups)
|
9
|
+
|
10
|
+
first_group_link = groups_with_embed.links.groups.first
|
11
|
+
return unless first_group_link
|
12
|
+
|
13
|
+
puts " First group link: #{first_group_link.href}"
|
14
|
+
return unless first_group_link.respond_to?(:realize)
|
15
|
+
|
16
|
+
begin
|
17
|
+
realized_group = first_group_link.realize(parent_resource: groups_with_embed)
|
18
|
+
puts " ✓ Link realization with embedded data successful"
|
19
|
+
puts " Realized group name: #{realized_group.name if realized_group.respond_to?(:name)}"
|
20
|
+
rescue StandardError => e
|
21
|
+
puts " ⚠ Link realization failed: #{e.message}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
puts "Testing W3C API Embed Functionality"
|
26
|
+
puts "=" * 40
|
27
|
+
|
28
|
+
# Initialize the client
|
29
|
+
client = W3cApi::Client.new
|
30
|
+
|
31
|
+
begin
|
32
|
+
puts "\n1. Testing Groups endpoint with embed..."
|
33
|
+
groups_with_embed = client.groups(embed: true, items: 5)
|
34
|
+
|
35
|
+
puts " Response type: #{groups_with_embed.class}"
|
36
|
+
puts " Has embedded content: #{groups_with_embed.respond_to?(:has_embedded?) && groups_with_embed.has_embedded?('groups')}"
|
37
|
+
|
38
|
+
if groups_with_embed.respond_to?(:has_embedded?) && groups_with_embed.has_embedded?("groups")
|
39
|
+
puts " Available methods: #{groups_with_embed.methods.grep(/embed/).join(', ')}"
|
40
|
+
|
41
|
+
embedded_groups = groups_with_embed.get_embedded("groups")
|
42
|
+
puts " Number of embedded groups: #{embedded_groups.length}"
|
43
|
+
puts " First embedded group: #{embedded_groups.first['name'] if embedded_groups.first}"
|
44
|
+
end
|
45
|
+
|
46
|
+
puts "\n2. Testing Specifications endpoint with embed..."
|
47
|
+
specs_with_embed = client.specifications(embed: true, items: 5)
|
48
|
+
|
49
|
+
puts " Response type: #{specs_with_embed.class}"
|
50
|
+
puts " Has embedded content: #{specs_with_embed.respond_to?(:has_embedded?) && specs_with_embed.has_embedded?('specifications')}"
|
51
|
+
|
52
|
+
if specs_with_embed.respond_to?(:has_embedded?) && specs_with_embed.has_embedded?("specifications")
|
53
|
+
puts " Available methods: #{specs_with_embed.methods.grep(/embed/).join(', ')}"
|
54
|
+
|
55
|
+
embedded_specs = specs_with_embed.get_embedded("specifications")
|
56
|
+
puts " Number of embedded specifications: #{embedded_specs.length}"
|
57
|
+
puts " First embedded spec: #{embedded_specs.first['title'] if embedded_specs.first}"
|
58
|
+
end
|
59
|
+
|
60
|
+
puts "\n3. Testing comparison: with vs without embed..."
|
61
|
+
|
62
|
+
# Without embed
|
63
|
+
start_time = Time.now
|
64
|
+
client.groups(items: 3)
|
65
|
+
without_embed_time = Time.now - start_time
|
66
|
+
puts " Without embed: #{without_embed_time.round(3)}s"
|
67
|
+
|
68
|
+
# With embed
|
69
|
+
start_time = Time.now
|
70
|
+
groups_with_embed = client.groups(embed: true, items: 3)
|
71
|
+
with_embed_time = Time.now - start_time
|
72
|
+
puts " With embed: #{with_embed_time.round(3)}s"
|
73
|
+
|
74
|
+
if groups_with_embed.respond_to?(:has_embedded?) && groups_with_embed.has_embedded?("groups")
|
75
|
+
puts " ✓ Embed functionality working correctly!"
|
76
|
+
else
|
77
|
+
puts " ⚠ Embed parameter accepted but no embedded content returned"
|
78
|
+
end
|
79
|
+
|
80
|
+
puts "\n4. Testing link realization with embedded content..."
|
81
|
+
test_link_realization(groups_with_embed)
|
82
|
+
|
83
|
+
puts "\n✅ Embed functionality test completed successfully!"
|
84
|
+
rescue StandardError => e
|
85
|
+
puts "\n❌ Error during testing: #{e.message}"
|
86
|
+
puts "Backtrace:"
|
87
|
+
puts e.backtrace.first(5).join("\n")
|
88
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "stringio"
|
5
|
+
require_relative "../lib/w3c_api"
|
6
|
+
|
7
|
+
puts "=== W3C API Improved Embed Functionality Demo ==="
|
8
|
+
puts
|
9
|
+
|
10
|
+
# Test 1: List embed-supported endpoints
|
11
|
+
puts "1. Testing embed-supported endpoints discovery:"
|
12
|
+
supported_endpoints = W3cApi::Client.embed_supported_endpoints
|
13
|
+
puts " Embed-supported endpoints: #{supported_endpoints.join(', ')}"
|
14
|
+
puts
|
15
|
+
|
16
|
+
# Test 2: Check specific endpoint support
|
17
|
+
puts "2. Testing specific endpoint embed support:"
|
18
|
+
client = W3cApi::Client.new
|
19
|
+
puts " specifications supports embed: #{client.embed_supported?(:specification_index)}"
|
20
|
+
puts " groups supports embed: #{client.embed_supported?(:group_index)}"
|
21
|
+
puts " series supports embed: #{client.embed_supported?(:serie_index)}"
|
22
|
+
puts " specification_resource supports embed: #{client.embed_supported?(:specification_resource)}"
|
23
|
+
puts
|
24
|
+
|
25
|
+
# Test 3: Get embed information
|
26
|
+
puts "3. Testing embed information:"
|
27
|
+
embed_info = W3cApi::Embed.embed_info
|
28
|
+
puts " Supported endpoints: #{embed_info[:supported_endpoints].join(', ')}"
|
29
|
+
puts " Discovery: #{embed_info[:usage_example][:discovery]}"
|
30
|
+
puts " Usage: #{embed_info[:usage_example][:usage]}"
|
31
|
+
puts " Automatic realization: #{embed_info[:usage_example][:automatic_realization]}"
|
32
|
+
puts
|
33
|
+
|
34
|
+
# Test 4: Use Client methods with embed
|
35
|
+
puts "4. Testing Client methods with embed parameter:"
|
36
|
+
begin
|
37
|
+
puts " Fetching specifications with embed=true..."
|
38
|
+
specs = client.specifications(embed: true, items: 2)
|
39
|
+
puts " ✓ Successfully fetched #{specs.class}"
|
40
|
+
|
41
|
+
if specs.respond_to?(:embedded_data) && specs.embedded_data
|
42
|
+
puts " ✓ Has embedded data: #{specs.embedded_data.keys.join(', ')}"
|
43
|
+
else
|
44
|
+
puts " ⚠ No embedded data found"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Test automatic embedded content detection
|
48
|
+
if specs.links.respond_to?(:specifications) && specs.links.specifications.any?
|
49
|
+
puts " Testing automatic embedded content detection..."
|
50
|
+
first_spec_link = specs.links.specifications.first
|
51
|
+
|
52
|
+
begin
|
53
|
+
# This should automatically use embedded content without parent_resource parameter
|
54
|
+
spec = first_spec_link.realize
|
55
|
+
puts " ✓ Successfully realized specification automatically"
|
56
|
+
puts " ✓ Specification class: #{spec.class}"
|
57
|
+
puts " ✓ Specification title: #{spec.title}" if spec.respond_to?(:title)
|
58
|
+
rescue StandardError => e
|
59
|
+
puts " ✗ Error realizing specification: #{e.message}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
rescue StandardError => e
|
63
|
+
puts " ✗ Error: #{e.message}"
|
64
|
+
end
|
65
|
+
puts
|
66
|
+
|
67
|
+
# Test 5: Test Embed module information methods
|
68
|
+
puts "5. Testing Embed module information methods:"
|
69
|
+
begin
|
70
|
+
puts " Testing supported_endpoints method..."
|
71
|
+
supported = W3cApi::Embed.supported_endpoints
|
72
|
+
puts " ✓ Supported endpoints: #{supported.join(', ')}"
|
73
|
+
|
74
|
+
puts " Testing supports_embed? method..."
|
75
|
+
puts " ✓ specifications supports embed: #{W3cApi::Embed.supports_embed?(:specification_index)}"
|
76
|
+
puts " ✓ groups supports embed: #{W3cApi::Embed.supports_embed?(:group_index)}"
|
77
|
+
|
78
|
+
puts " Testing endpoint_descriptions method..."
|
79
|
+
descriptions = W3cApi::Embed.endpoint_descriptions
|
80
|
+
puts " ✓ Available descriptions: #{descriptions.keys.join(', ')}"
|
81
|
+
rescue StandardError => e
|
82
|
+
puts " ✗ Error: #{e.message}"
|
83
|
+
end
|
84
|
+
puts
|
85
|
+
|
86
|
+
puts "=== Demo completed ==="
|
87
|
+
puts "Summary of improvements:"
|
88
|
+
puts "• ✓ Added embed-supported endpoints discovery methods"
|
89
|
+
puts "• ✓ Client methods now support embed parameter directly"
|
90
|
+
puts "• ✓ Automatic embedded content detection (no parent_resource needed)"
|
91
|
+
puts "• ✓ Enhanced Embed module with information methods"
|
92
|
+
puts "• ✓ Removed deprecated code for cleaner API"
|
@@ -0,0 +1,239 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "../lib/w3c_api"
|
5
|
+
|
6
|
+
# Advanced example: Rate limiting stress test and performance analysis
|
7
|
+
puts "W3C API Rate Limiting - Advanced Stress Test Example"
|
8
|
+
puts "=" * 55
|
9
|
+
|
10
|
+
puts "\nThis example demonstrates advanced rate limiting scenarios:"
|
11
|
+
puts "• Rapid sequential requests"
|
12
|
+
puts "• Performance analysis across different endpoints"
|
13
|
+
puts "• Dynamic configuration changes"
|
14
|
+
puts "• Load testing patterns"
|
15
|
+
|
16
|
+
# Create a client instance
|
17
|
+
client = W3cApi::Client.new
|
18
|
+
|
19
|
+
# Configure aggressive rate limiting for testing
|
20
|
+
W3cApi::Hal.instance.configure_rate_limiting(
|
21
|
+
max_retries: 3,
|
22
|
+
base_delay: 0.1, # Very short delay for testing
|
23
|
+
max_delay: 5.0, # Lower max delay
|
24
|
+
backoff_factor: 2.0,
|
25
|
+
)
|
26
|
+
|
27
|
+
puts "\n🔧 Rate limiting configuration for stress testing:"
|
28
|
+
puts " - Max retries: 3"
|
29
|
+
puts " - Base delay: 0.1s (very aggressive)"
|
30
|
+
puts " - Max delay: 5.0s"
|
31
|
+
puts " - Backoff factor: 2.0"
|
32
|
+
|
33
|
+
# Test 1: Rapid sequential requests
|
34
|
+
puts "\n1. 🚀 Rapid Sequential Requests Test:"
|
35
|
+
puts " Making 10 rapid requests to analyze rate limiting behavior..."
|
36
|
+
|
37
|
+
start_time = Time.now
|
38
|
+
successful_requests = 0
|
39
|
+
failed_requests = 0
|
40
|
+
request_times = []
|
41
|
+
|
42
|
+
10.times do |i|
|
43
|
+
print " Request #{i + 1}: "
|
44
|
+
request_start = Time.now
|
45
|
+
|
46
|
+
begin
|
47
|
+
specs = client.specifications(items: 1)
|
48
|
+
request_time = (Time.now - request_start).round(3)
|
49
|
+
request_times << request_time
|
50
|
+
puts "✓ Success (#{specs.links.specifications.length} items, #{request_time}s)"
|
51
|
+
successful_requests += 1
|
52
|
+
rescue StandardError => e
|
53
|
+
request_time = (Time.now - request_start).round(3)
|
54
|
+
request_times << request_time
|
55
|
+
puts "✗ Failed: #{e.message} (#{request_time}s)"
|
56
|
+
failed_requests += 1
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end_time = Time.now
|
61
|
+
total_time = (end_time - start_time).round(2)
|
62
|
+
|
63
|
+
puts "\n 📊 Performance Analysis:"
|
64
|
+
puts " - Successful requests: #{successful_requests}"
|
65
|
+
puts " - Failed requests: #{failed_requests}"
|
66
|
+
puts " - Total time: #{total_time}s"
|
67
|
+
puts " - Average time per request: #{(total_time / 10).round(3)}s"
|
68
|
+
puts " - Fastest request: #{request_times.min}s"
|
69
|
+
puts " - Slowest request: #{request_times.max}s"
|
70
|
+
|
71
|
+
# Test 2: Cross-endpoint performance analysis
|
72
|
+
puts "\n2. 🎯 Cross-Endpoint Performance Analysis:"
|
73
|
+
endpoints = [
|
74
|
+
{ name: "specifications", method: :specifications,
|
75
|
+
link_key: :specifications },
|
76
|
+
{ name: "groups", method: :groups, link_key: :groups },
|
77
|
+
{ name: "series", method: :series, link_key: :series },
|
78
|
+
{ name: "ecosystems", method: :ecosystems, link_key: :ecosystems },
|
79
|
+
]
|
80
|
+
|
81
|
+
endpoint_results = {}
|
82
|
+
|
83
|
+
endpoints.each do |endpoint|
|
84
|
+
print " Testing #{endpoint[:name].ljust(15)}: "
|
85
|
+
start = Time.now
|
86
|
+
|
87
|
+
begin
|
88
|
+
result = client.send(endpoint[:method], items: 2)
|
89
|
+
duration = (Time.now - start).round(3)
|
90
|
+
count = result.links.send(endpoint[:link_key]).length
|
91
|
+
|
92
|
+
endpoint_results[endpoint[:name]] = {
|
93
|
+
success: true,
|
94
|
+
duration: duration,
|
95
|
+
count: count,
|
96
|
+
}
|
97
|
+
|
98
|
+
puts "✓ Success (#{count} items, #{duration}s)"
|
99
|
+
rescue StandardError => e
|
100
|
+
duration = (Time.now - start).round(3)
|
101
|
+
endpoint_results[endpoint[:name]] = {
|
102
|
+
success: false,
|
103
|
+
duration: duration,
|
104
|
+
error: e.message,
|
105
|
+
}
|
106
|
+
puts "✗ Failed: #{e.message} (#{duration}s)"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
puts "\n 📈 Endpoint Performance Summary:"
|
111
|
+
endpoint_results.each do |name, result|
|
112
|
+
if result[:success]
|
113
|
+
puts " - #{name.ljust(15)}: #{result[:duration]}s (#{result[:count]} items)"
|
114
|
+
else
|
115
|
+
puts " - #{name.ljust(15)}: #{result[:duration]}s (FAILED)"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Test 3: Dynamic configuration testing
|
120
|
+
puts "\n3. ⚙️ Dynamic Configuration Testing:"
|
121
|
+
|
122
|
+
begin
|
123
|
+
puts " Testing with rate limiting enabled..."
|
124
|
+
start = Time.now
|
125
|
+
client.specifications(items: 1)
|
126
|
+
time1 = (Time.now - start).round(3)
|
127
|
+
puts " ✓ Request 1 (enabled): #{time1}s"
|
128
|
+
|
129
|
+
puts " 🔄 Disabling rate limiting..."
|
130
|
+
W3cApi::Hal.instance.disable_rate_limiting
|
131
|
+
|
132
|
+
start = Time.now
|
133
|
+
client.specifications(items: 1)
|
134
|
+
time2 = (Time.now - start).round(3)
|
135
|
+
puts " ✓ Request 2 (disabled): #{time2}s"
|
136
|
+
|
137
|
+
puts " 🔄 Re-enabling with different configuration..."
|
138
|
+
W3cApi::Hal.instance.enable_rate_limiting
|
139
|
+
W3cApi::Hal.instance.configure_rate_limiting(
|
140
|
+
max_retries: 5,
|
141
|
+
base_delay: 0.2,
|
142
|
+
max_delay: 10.0,
|
143
|
+
backoff_factor: 1.5,
|
144
|
+
)
|
145
|
+
|
146
|
+
start = Time.now
|
147
|
+
client.specifications(items: 1)
|
148
|
+
time3 = (Time.now - start).round(3)
|
149
|
+
puts " ✓ Request 3 (reconfigured): #{time3}s"
|
150
|
+
|
151
|
+
puts "\n ⏱️ Timing Comparison:"
|
152
|
+
puts " - Enabled (default): #{time1}s"
|
153
|
+
puts " - Disabled: #{time2}s"
|
154
|
+
puts " - Reconfigured: #{time3}s"
|
155
|
+
rescue StandardError => e
|
156
|
+
puts " ✗ Error: #{e.message}"
|
157
|
+
end
|
158
|
+
|
159
|
+
# Test 4: Bulk operation simulation
|
160
|
+
puts "\n4. 📦 Bulk Operation Simulation:"
|
161
|
+
puts " Simulating a bulk data collection scenario..."
|
162
|
+
|
163
|
+
bulk_start = Time.now
|
164
|
+
bulk_results = []
|
165
|
+
|
166
|
+
# Simulate collecting data from multiple endpoints
|
167
|
+
bulk_operations = [
|
168
|
+
{ name: "Collect specifications", method: :specifications, items: 3 },
|
169
|
+
{ name: "Collect groups", method: :groups, items: 2 },
|
170
|
+
{ name: "Collect series", method: :series, items: 2 },
|
171
|
+
]
|
172
|
+
|
173
|
+
bulk_operations.each_with_index do |operation, _index|
|
174
|
+
print " #{operation[:name]}: "
|
175
|
+
op_start = Time.now
|
176
|
+
|
177
|
+
begin
|
178
|
+
result = client.send(operation[:method], items: operation[:items])
|
179
|
+
duration = (Time.now - op_start).round(3)
|
180
|
+
|
181
|
+
case operation[:method]
|
182
|
+
when :specifications
|
183
|
+
count = result.links.specifications.length
|
184
|
+
when :groups
|
185
|
+
count = result.links.groups.length
|
186
|
+
when :series
|
187
|
+
count = result.links.series.length
|
188
|
+
end
|
189
|
+
|
190
|
+
bulk_results << { success: true, duration: duration, count: count }
|
191
|
+
puts "✓ #{count} items (#{duration}s)"
|
192
|
+
|
193
|
+
# Add a small delay between bulk operations
|
194
|
+
sleep(0.1)
|
195
|
+
rescue StandardError => e
|
196
|
+
duration = (Time.now - op_start).round(3)
|
197
|
+
bulk_results << { success: false, duration: duration }
|
198
|
+
puts "✗ Failed: #{e.message} (#{duration}s)"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
bulk_total_time = (Time.now - bulk_start).round(2)
|
203
|
+
successful_ops = bulk_results.count { |r| r[:success] }
|
204
|
+
total_items = bulk_results.select { |r| r[:success] }.sum { |r| r[:count] || 0 }
|
205
|
+
|
206
|
+
puts "\n 📊 Bulk Operation Results:"
|
207
|
+
puts " - Total time: #{bulk_total_time}s"
|
208
|
+
puts " - Successful operations: #{successful_ops}/#{bulk_operations.length}"
|
209
|
+
puts " - Total items collected: #{total_items}"
|
210
|
+
puts " - Average time per operation: #{(bulk_total_time / bulk_operations.length).round(3)}s"
|
211
|
+
|
212
|
+
puts "\n#{'=' * 55}"
|
213
|
+
puts "🎉 Advanced Stress Test Completed!"
|
214
|
+
|
215
|
+
puts "\n📋 Test Summary:"
|
216
|
+
puts "• Sequential requests: #{successful_requests}/10 successful"
|
217
|
+
puts "• Endpoint tests: #{endpoint_results.count do |_, r|
|
218
|
+
r[:success]
|
219
|
+
end}/#{endpoints.length} successful"
|
220
|
+
puts "• Configuration changes: Applied successfully"
|
221
|
+
puts "• Bulk operations: #{successful_ops}/#{bulk_operations.length} successful"
|
222
|
+
|
223
|
+
puts "\n💡 Key Insights:"
|
224
|
+
puts "• Rate limiting maintains API stability under load"
|
225
|
+
puts "• Configuration changes take effect immediately"
|
226
|
+
puts "• Different endpoints may have varying response times"
|
227
|
+
puts "• Bulk operations benefit from rate limiting protection"
|
228
|
+
|
229
|
+
puts "\n🔍 In Production Scenarios:"
|
230
|
+
puts "• Rate limiting prevents API abuse and ensures fair usage"
|
231
|
+
puts "• Exponential backoff reduces server load during high traffic"
|
232
|
+
puts "• Retry-After headers are automatically respected"
|
233
|
+
puts "• 429 and 5xx errors are handled gracefully with retries"
|
234
|
+
|
235
|
+
puts "\n📚 Advanced Usage Tips:"
|
236
|
+
puts "• Monitor request patterns to optimize rate limiting settings"
|
237
|
+
puts "• Use bulk operations with manual delays for large datasets"
|
238
|
+
puts "• Adjust configuration based on API documentation"
|
239
|
+
puts "• Consider disabling rate limiting for controlled bulk operations"
|
data/exe/w3c_api
CHANGED
data/lib/w3c_api/cli.rb
CHANGED
@@ -1,45 +1,46 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
8
|
-
require_relative
|
9
|
-
require_relative
|
10
|
-
require_relative
|
11
|
-
require_relative
|
12
|
-
require_relative
|
3
|
+
require "thor"
|
4
|
+
require_relative "commands/specification"
|
5
|
+
require_relative "commands/specification_version"
|
6
|
+
require_relative "commands/group"
|
7
|
+
require_relative "commands/user"
|
8
|
+
require_relative "commands/translation"
|
9
|
+
require_relative "commands/ecosystem"
|
10
|
+
require_relative "commands/series"
|
11
|
+
require_relative "commands/affiliation"
|
12
|
+
require_relative "commands/participation"
|
13
13
|
|
14
14
|
module W3cApi
|
15
15
|
# Main CLI class that registers all subcommands
|
16
16
|
class Cli < Thor
|
17
17
|
# Register subcommands
|
18
|
-
desc
|
19
|
-
subcommand
|
18
|
+
desc "specification SUBCOMMAND ...ARGS", "Work with W3C specifications"
|
19
|
+
subcommand "specification", Commands::Specification
|
20
20
|
|
21
|
-
desc
|
22
|
-
|
21
|
+
desc "specification_version SUBCOMMAND ...ARGS",
|
22
|
+
"Work with W3C specification versions"
|
23
|
+
subcommand "specification_version", Commands::SpecificationVersion
|
23
24
|
|
24
|
-
desc
|
25
|
-
subcommand
|
25
|
+
desc "group SUBCOMMAND ...ARGS", "Work with W3C groups"
|
26
|
+
subcommand "group", Commands::Group
|
26
27
|
|
27
|
-
desc
|
28
|
-
subcommand
|
28
|
+
desc "user SUBCOMMAND ...ARGS", "Work with W3C users"
|
29
|
+
subcommand "user", Commands::User
|
29
30
|
|
30
|
-
desc
|
31
|
-
subcommand
|
31
|
+
desc "translation SUBCOMMAND ...ARGS", "Work with W3C translations"
|
32
|
+
subcommand "translation", Commands::Translation
|
32
33
|
|
33
|
-
desc
|
34
|
-
subcommand
|
34
|
+
desc "ecosystem SUBCOMMAND ...ARGS", "Work with W3C ecosystems"
|
35
|
+
subcommand "ecosystem", Commands::Ecosystem
|
35
36
|
|
36
|
-
desc
|
37
|
-
subcommand
|
37
|
+
desc "series SUBCOMMAND ...ARGS", "Work with W3C specification series"
|
38
|
+
subcommand "series", Commands::Series
|
38
39
|
|
39
|
-
desc
|
40
|
-
subcommand
|
40
|
+
desc "affiliation SUBCOMMAND ...ARGS", "Work with W3C affiliations"
|
41
|
+
subcommand "affiliation", Commands::Affiliation
|
41
42
|
|
42
|
-
desc
|
43
|
-
subcommand
|
43
|
+
desc "participation SUBCOMMAND ...ARGS", "Work with W3C participations"
|
44
|
+
subcommand "participation", Commands::Participation
|
44
45
|
end
|
45
46
|
end
|