lepus 0.0.1.beta2 → 0.1.0

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 (125) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linter.yml +21 -0
  3. data/.github/workflows/specs.yml +93 -13
  4. data/.gitignore +2 -0
  5. data/.rubocop.yml +10 -0
  6. data/.tool-versions +1 -1
  7. data/Gemfile +7 -0
  8. data/Gemfile.lock +36 -9
  9. data/Makefile +19 -0
  10. data/README.md +562 -7
  11. data/bin/setup +5 -2
  12. data/config.ru +14 -0
  13. data/docker-compose.yml +5 -3
  14. data/docs/README.md +80 -0
  15. data/docs/cli.md +108 -0
  16. data/docs/configuration.md +171 -0
  17. data/docs/consumers.md +168 -0
  18. data/docs/getting-started.md +136 -0
  19. data/docs/images/lepus-web.png +0 -0
  20. data/docs/middleware.md +240 -0
  21. data/docs/producers.md +173 -0
  22. data/docs/prometheus.md +112 -0
  23. data/docs/rails.md +161 -0
  24. data/docs/supervisor.md +112 -0
  25. data/docs/testing.md +141 -0
  26. data/docs/web.md +85 -0
  27. data/examples/grafana-dashboard.json +450 -0
  28. data/gemfiles/Gemfile.rails-5.2 +7 -0
  29. data/gemfiles/{rails52.gemfile.lock → Gemfile.rails-5.2.lock} +102 -69
  30. data/gemfiles/Gemfile.rails-6.1 +7 -0
  31. data/gemfiles/{rails61.gemfile.lock → Gemfile.rails-6.1.lock} +113 -79
  32. data/gemfiles/{rails52.gemfile → Gemfile.rails-7.2} +1 -1
  33. data/gemfiles/Gemfile.rails-7.2.lock +321 -0
  34. data/gemfiles/{rails61.gemfile → Gemfile.rails-8.0} +1 -1
  35. data/gemfiles/Gemfile.rails-8.0.lock +322 -0
  36. data/lepus.gemspec +7 -1
  37. data/lib/lepus/cli.rb +35 -4
  38. data/lib/lepus/configuration.rb +107 -0
  39. data/lib/lepus/connection_pool.rb +135 -0
  40. data/lib/lepus/consumer.rb +59 -41
  41. data/lib/lepus/consumers/config.rb +183 -0
  42. data/lib/lepus/consumers/handler.rb +56 -0
  43. data/lib/lepus/consumers/middleware_chain.rb +22 -0
  44. data/lib/lepus/consumers/middlewares/exception_logger.rb +27 -0
  45. data/lib/lepus/consumers/middlewares/honeybadger.rb +33 -0
  46. data/lib/lepus/consumers/middlewares/json.rb +37 -0
  47. data/lib/lepus/consumers/middlewares/max_retry.rb +83 -0
  48. data/lib/lepus/consumers/middlewares/unique.rb +65 -0
  49. data/lib/lepus/consumers/stats.rb +70 -0
  50. data/lib/lepus/consumers/stats_registry.rb +29 -0
  51. data/lib/lepus/consumers/worker.rb +141 -0
  52. data/lib/lepus/consumers/worker_factory.rb +124 -0
  53. data/lib/lepus/consumers.rb +6 -0
  54. data/lib/lepus/message/delivery_info.rb +72 -0
  55. data/lib/lepus/message/metadata.rb +99 -0
  56. data/lib/lepus/message.rb +88 -5
  57. data/lib/lepus/middleware_chain.rb +83 -0
  58. data/lib/lepus/primitive/hash.rb +29 -0
  59. data/lib/lepus/process.rb +24 -24
  60. data/lib/lepus/process_registry/backend.rb +49 -0
  61. data/lib/lepus/process_registry/file_backend.rb +108 -0
  62. data/lib/lepus/process_registry/message_builder.rb +72 -0
  63. data/lib/lepus/process_registry/rabbitmq_backend.rb +153 -0
  64. data/lib/lepus/process_registry.rb +56 -23
  65. data/lib/lepus/processes/base.rb +0 -5
  66. data/lib/lepus/processes/callbacks.rb +3 -0
  67. data/lib/lepus/processes/interruptible.rb +4 -8
  68. data/lib/lepus/processes/procline.rb +1 -1
  69. data/lib/lepus/processes/registrable.rb +1 -1
  70. data/lib/lepus/processes/runnable.rb +1 -1
  71. data/lib/lepus/processes.rb +15 -0
  72. data/lib/lepus/producer.rb +141 -30
  73. data/lib/lepus/producers/config.rb +46 -0
  74. data/lib/lepus/producers/definition.rb +48 -0
  75. data/lib/lepus/producers/hooks.rb +170 -0
  76. data/lib/lepus/producers/middleware_chain.rb +22 -0
  77. data/lib/lepus/producers/middlewares/correlation_id.rb +37 -0
  78. data/lib/lepus/producers/middlewares/header.rb +47 -0
  79. data/lib/lepus/producers/middlewares/instrumentation.rb +30 -0
  80. data/lib/lepus/producers/middlewares/json.rb +47 -0
  81. data/lib/lepus/producers/middlewares/unique.rb +67 -0
  82. data/lib/lepus/producers.rb +7 -0
  83. data/lib/lepus/prometheus/collector.rb +149 -0
  84. data/lib/lepus/prometheus/instrumentation.rb +168 -0
  85. data/lib/lepus/prometheus.rb +48 -0
  86. data/lib/lepus/publisher.rb +67 -0
  87. data/lib/lepus/supervisor/children_pipes.rb +25 -0
  88. data/lib/lepus/supervisor/lifecycle_hooks.rb +50 -0
  89. data/lib/lepus/supervisor/pidfiled.rb +1 -1
  90. data/lib/lepus/supervisor/registry_cleaner.rb +22 -0
  91. data/lib/lepus/supervisor.rb +129 -25
  92. data/lib/lepus/testing/exchange.rb +95 -0
  93. data/lib/lepus/testing/message_builder.rb +177 -0
  94. data/lib/lepus/testing/rspec_matchers.rb +258 -0
  95. data/lib/lepus/testing.rb +210 -0
  96. data/lib/lepus/unique.rb +18 -0
  97. data/lib/lepus/version.rb +1 -1
  98. data/lib/lepus/web/aggregator.rb +154 -0
  99. data/lib/lepus/web/api.rb +132 -0
  100. data/lib/lepus/web/app.rb +37 -0
  101. data/lib/lepus/web/management_api.rb +192 -0
  102. data/lib/lepus/web/respond_with.rb +28 -0
  103. data/lib/lepus/web.rb +238 -0
  104. data/lib/lepus.rb +39 -28
  105. data/test_offline.html +189 -0
  106. data/web/assets/css/styles.css +635 -0
  107. data/web/assets/js/app.js +6 -0
  108. data/web/assets/js/bootstrap.js +20 -0
  109. data/web/assets/js/controllers/connection_controller.js +44 -0
  110. data/web/assets/js/controllers/dashboard_controller.js +499 -0
  111. data/web/assets/js/controllers/queue_controller.js +17 -0
  112. data/web/assets/js/controllers/theme_controller.js +31 -0
  113. data/web/assets/js/offline-manager.js +233 -0
  114. data/web/assets/js/service-worker-manager.js +65 -0
  115. data/web/index.html +159 -0
  116. data/web/sw.js +144 -0
  117. metadata +177 -18
  118. data/lib/lepus/consumer_config.rb +0 -149
  119. data/lib/lepus/consumer_wrapper.rb +0 -46
  120. data/lib/lepus/lifecycle_hooks.rb +0 -49
  121. data/lib/lepus/middlewares/honeybadger.rb +0 -23
  122. data/lib/lepus/middlewares/json.rb +0 -35
  123. data/lib/lepus/middlewares/max_retry.rb +0 -57
  124. data/lib/lepus/processes/consumer.rb +0 -113
  125. data/lib/lepus/supervisor/config.rb +0 -45
