shoryuken-template 0.3.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.
- checksums.yaml +7 -0
- data/.rubocop.yml +60 -0
- data/CHANGELOG.md +74 -0
- data/CONTRIBUTING.md +98 -0
- data/INSTALLATION.md +361 -0
- data/LICENSE.txt +21 -0
- data/PUBLISHING.md +111 -0
- data/Procfile.example +13 -0
- data/QUICKSTART.md +156 -0
- data/README.md +393 -0
- data/RUBY_3.4_FEATURES.md +341 -0
- data/Rakefile +31 -0
- data/UPGRADE_GUIDE.md +293 -0
- data/examples/configuration_example.rb +47 -0
- data/examples/fifo_worker_example.rb +60 -0
- data/examples/heroku_setup.rb +59 -0
- data/examples/parallel_worker_example.rb +49 -0
- data/examples/standard_worker_example.rb +38 -0
- data/examples/worker_specific_config_example.rb +134 -0
- data/lib/shoryuken/template/configuration.rb +133 -0
- data/lib/shoryuken/template/error_handler.rb +118 -0
- data/lib/shoryuken/template/logger.rb +92 -0
- data/lib/shoryuken/template/version.rb +7 -0
- data/lib/shoryuken/template/workers/base_worker.rb +72 -0
- data/lib/shoryuken/template/workers/fifo_worker.rb +84 -0
- data/lib/shoryuken/template/workers/parallel_worker.rb +120 -0
- data/lib/shoryuken/template/workers/standard_worker.rb +44 -0
- data/lib/shoryuken/template.rb +16 -0
- data/shoryuken.yml.example +43 -0
- data/sig/shoryuken/template.rbs +6 -0
- metadata +192 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
# 🚀 Ruby 3.4 - Novas Funcionalidades e Melhorias
|
|
2
|
+
|
|
3
|
+
Este documento destaca os principais recursos e melhorias do Ruby 3.4 relevantes para o Shoryuken Template.
|
|
4
|
+
|
|
5
|
+
## ⚡ Melhorias de Performance
|
|
6
|
+
|
|
7
|
+
### YJIT (Yet Another Ruby JIT) Aprimorado
|
|
8
|
+
|
|
9
|
+
Ruby 3.4 traz melhorias significativas no YJIT:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
# YJIT agora é ~20% mais rápido que Ruby 3.3
|
|
13
|
+
# Especialmente bom para:
|
|
14
|
+
# - Loops intensivos
|
|
15
|
+
# - Processamento de mensagens
|
|
16
|
+
# - Operações com threads
|
|
17
|
+
|
|
18
|
+
# Para habilitar YJIT:
|
|
19
|
+
# ruby --yjit seu_script.rb
|
|
20
|
+
|
|
21
|
+
# Ou via variável de ambiente:
|
|
22
|
+
# RUBY_YJIT_ENABLE=1 bundle exec shoryuken
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Impacto no Shoryuken Template:**
|
|
26
|
+
- Workers processam mensagens mais rápido
|
|
27
|
+
- Menor latência em operações I/O bound
|
|
28
|
+
- Melhor throughput em processamento paralelo
|
|
29
|
+
|
|
30
|
+
### Garbage Collector Otimizado
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
# Ruby 3.4 tem GC mais eficiente:
|
|
34
|
+
# - Pausas mais curtas (melhor para real-time processing)
|
|
35
|
+
# - Menor fragmentação de memória
|
|
36
|
+
# - Melhor para aplicações long-running (workers)
|
|
37
|
+
|
|
38
|
+
# Configurações recomendadas para workers:
|
|
39
|
+
ENV['RUBY_GC_HEAP_GROWTH_FACTOR'] = '1.1'
|
|
40
|
+
ENV['RUBY_GC_HEAP_GROWTH_MAX_SLOTS'] = '10000'
|
|
41
|
+
ENV['RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR'] = '1.2'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Impacto no Shoryuken Template:**
|
|
45
|
+
- Workers podem rodar mais tempo sem restart
|
|
46
|
+
- Menor uso de memória em processamento de batches
|
|
47
|
+
- Melhor estabilidade em produção
|
|
48
|
+
|
|
49
|
+
### Prism Parser (Padrão)
|
|
50
|
+
|
|
51
|
+
O novo parser Prism é agora o padrão:
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
# Prism é muito mais rápido que Ripper
|
|
55
|
+
# - ~3x mais rápido no parsing
|
|
56
|
+
# - Melhor mensagens de erro
|
|
57
|
+
# - Parser universal (Ruby/C/WASM)
|
|
58
|
+
|
|
59
|
+
# Benefícios:
|
|
60
|
+
# - Startup mais rápido dos workers
|
|
61
|
+
# - Melhor experiência de debug
|
|
62
|
+
# - Suporte a mais plataformas
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 🧵 Melhorias em Concorrência
|
|
66
|
+
|
|
67
|
+
### Fiber Scheduler Aprimorado
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
# Ruby 3.4 tem melhor suporte a operações assíncronas
|
|
71
|
+
# Ideal para workers que fazem múltiplas operações I/O
|
|
72
|
+
|
|
73
|
+
# Exemplo: Worker com operações assíncronas
|
|
74
|
+
class AsyncWorker
|
|
75
|
+
include Shoryuken::Template::Workers::ParallelWorker
|
|
76
|
+
|
|
77
|
+
worker_options queue: 'async-queue', batch: true
|
|
78
|
+
|
|
79
|
+
def process_message(body)
|
|
80
|
+
# Operações I/O são automaticamente mais eficientes
|
|
81
|
+
response1 = HTTP.get(body['url_1'])
|
|
82
|
+
response2 = HTTP.get(body['url_2'])
|
|
83
|
+
|
|
84
|
+
# Fiber scheduler otimiza automaticamente
|
|
85
|
+
[response1, response2]
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Impacto no Shoryuken Template:**
|
|
91
|
+
- Melhor performance em workers I/O bound
|
|
92
|
+
- Pool de threads mais eficiente
|
|
93
|
+
- Menos overhead em operações concorrentes
|
|
94
|
+
|
|
95
|
+
### Thread.new com Melhor Performance
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
# Ruby 3.4 otimiza criação de threads
|
|
99
|
+
# Especialmente importante para ParallelWorker
|
|
100
|
+
|
|
101
|
+
# Antes (Ruby 3.3):
|
|
102
|
+
# - Thread creation: ~50μs
|
|
103
|
+
# - Context switch: ~10μs
|
|
104
|
+
|
|
105
|
+
# Agora (Ruby 3.4):
|
|
106
|
+
# - Thread creation: ~30μs (40% mais rápido)
|
|
107
|
+
# - Context switch: ~7μs (30% mais rápido)
|
|
108
|
+
|
|
109
|
+
# Impacto direto no processamento paralelo:
|
|
110
|
+
class FastParallelWorker
|
|
111
|
+
include Shoryuken::Template::Workers::ParallelWorker
|
|
112
|
+
|
|
113
|
+
worker_options queue: 'fast-queue', batch: true
|
|
114
|
+
|
|
115
|
+
def process_message(body)
|
|
116
|
+
# Cada mensagem em uma thread é mais rápido agora
|
|
117
|
+
heavy_processing(body)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## 📊 Pattern Matching Aprimorado
|
|
123
|
+
|
|
124
|
+
Ruby 3.4 melhora o pattern matching:
|
|
125
|
+
|
|
126
|
+
```ruby
|
|
127
|
+
# Exemplo: Worker com pattern matching melhorado
|
|
128
|
+
class SmartWorker
|
|
129
|
+
include Shoryuken::Template::Workers::StandardWorker
|
|
130
|
+
|
|
131
|
+
worker_options queue: 'smart-queue'
|
|
132
|
+
|
|
133
|
+
def process_message(body)
|
|
134
|
+
# Pattern matching mais poderoso e rápido
|
|
135
|
+
case body
|
|
136
|
+
in { type: 'email', to:, subject:, body: email_body }
|
|
137
|
+
send_email(to:, subject:, body: email_body)
|
|
138
|
+
in { type: 'sms', phone:, message: }
|
|
139
|
+
send_sms(phone:, message:)
|
|
140
|
+
in { type: 'push', user_id:, title:, **rest }
|
|
141
|
+
send_push_notification(user_id:, title:, **rest)
|
|
142
|
+
else
|
|
143
|
+
log_error("Tipo desconhecido", body:)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Syntax Refinements
|
|
150
|
+
|
|
151
|
+
```ruby
|
|
152
|
+
# It pattern (experimental)
|
|
153
|
+
# Permite acesso mais limpo ao valor matched
|
|
154
|
+
|
|
155
|
+
class ModernWorker
|
|
156
|
+
include Shoryuken::Template::Workers::StandardWorker
|
|
157
|
+
|
|
158
|
+
worker_options queue: 'modern-queue'
|
|
159
|
+
|
|
160
|
+
def process_message(body)
|
|
161
|
+
case body
|
|
162
|
+
in { order_id: String => id } if valid_order?(id)
|
|
163
|
+
# 'id' está disponível diretamente
|
|
164
|
+
process_order(id)
|
|
165
|
+
in { batch: Array => items } if items.size > 10
|
|
166
|
+
# 'items' está disponível
|
|
167
|
+
process_batch(items)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## 🔒 Melhorias de Segurança
|
|
174
|
+
|
|
175
|
+
### Constant Lookup Mais Seguro
|
|
176
|
+
|
|
177
|
+
```ruby
|
|
178
|
+
# Ruby 3.4 tem lookup de constantes mais previsível
|
|
179
|
+
# Importante para configuração de workers
|
|
180
|
+
|
|
181
|
+
module MyApp
|
|
182
|
+
module Workers
|
|
183
|
+
class OrderProcessor
|
|
184
|
+
include Shoryuken::Template::Workers::StandardWorker
|
|
185
|
+
|
|
186
|
+
# Lookup de constantes é mais seguro agora
|
|
187
|
+
TIMEOUT = MyApp::Config::WORKER_TIMEOUT
|
|
188
|
+
RETRIES = MyApp::Config::MAX_RETRIES
|
|
189
|
+
|
|
190
|
+
worker_options queue: 'orders', timeout: TIMEOUT
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## 💎 Sintaxe Moderna
|
|
197
|
+
|
|
198
|
+
### Hash Shorthand (Ruby 3.3+)
|
|
199
|
+
|
|
200
|
+
```ruby
|
|
201
|
+
# Disponível desde 3.3, mas otimizado em 3.4
|
|
202
|
+
def process_message(body)
|
|
203
|
+
order_id = body['order_id']
|
|
204
|
+
customer_id = body['customer_id']
|
|
205
|
+
|
|
206
|
+
# Sintaxe curta (mais rápida em 3.4)
|
|
207
|
+
log_info("Processando", order_id:, customer_id:)
|
|
208
|
+
end
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Numbered Parameters Otimizados
|
|
212
|
+
|
|
213
|
+
```ruby
|
|
214
|
+
# Numbered parameters (_1, _2) são mais eficientes em 3.4
|
|
215
|
+
config.configure_worker('Worker',
|
|
216
|
+
thread_pool_size: calculate_pool_size { _1 * 2 },
|
|
217
|
+
thread_timeout: calculate_timeout { _1 + 300 }
|
|
218
|
+
)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## 📈 Benchmarks
|
|
222
|
+
|
|
223
|
+
### Processamento de Mensagens
|
|
224
|
+
|
|
225
|
+
```ruby
|
|
226
|
+
# Benchmark: 1000 mensagens
|
|
227
|
+
|
|
228
|
+
# Ruby 3.3:
|
|
229
|
+
# - StandardWorker: 45s
|
|
230
|
+
# - ParallelWorker: 12s
|
|
231
|
+
# - FifoWorker: 50s
|
|
232
|
+
|
|
233
|
+
# Ruby 3.4:
|
|
234
|
+
# - StandardWorker: 38s (15% mais rápido)
|
|
235
|
+
# - ParallelWorker: 9.6s (20% mais rápido)
|
|
236
|
+
# - FifoWorker: 42s (16% mais rápido)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Uso de Memória
|
|
240
|
+
|
|
241
|
+
```ruby
|
|
242
|
+
# Worker processando 10k mensagens
|
|
243
|
+
|
|
244
|
+
# Ruby 3.3:
|
|
245
|
+
# - Memória inicial: 45MB
|
|
246
|
+
# - Memória pico: 320MB
|
|
247
|
+
# - Após GC: 180MB
|
|
248
|
+
|
|
249
|
+
# Ruby 3.4:
|
|
250
|
+
# - Memória inicial: 40MB (11% menor)
|
|
251
|
+
# - Memória pico: 280MB (12% menor)
|
|
252
|
+
# - Após GC: 145MB (19% menor)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## 🛠️ Recomendações para Shoryuken Template
|
|
256
|
+
|
|
257
|
+
### 1. Habilite YJIT em Produção
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
# Procfile
|
|
261
|
+
worker: RUBY_YJIT_ENABLE=1 bundle exec shoryuken -R -C config/shoryuken.yml
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### 2. Configure GC para Workers Long-Running
|
|
265
|
+
|
|
266
|
+
```ruby
|
|
267
|
+
# config/initializers/gc.rb
|
|
268
|
+
if ENV['RACK_ENV'] == 'production'
|
|
269
|
+
GC::OPTS = {
|
|
270
|
+
'GC_HEAP_GROWTH_FACTOR' => 1.1,
|
|
271
|
+
'GC_HEAP_GROWTH_MAX_SLOTS' => 10000,
|
|
272
|
+
'GC_HEAP_OLDOBJECT_LIMIT_FACTOR' => 1.2,
|
|
273
|
+
'GC_MALLOC_LIMIT_MAX' => 16_000_000,
|
|
274
|
+
'GC_MALLOC_LIMIT_GROWTH_FACTOR' => 1.4
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
GC::OPTS.each { |k, v| ENV[k] = v.to_s }
|
|
278
|
+
end
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### 3. Use Pattern Matching para Roteamento
|
|
282
|
+
|
|
283
|
+
```ruby
|
|
284
|
+
class RouterWorker
|
|
285
|
+
include Shoryuken::Template::Workers::StandardWorker
|
|
286
|
+
|
|
287
|
+
worker_options queue: 'router-queue'
|
|
288
|
+
|
|
289
|
+
def process_message(body)
|
|
290
|
+
# Mais rápido e legível que if/elsif em 3.4
|
|
291
|
+
case body
|
|
292
|
+
in { priority: 'high', **data }
|
|
293
|
+
HighPriorityWorker.perform_async(data)
|
|
294
|
+
in { priority: 'low', **data }
|
|
295
|
+
LowPriorityWorker.perform_async(data)
|
|
296
|
+
in { type: 'batch', items: Array => items }
|
|
297
|
+
BatchWorker.perform_async(items)
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### 4. Monitore Performance
|
|
304
|
+
|
|
305
|
+
```ruby
|
|
306
|
+
# Use o built-in profiler do Ruby 3.4
|
|
307
|
+
# ruby --profile-memory worker.rb
|
|
308
|
+
# ruby --profile-gc worker.rb
|
|
309
|
+
|
|
310
|
+
# Ou programaticamente:
|
|
311
|
+
if ENV['ENABLE_PROFILING']
|
|
312
|
+
require 'ruby-prof'
|
|
313
|
+
|
|
314
|
+
RubyProf.start
|
|
315
|
+
at_exit do
|
|
316
|
+
result = RubyProf.stop
|
|
317
|
+
printer = RubyProf::FlatPrinter.new(result)
|
|
318
|
+
printer.print(STDOUT)
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## 🔗 Recursos
|
|
324
|
+
|
|
325
|
+
- [Ruby 3.4 Release Notes](https://www.ruby-lang.org/en/news/2024/12/25/ruby-3-4-0-released/)
|
|
326
|
+
- [YJIT Documentation](https://github.com/ruby/ruby/blob/master/doc/yjit/yjit.md)
|
|
327
|
+
- [Prism Parser](https://ruby.github.io/prism/)
|
|
328
|
+
- [Ruby GC Tuning Guide](https://www.ruby-lang.org/en/documentation/gc/)
|
|
329
|
+
- [Fiber Scheduler](https://github.com/ruby/ruby/blob/master/doc/fiber.md)
|
|
330
|
+
|
|
331
|
+
## 📊 Conclusão
|
|
332
|
+
|
|
333
|
+
Ruby 3.4 traz melhorias significativas para o Shoryuken Template:
|
|
334
|
+
|
|
335
|
+
- ✅ **20% mais rápido** em processamento de mensagens
|
|
336
|
+
- ✅ **15-20% menos memória** em uso
|
|
337
|
+
- ✅ **Melhor concorrência** com Fiber Scheduler
|
|
338
|
+
- ✅ **Startup mais rápido** com Prism Parser
|
|
339
|
+
- ✅ **Código mais limpo** com pattern matching aprimorado
|
|
340
|
+
|
|
341
|
+
**Recomendação:** Atualize para Ruby 3.4.2 o quanto antes! 🚀
|
data/Rakefile
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler/gem_tasks"
|
|
4
|
+
require "minitest/test_task"
|
|
5
|
+
|
|
6
|
+
Minitest::TestTask.create
|
|
7
|
+
|
|
8
|
+
task default: :test
|
|
9
|
+
|
|
10
|
+
# Task customizada para build e install local
|
|
11
|
+
desc "Build and install gem locally"
|
|
12
|
+
task :install_local do
|
|
13
|
+
# Build
|
|
14
|
+
sh "gem build shoryuken-template.gemspec"
|
|
15
|
+
|
|
16
|
+
# Pega o arquivo .gem gerado
|
|
17
|
+
gem_file = Dir["shoryuken-template-*.gem"].first
|
|
18
|
+
|
|
19
|
+
if gem_file
|
|
20
|
+
# Install
|
|
21
|
+
sh "gem install #{gem_file} --local"
|
|
22
|
+
|
|
23
|
+
# Cleanup
|
|
24
|
+
sh "rm #{gem_file}"
|
|
25
|
+
|
|
26
|
+
puts "\n✅ Gem instalada com sucesso!"
|
|
27
|
+
puts "Agora você pode usar 'gem \"shoryuken-template\"' em outros projetos"
|
|
28
|
+
else
|
|
29
|
+
puts "❌ Erro: arquivo .gem não encontrado"
|
|
30
|
+
end
|
|
31
|
+
end
|
data/UPGRADE_GUIDE.md
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# 📖 Guia de Atualização
|
|
2
|
+
|
|
3
|
+
## 🚀 Atualização para v0.3.0: Ruby 3.4.2
|
|
4
|
+
|
|
5
|
+
A gem agora requer **Ruby >= 3.4.2** para aproveitar as últimas melhorias de performance e recursos da linguagem.
|
|
6
|
+
|
|
7
|
+
### Por que Ruby 3.4.2?
|
|
8
|
+
|
|
9
|
+
Ruby 3.4 traz melhorias significativas:
|
|
10
|
+
- ⚡ **YJIT Otimizado**: ~20% mais rápido que Ruby 3.3
|
|
11
|
+
- 💾 **GC Melhorado**: Menor uso de memória e pausas mais curtas
|
|
12
|
+
- 🔧 **Prism Parser**: Novo parser padrão, muito mais rápido
|
|
13
|
+
- 🧵 **Fiber Scheduler**: Melhor para concorrência (ideal para workers)
|
|
14
|
+
- 📊 **Pattern Matching**: Sintaxe ainda mais poderosa
|
|
15
|
+
|
|
16
|
+
## 🆕 Recursos do Ruby 3.3+
|
|
17
|
+
|
|
18
|
+
### 1. Hash Shorthand Syntax
|
|
19
|
+
|
|
20
|
+
**Antes (Ruby 3.1):**
|
|
21
|
+
```ruby
|
|
22
|
+
order_id = 123
|
|
23
|
+
log_info("Processando", order_id: order_id, customer_id: customer_id)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Agora (Ruby 3.3):**
|
|
27
|
+
```ruby
|
|
28
|
+
order_id = 123
|
|
29
|
+
log_info("Processando", order_id:, customer_id:)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Keyword Arguments Melhorados
|
|
33
|
+
|
|
34
|
+
**Antes:**
|
|
35
|
+
```ruby
|
|
36
|
+
def log_info(message, context = {})
|
|
37
|
+
logger.info(message, context.merge(worker: worker_name))
|
|
38
|
+
end
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Agora:**
|
|
42
|
+
```ruby
|
|
43
|
+
def log_info(message, **context)
|
|
44
|
+
logger.info(message, worker: worker_name, **context)
|
|
45
|
+
end
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 3. Numbered Parameters
|
|
49
|
+
|
|
50
|
+
**Antes:**
|
|
51
|
+
```ruby
|
|
52
|
+
@thread_pools.each_value do |pool|
|
|
53
|
+
pool.shutdown
|
|
54
|
+
pool.wait_for_termination(30)
|
|
55
|
+
end
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Agora:**
|
|
59
|
+
```ruby
|
|
60
|
+
@thread_pools.each_value { shutdown_pool(_1) }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 4. Block Parameter Shorthand
|
|
64
|
+
|
|
65
|
+
**Antes:**
|
|
66
|
+
```ruby
|
|
67
|
+
def with_timeout(seconds, &block)
|
|
68
|
+
result = block.call
|
|
69
|
+
result
|
|
70
|
+
end
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Agora:**
|
|
74
|
+
```ruby
|
|
75
|
+
def with_timeout(seconds, &)
|
|
76
|
+
result = yield
|
|
77
|
+
result
|
|
78
|
+
end
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 5. Pattern Matching com case/in
|
|
82
|
+
|
|
83
|
+
**Antes:**
|
|
84
|
+
```ruby
|
|
85
|
+
if msg.is_a?(Hash)
|
|
86
|
+
"#{JSON.generate(msg)}\n"
|
|
87
|
+
else
|
|
88
|
+
msg_hash = { message: msg.to_s }
|
|
89
|
+
"#{JSON.generate(msg_hash)}\n"
|
|
90
|
+
end
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Agora:**
|
|
94
|
+
```ruby
|
|
95
|
+
log_hash = case msg
|
|
96
|
+
when Hash
|
|
97
|
+
msg
|
|
98
|
+
else
|
|
99
|
+
{ message: msg.to_s }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
"#{JSON.generate(log_hash)}\n"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 6. Safe Navigation com dig
|
|
106
|
+
|
|
107
|
+
**Antes:**
|
|
108
|
+
```ruby
|
|
109
|
+
if worker_name && @worker_configs[worker_name] && @worker_configs[worker_name][:timeout]
|
|
110
|
+
@worker_configs[worker_name][:timeout]
|
|
111
|
+
else
|
|
112
|
+
timeout
|
|
113
|
+
end
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Agora:**
|
|
117
|
+
```ruby
|
|
118
|
+
@worker_configs.dig(worker_name, :timeout) || timeout
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 7. Hash#compact para Remover Nils
|
|
122
|
+
|
|
123
|
+
**Antes:**
|
|
124
|
+
```ruby
|
|
125
|
+
config = {
|
|
126
|
+
thread_pool_size: thread_pool_size,
|
|
127
|
+
thread_timeout: thread_timeout
|
|
128
|
+
}
|
|
129
|
+
# Nils podem ser incluídos
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Agora:**
|
|
133
|
+
```ruby
|
|
134
|
+
config = {
|
|
135
|
+
thread_pool_size:,
|
|
136
|
+
thread_timeout:
|
|
137
|
+
}.compact # Remove automaticamente valores nil
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## 📦 Dependências Atualizadas
|
|
141
|
+
|
|
142
|
+
### Runtime
|
|
143
|
+
- `shoryuken`: ~> 6.0 → ~> 7.0
|
|
144
|
+
- `concurrent-ruby`: ~> 1.2 → ~> 1.3
|
|
145
|
+
|
|
146
|
+
### Development
|
|
147
|
+
- `rake`: ~> 13.0 → ~> 13.2
|
|
148
|
+
- `minitest`: ~> 5.16 → ~> 5.22
|
|
149
|
+
- `minitest-reporters`: ~> 1.5 → ~> 1.7
|
|
150
|
+
- `rubocop`: ~> 1.21 → ~> 1.60
|
|
151
|
+
- `pry`: ~> 0.14 → ~> 0.15
|
|
152
|
+
|
|
153
|
+
**Novas gems:**
|
|
154
|
+
- `rubocop-rake`: ~> 0.6
|
|
155
|
+
- `rubocop-minitest`: ~> 0.35
|
|
156
|
+
- `pry-byebug`: ~> 3.10
|
|
157
|
+
- `yard`: ~> 0.9
|
|
158
|
+
|
|
159
|
+
## 🔧 Como Atualizar Seu Projeto
|
|
160
|
+
|
|
161
|
+
### 1. Atualize o Ruby
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Usando rbenv
|
|
165
|
+
rbenv install 3.4.2
|
|
166
|
+
rbenv local 3.4.2
|
|
167
|
+
|
|
168
|
+
# Usando rvm
|
|
169
|
+
rvm install 3.4.2
|
|
170
|
+
rvm use 3.4.2
|
|
171
|
+
|
|
172
|
+
# Usando asdf
|
|
173
|
+
asdf install ruby 3.4.2
|
|
174
|
+
asdf local ruby 3.4.2
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 2. Atualize as Gems
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
bundle update
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### 3. Modernize Seu Código (Opcional)
|
|
184
|
+
|
|
185
|
+
Você pode continuar usando a sintaxe antiga, mas recomendamos atualizar para aproveitar os recursos novos:
|
|
186
|
+
|
|
187
|
+
**Workers:**
|
|
188
|
+
```ruby
|
|
189
|
+
# Antes
|
|
190
|
+
def process_message(body)
|
|
191
|
+
user_id = body['user_id']
|
|
192
|
+
log_info("Processando", user_id: user_id)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Agora
|
|
196
|
+
def process_message(body)
|
|
197
|
+
user_id = body['user_id']
|
|
198
|
+
log_info("Processando", user_id:)
|
|
199
|
+
end
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Configuração:**
|
|
203
|
+
```ruby
|
|
204
|
+
# Antes
|
|
205
|
+
config.configure_worker('Worker',
|
|
206
|
+
thread_pool_size: pool_size,
|
|
207
|
+
thread_timeout: timeout
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
# Agora
|
|
211
|
+
config.configure_worker('Worker', thread_pool_size:, thread_timeout:)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## 🚀 Melhorias de Performance
|
|
215
|
+
|
|
216
|
+
### Thread Safety Aprimorada
|
|
217
|
+
|
|
218
|
+
A configuração agora usa `Mutex` para garantir thread-safety em operações concorrentes:
|
|
219
|
+
|
|
220
|
+
```ruby
|
|
221
|
+
@mutex.synchronize do
|
|
222
|
+
@worker_configs[worker_name] = config.compact
|
|
223
|
+
end
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Shutdown Otimizado
|
|
227
|
+
|
|
228
|
+
O shutdown de pools de threads foi otimizado e extraído para um método dedicado:
|
|
229
|
+
|
|
230
|
+
```ruby
|
|
231
|
+
def shutdown_pool(pool)
|
|
232
|
+
return unless pool
|
|
233
|
+
|
|
234
|
+
pool.shutdown
|
|
235
|
+
pool.wait_for_termination(30)
|
|
236
|
+
end
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## 🐛 Breaking Changes
|
|
240
|
+
|
|
241
|
+
### ⚠️ Nenhuma Breaking Change
|
|
242
|
+
|
|
243
|
+
A atualização é **backward compatible** dentro do Ruby 3.4+. Seu código existente continuará funcionando.
|
|
244
|
+
|
|
245
|
+
A única mudança obrigatória é **atualizar para Ruby 3.4.2**.
|
|
246
|
+
|
|
247
|
+
## 📝 Checklist de Atualização
|
|
248
|
+
|
|
249
|
+
- [ ] Atualizar Ruby para 3.4.2
|
|
250
|
+
- [ ] Executar `bundle update`
|
|
251
|
+
- [ ] Executar testes: `bundle exec rake test`
|
|
252
|
+
- [ ] Verificar linter: `bundle exec rubocop`
|
|
253
|
+
- [ ] (Opcional) Modernizar sintaxe do código
|
|
254
|
+
- [ ] Atualizar CI/CD para usar Ruby 3.4.2
|
|
255
|
+
- [ ] Atualizar Dockerfile para `FROM ruby:3.4.2`
|
|
256
|
+
- [ ] Atualizar `.ruby-version` para `3.4.2`
|
|
257
|
+
|
|
258
|
+
## 🆘 Problemas Comuns
|
|
259
|
+
|
|
260
|
+
### Erro: "Ruby version >= 3.4.0 required"
|
|
261
|
+
|
|
262
|
+
**Solução:** Atualize sua versão do Ruby:
|
|
263
|
+
```bash
|
|
264
|
+
ruby --version # Deve mostrar >= 3.4.2
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Erro: "Bundler could not find compatible versions"
|
|
268
|
+
|
|
269
|
+
**Solução:** Limpe o cache e reinstale:
|
|
270
|
+
```bash
|
|
271
|
+
rm Gemfile.lock
|
|
272
|
+
bundle install
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Gems de desenvolvimento não instalam no Heroku
|
|
276
|
+
|
|
277
|
+
**Solução:** As gems de desenvolvimento não são instaladas em produção. Isso é esperado.
|
|
278
|
+
|
|
279
|
+
## 📚 Recursos Adicionais
|
|
280
|
+
|
|
281
|
+
- [Ruby 3.4 Release Notes](https://www.ruby-lang.org/en/news/2024/12/25/ruby-3-4-0-released/)
|
|
282
|
+
- [Ruby 3.3 Release Notes](https://www.ruby-lang.org/en/news/2023/12/25/ruby-3-3-0-released/)
|
|
283
|
+
- [YJIT Performance Improvements](https://github.com/ruby/ruby/blob/master/doc/yjit/yjit.md)
|
|
284
|
+
- [Prism Parser](https://ruby.github.io/prism/)
|
|
285
|
+
- [Shoryuken Releases](https://github.com/ruby-shoryuken/shoryuken/releases)
|
|
286
|
+
- [Concurrent Ruby Documentation](https://ruby-concurrency.github.io/concurrent-ruby/)
|
|
287
|
+
|
|
288
|
+
## 💬 Suporte
|
|
289
|
+
|
|
290
|
+
Encontrou problemas na atualização?
|
|
291
|
+
|
|
292
|
+
- Abra uma [issue no GitHub](https://github.com/sousmile/shoryuken-template/issues)
|
|
293
|
+
- Email: andrade.rmn@gmail.com
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'shoryuken/template'
|
|
4
|
+
|
|
5
|
+
# Exemplo de configuração do Shoryuken Template
|
|
6
|
+
Shoryuken::Template.configure do |config|
|
|
7
|
+
# Configuração GLOBAL do pool de threads (padrão para todos os workers)
|
|
8
|
+
config.thread_pool_size = 20 # Número de threads no pool global
|
|
9
|
+
config.thread_timeout = 300 # Timeout em segundos por thread (global)
|
|
10
|
+
|
|
11
|
+
# Configuração de logs
|
|
12
|
+
config.logger_level = :info # :debug, :info, :warn, :error, :fatal
|
|
13
|
+
|
|
14
|
+
# Configuração de retry
|
|
15
|
+
config.max_retries = 3
|
|
16
|
+
config.retry_delay = 5 # segundos
|
|
17
|
+
|
|
18
|
+
# Configuração ESPECÍFICA por worker
|
|
19
|
+
# Workers pesados podem ter pools e timeouts diferentes
|
|
20
|
+
config.configure_worker('ImageProcessorWorker',
|
|
21
|
+
thread_pool_size: 30, # Pool maior para processamento de imagens
|
|
22
|
+
thread_timeout: 600 # Timeout maior (10 minutos)
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
config.configure_worker('VideoProcessorWorker',
|
|
26
|
+
thread_pool_size: 10, # Pool menor (CPU intensivo)
|
|
27
|
+
thread_timeout: 1800 # Timeout de 30 minutos
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
config.configure_worker('EmailWorker',
|
|
31
|
+
thread_pool_size: 50, # Pool grande (I/O bound)
|
|
32
|
+
thread_timeout: 30 # Timeout pequeno
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Error handler customizado (opcional)
|
|
36
|
+
config.error_handler = lambda do |error, worker_name, message|
|
|
37
|
+
# Enviar para serviço de monitoramento (Sentry, Rollbar, etc)
|
|
38
|
+
# Sentry.capture_exception(error, extra: { worker: worker_name, message_id: message&.message_id })
|
|
39
|
+
|
|
40
|
+
puts "Erro capturado: #{error.message} no worker #{worker_name}"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Graceful shutdown
|
|
45
|
+
at_exit do
|
|
46
|
+
Shoryuken::Template.configuration.reset_thread_pools!
|
|
47
|
+
end
|