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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +16 -1
  3. data/.rubocop_todo.yml +23 -32
  4. data/README.adoc +297 -827
  5. data/Rakefile +3 -3
  6. data/demo/rate_limiting_demo.rb +135 -0
  7. data/demo/test_embed_functionality.rb +88 -0
  8. data/demo/test_improved_embed_functionality.rb +92 -0
  9. data/examples/rate_limiting_stress_test.rb +239 -0
  10. data/exe/w3c_api +1 -1
  11. data/lib/w3c_api/cli.rb +29 -28
  12. data/lib/w3c_api/client.rb +30 -7
  13. data/lib/w3c_api/commands/affiliation.rb +15 -12
  14. data/lib/w3c_api/commands/ecosystem.rb +22 -15
  15. data/lib/w3c_api/commands/group.rb +32 -25
  16. data/lib/w3c_api/commands/output_formatter.rb +1 -1
  17. data/lib/w3c_api/commands/participation.rb +11 -9
  18. data/lib/w3c_api/commands/series.rb +11 -9
  19. data/lib/w3c_api/commands/specification.rb +59 -45
  20. data/lib/w3c_api/commands/specification_version.rb +21 -12
  21. data/lib/w3c_api/commands/translation.rb +7 -6
  22. data/lib/w3c_api/commands/user.rb +36 -24
  23. data/lib/w3c_api/embed.rb +40 -0
  24. data/lib/w3c_api/hal.rb +374 -164
  25. data/lib/w3c_api/models/account.rb +3 -3
  26. data/lib/w3c_api/models/affiliation.rb +8 -7
  27. data/lib/w3c_api/models/affiliation_index.rb +3 -2
  28. data/lib/w3c_api/models/call_for_translation.rb +4 -3
  29. data/lib/w3c_api/models/chair_index.rb +2 -2
  30. data/lib/w3c_api/models/charter.rb +5 -5
  31. data/lib/w3c_api/models/charter_index.rb +3 -2
  32. data/lib/w3c_api/models/connected_account.rb +2 -2
  33. data/lib/w3c_api/models/deliverer_index.rb +3 -2
  34. data/lib/w3c_api/models/ecosystem.rb +8 -6
  35. data/lib/w3c_api/models/ecosystem_index.rb +3 -2
  36. data/lib/w3c_api/models/editor_index.rb +2 -2
  37. data/lib/w3c_api/models/evangelist_index.rb +3 -2
  38. data/lib/w3c_api/models/group.rb +16 -13
  39. data/lib/w3c_api/models/group_index.rb +2 -2
  40. data/lib/w3c_api/models/groups.rb +2 -2
  41. data/lib/w3c_api/models/participant_index.rb +3 -2
  42. data/lib/w3c_api/models/participation.rb +6 -5
  43. data/lib/w3c_api/models/participation_index.rb +3 -2
  44. data/lib/w3c_api/models/photo.rb +1 -1
  45. data/lib/w3c_api/models/serie.rb +6 -4
  46. data/lib/w3c_api/models/serie_index.rb +3 -2
  47. data/lib/w3c_api/models/spec_version.rb +10 -7
  48. data/lib/w3c_api/models/spec_version_index.rb +3 -2
  49. data/lib/w3c_api/models/spec_version_predecessor_index.rb +3 -2
  50. data/lib/w3c_api/models/spec_version_successor_index.rb +3 -2
  51. data/lib/w3c_api/models/specification.rb +17 -9
  52. data/lib/w3c_api/models/specification_index.rb +3 -2
  53. data/lib/w3c_api/models/team_contact_index.rb +3 -2
  54. data/lib/w3c_api/models/testimonial.rb +2 -2
  55. data/lib/w3c_api/models/translation.rb +4 -4
  56. data/lib/w3c_api/models/translation_index.rb +3 -2
  57. data/lib/w3c_api/models/user.rb +16 -11
  58. data/lib/w3c_api/models/user_index.rb +2 -2
  59. data/lib/w3c_api/models.rb +52 -37
  60. data/lib/w3c_api/version.rb +1 -1
  61. data/lib/w3c_api.rb +8 -7
  62. metadata +10 -19
data/Rakefile CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'bundler/gem_tasks'
4
- require 'rspec/core/rake_task'
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
- require 'rubocop/rake_task'
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
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'w3c_api'
4
+ require "w3c_api"
5
5
 
6
6
  W3cApi::Cli.start(ARGV)
data/lib/w3c_api/cli.rb CHANGED
@@ -1,45 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
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'
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 'specification SUBCOMMAND ...ARGS', 'Work with W3C specifications'
19
- subcommand 'specification', Commands::Specification
18
+ desc "specification SUBCOMMAND ...ARGS", "Work with W3C specifications"
19
+ subcommand "specification", Commands::Specification
20
20
 
21
- desc 'specification_version SUBCOMMAND ...ARGS', 'Work with W3C specification versions'
22
- subcommand 'specification_version', Commands::SpecificationVersion
21
+ desc "specification_version SUBCOMMAND ...ARGS",
22
+ "Work with W3C specification versions"
23
+ subcommand "specification_version", Commands::SpecificationVersion
23
24
 
24
- desc 'group SUBCOMMAND ...ARGS', 'Work with W3C groups'
25
- subcommand 'group', Commands::Group
25
+ desc "group SUBCOMMAND ...ARGS", "Work with W3C groups"
26
+ subcommand "group", Commands::Group
26
27
 
27
- desc 'user SUBCOMMAND ...ARGS', 'Work with W3C users'
28
- subcommand 'user', Commands::User
28
+ desc "user SUBCOMMAND ...ARGS", "Work with W3C users"
29
+ subcommand "user", Commands::User
29
30
 
30
- desc 'translation SUBCOMMAND ...ARGS', 'Work with W3C translations'
31
- subcommand 'translation', Commands::Translation
31
+ desc "translation SUBCOMMAND ...ARGS", "Work with W3C translations"
32
+ subcommand "translation", Commands::Translation
32
33
 
33
- desc 'ecosystem SUBCOMMAND ...ARGS', 'Work with W3C ecosystems'
34
- subcommand 'ecosystem', Commands::Ecosystem
34
+ desc "ecosystem SUBCOMMAND ...ARGS", "Work with W3C ecosystems"
35
+ subcommand "ecosystem", Commands::Ecosystem
35
36
 
36
- desc 'series SUBCOMMAND ...ARGS', 'Work with W3C specification series'
37
- subcommand 'series', Commands::Series
37
+ desc "series SUBCOMMAND ...ARGS", "Work with W3C specification series"
38
+ subcommand "series", Commands::Series
38
39
 
39
- desc 'affiliation SUBCOMMAND ...ARGS', 'Work with W3C affiliations'
40
- subcommand 'affiliation', Commands::Affiliation
40
+ desc "affiliation SUBCOMMAND ...ARGS", "Work with W3C affiliations"
41
+ subcommand "affiliation", Commands::Affiliation
41
42
 
42
- desc 'participation SUBCOMMAND ...ARGS', 'Work with W3C participations'
43
- subcommand 'participation', Commands::Participation
43
+ desc "participation SUBCOMMAND ...ARGS", "Work with W3C participations"
44
+ subcommand "participation", Commands::Participation
44
45
  end
45
46
  end