data/test_offline.html ADDED
@@ -0,0 +1,189 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Lepus Offline Test</title>
7
+ <style>
8
+ body { font-family: system-ui; padding: 20px; }
9
+ .test-section { margin: 20px 0; padding: 15px; border: 1px solid #ccc; border-radius: 5px; }
10
+ .success { background: #d4edda; border-color: #c3e6cb; }
11
+ .error { background: #f8d7da; border-color: #f5c6cb; }
12
+ .info { background: #d1ecf1; border-color: #bee5eb; }
13
+ button { padding: 10px 15px; margin: 5px; cursor: pointer; }
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <h1>Lepus Offline Support Test</h1>
18
+
19
+ <div class="test-section info">
20
+ <h3>Current Status</h3>
21
+ <p>Online: <span id="online-status">Checking...</span></p>
22
+ <p>Service Worker: <span id="sw-status">Checking...</span></p>
23
+ </div>
24
+
25
+ <div class="test-section">
26
+ <h3>Test Controls</h3>
27
+ <button onclick="simulateOffline()">Simulate Offline</button>
28
+ <button onclick="simulateOnline()">Simulate Online</button>
29
+ <button onclick="testExternalDependencies()">Test External Dependencies</button>
30
+ <button onclick="testServiceWorker()">Test Service Worker</button>
31
+ <button onclick="testOfflineModules()">Test Offline Modules</button>
32
+ </div>
33
+
34
+ <div class="test-section">
35
+ <h3>Test Results</h3>
36
+ <div id="test-results"></div>
37
+ </div>
38
+
39
+ <script>
40
+ // Test offline functionality
41
+ function updateStatus() {
42
+ document.getElementById('online-status').textContent = navigator.onLine ? 'Yes' : 'No';
43
+ document.getElementById('online-status').style.color = navigator.onLine ? 'green' : 'red';
44
+ }
45
+
46
+ function addResult(message, type = 'info') {
47
+ const results = document.getElementById('test-results');
48
+ const div = document.createElement('div');
49
+ div.className = `test-section ${type}`;
50
+ div.innerHTML = `<p>${new Date().toLocaleTimeString()}: ${message}</p>`;
51
+ results.appendChild(div);
52
+ }
53
+
54
+ function simulateOffline() {
55
+ Object.defineProperty(navigator, 'onLine', {
56
+ writable: true,
57
+ value: false
58
+ });
59
+ window.dispatchEvent(new Event('offline'));
60
+ updateStatus();
61
+ addResult('Simulated offline state', 'info');
62
+ }
63
+
64
+ function simulateOnline() {
65
+ Object.defineProperty(navigator, 'onLine', {
66
+ writable: true,
67
+ value: true
68
+ });
69
+ window.dispatchEvent(new Event('online'));
70
+ updateStatus();
71
+ addResult('Simulated online state', 'success');
72
+ }
73
+
74
+ async function testExternalDependencies() {
75
+ addResult('Testing external dependencies...', 'info');
76
+
77
+ try {
78
+ // Test Stimulus CDN
79
+ const stimulusResponse = await fetch('https://unpkg.com/@hotwired/stimulus@3.2.2/dist/stimulus.umd.js');
80
+ if (stimulusResponse.ok) {
81
+ addResult('✓ Stimulus CDN accessible', 'success');
82
+ } else {
83
+ addResult('✗ Stimulus CDN not accessible', 'error');
84
+ }
85
+ } catch (error) {
86
+ addResult('✗ Stimulus CDN failed: ' + error.message, 'error');
87
+ }
88
+
89
+ try {
90
+ // Test Chart.js CDN
91
+ const chartResponse = await fetch('https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js');
92
+ if (chartResponse.ok) {
93
+ addResult('✓ Chart.js CDN accessible', 'success');
94
+ } else {
95
+ addResult('✗ Chart.js CDN not accessible', 'error');
96
+ }
97
+ } catch (error) {
98
+ addResult('✗ Chart.js CDN failed: ' + error.message, 'error');
99
+ }
100
+ }
101
+
102
+ function testServiceWorker() {
103
+ if ('serviceWorker' in navigator) {
104
+ navigator.serviceWorker.register('/sw.js')
105
+ .then(registration => {
106
+ addResult('✓ Service Worker registered successfully', 'success');
107
+ return navigator.serviceWorker.ready;
108
+ })
109
+ .then(registration => {
110
+ addResult('✓ Service Worker ready', 'success');
111
+ document.getElementById('sw-status').textContent = 'Active';
112
+ document.getElementById('sw-status').style.color = 'green';
113
+ })
114
+ .catch(error => {
115
+ addResult('✗ Service Worker failed: ' + error.message, 'error');
116
+ document.getElementById('sw-status').textContent = 'Failed';
117
+ document.getElementById('sw-status').style.color = 'red';
118
+ });
119
+ } else {
120
+ addResult('✗ Service Worker not supported', 'error');
121
+ document.getElementById('sw-status').textContent = 'Not Supported';
122
+ document.getElementById('sw-status').style.color = 'red';
123
+ }
124
+ }
125
+
126
+ async function testOfflineModules() {
127
+ addResult('Testing offline modules...', 'info');
128
+
129
+ try {
130
+ // Test offline-manager.js
131
+ const offlineResponse = await fetch('/assets/js/offline-manager.js');
132
+ if (offlineResponse.ok) {
133
+ addResult('✓ offline-manager.js accessible', 'success');
134
+ } else {
135
+ addResult('✗ offline-manager.js not accessible', 'error');
136
+ }
137
+ } catch (error) {
138
+ addResult('✗ offline-manager.js failed: ' + error.message, 'error');
139
+ }
140
+
141
+ try {
142
+ // Test service-worker-manager.js
143
+ const swResponse = await fetch('/assets/js/service-worker-manager.js');
144
+ if (swResponse.ok) {
145
+ addResult('✓ service-worker-manager.js accessible', 'success');
146
+ } else {
147
+ addResult('✗ service-worker-manager.js not accessible', 'error');
148
+ }
149
+ } catch (error) {
150
+ addResult('✗ service-worker-manager.js failed: ' + error.message, 'error');
151
+ }
152
+
153
+ // Test if modules are loaded in window
154
+ if (window.OfflineManager) {
155
+ addResult('✓ OfflineManager class available', 'success');
156
+ } else {
157
+ addResult('✗ OfflineManager class not available', 'error');
158
+ }
159
+
160
+ if (window.ServiceWorkerManager) {
161
+ addResult('✓ ServiceWorkerManager class available', 'success');
162
+ } else {
163
+ addResult('✗ ServiceWorkerManager class not available', 'error');
164
+ }
165
+ }
166
+
167
+ // Initialize
168
+ updateStatus();
169
+
170
+ // Listen for online/offline events
171
+ window.addEventListener('online', () => {
172
+ updateStatus();
173
+ addResult('Browser went online', 'success');
174
+ });
175
+
176
+ window.addEventListener('offline', () => {
177
+ updateStatus();
178
+ addResult('Browser went offline', 'error');
179
+ });
180
+
181
+ // Auto-test on load
182
+ setTimeout(() => {
183
+ testExternalDependencies();
184
+ testServiceWorker();
185
+ testOfflineModules();
186
+ }, 1000);
187
+ </script>
188
+ </body>
189
+ </html>