smart_message 0.0.1 → 0.0.3

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.
@@ -0,0 +1,471 @@
1
+ # SmartMessage Property System
2
+
3
+ The SmartMessage property system builds on Hashie::Dash to provide a robust, declarative way to define message attributes. This document covers all available property options and features.
4
+
5
+ ## Table of Contents
6
+ - [Basic Property Definition](#basic-property-definition)
7
+ - [Class-Level Description](#class-level-description)
8
+ - [Property Options](#property-options)
9
+ - [Accessing Property Information](#accessing-property-information)
10
+ - [Hashie Extensions](#hashie-extensions)
11
+ - [Examples](#examples)
12
+
13
+ ## Basic Property Definition
14
+
15
+ Properties are defined using the `property` method in your message class:
16
+
17
+ ```ruby
18
+ class MyMessage < SmartMessage::Base
19
+ property :field_name
20
+ end
21
+ ```
22
+
23
+ ## Class-Level Description
24
+
25
+ In addition to property-level descriptions, you can add a description for the entire message class:
26
+
27
+ ```ruby
28
+ class OrderMessage < SmartMessage::Base
29
+ description "Handles order processing and fulfillment workflow"
30
+
31
+ property :order_id, description: "Unique order identifier"
32
+ property :amount, description: "Total amount in cents"
33
+ end
34
+
35
+ # Access the class description
36
+ OrderMessage.description # => "Handles order processing and fulfillment workflow"
37
+
38
+ # Class descriptions can also be set after class definition
39
+ class PaymentMessage < SmartMessage::Base
40
+ property :payment_id
41
+ end
42
+
43
+ PaymentMessage.description "Processes payment transactions"
44
+ PaymentMessage.description # => "Processes payment transactions"
45
+
46
+ # Can be set within config block
47
+ class NotificationMessage < SmartMessage::Base
48
+ config do
49
+ description "Sends notifications to users"
50
+ transport MyTransport.new
51
+ serializer MySerializer.new
52
+ end
53
+ end
54
+ ```
55
+
56
+ Class descriptions are useful for:
57
+ - Documenting the overall purpose of a message class
58
+ - Providing context for code generation tools
59
+ - Integration with documentation systems
60
+ - API documentation generation
61
+
62
+ Note: Class descriptions are not inherited by subclasses. Each class maintains its own description.
63
+
64
+ ## Property Options
65
+
66
+ SmartMessage supports all Hashie::Dash property options plus additional features:
67
+
68
+ ### 1. Default Values
69
+
70
+ Specify a default value for a property when not provided during initialization:
71
+
72
+ ```ruby
73
+ class OrderMessage < SmartMessage::Base
74
+ # Static default
75
+ property :status, default: 'pending'
76
+
77
+ # Dynamic default using a Proc
78
+ property :created_at, default: -> { Time.now }
79
+
80
+ # Default array
81
+ property :items, default: []
82
+ end
83
+
84
+ order = OrderMessage.new
85
+ order.status # => 'pending'
86
+ order.created_at # => Current time
87
+ order.items # => []
88
+ ```
89
+
90
+ ### 2. Required Properties
91
+
92
+ Mark properties as required to ensure they're provided during initialization:
93
+
94
+ ```ruby
95
+ class PaymentMessage < SmartMessage::Base
96
+ property :payment_id, required: true
97
+ property :amount, required: true
98
+ property :note # Optional
99
+ end
100
+
101
+ # This raises ArgumentError: The property 'payment_id' is required
102
+ PaymentMessage.new(amount: 100)
103
+
104
+ # This works
105
+ PaymentMessage.new(payment_id: 'PAY-123', amount: 100)
106
+ ```
107
+
108
+ ### 3. Property Transformation
109
+
110
+ Transform property values when they're set:
111
+
112
+ ```ruby
113
+ class UserMessage < SmartMessage::Base
114
+ property :email, transform_with: ->(v) { v.to_s.downcase }
115
+ property :name, transform_with: ->(v) { v.to_s.strip.capitalize }
116
+ property :tags, transform_with: ->(v) { Array(v).map(&:to_s) }
117
+ end
118
+
119
+ user = UserMessage.new(
120
+ email: 'USER@EXAMPLE.COM',
121
+ name: ' john ',
122
+ tags: 'admin'
123
+ )
124
+
125
+ user.email # => 'user@example.com'
126
+ user.name # => 'John'
127
+ user.tags # => ['admin']
128
+ ```
129
+
130
+ ### 4. Property Translation (from Hashie::Extensions::Dash::PropertyTranslation)
131
+
132
+ Map external field names to internal property names:
133
+
134
+ ```ruby
135
+ class ApiMessage < SmartMessage::Base
136
+ property :user_id, from: :userId
137
+ property :order_date, from: 'orderDate'
138
+ property :total_amount, from: [:totalAmount, :total, :amount]
139
+ end
140
+
141
+ # All of these work
142
+ msg1 = ApiMessage.new(userId: 123)
143
+ msg2 = ApiMessage.new(user_id: 123)
144
+ msg3 = ApiMessage.new('orderDate' => '2024-01-01')
145
+ msg4 = ApiMessage.new(totalAmount: 100) # or total: 100, or amount: 100
146
+
147
+ msg1.user_id # => 123
148
+ ```
149
+
150
+ ### 5. Type Coercion (from Hashie::Extensions::Coercion)
151
+
152
+ Automatically coerce property values to specific types:
153
+
154
+ ```ruby
155
+ class TypedMessage < SmartMessage::Base
156
+ property :count
157
+ property :price
158
+ property :active
159
+ property :tags
160
+ property :metadata
161
+
162
+ coerce_key :count, Integer
163
+ coerce_key :price, Float
164
+ coerce_key :active, ->(v) { v.to_s.downcase == 'true' }
165
+ coerce_key :tags, Array[String]
166
+ coerce_key :metadata, Hash
167
+ end
168
+
169
+ msg = TypedMessage.new(
170
+ count: '42',
171
+ price: '19.99',
172
+ active: 'yes',
173
+ tags: 'important',
174
+ metadata: nil
175
+ )
176
+
177
+ msg.count # => 42 (Integer)
178
+ msg.price # => 19.99 (Float)
179
+ msg.active # => false (Boolean logic)
180
+ msg.tags # => ['important'] (Array)
181
+ msg.metadata # => {} (Hash)
182
+ ```
183
+
184
+ ### 6. Property Descriptions (SmartMessage Enhancement)
185
+
186
+ Add human-readable descriptions to document your properties for dynamic LLM integration:
187
+
188
+ ```ruby
189
+ class DocumentedMessage < SmartMessage::Base
190
+ property :transaction_id,
191
+ required: true,
192
+ description: "Unique identifier for the transaction"
193
+
194
+ property :amount,
195
+ transform_with: ->(v) { BigDecimal(v.to_s) },
196
+ description: "Transaction amount in the smallest currency unit"
197
+
198
+ property :currency,
199
+ default: 'USD',
200
+ description: "ISO 4217 currency code"
201
+
202
+ property :status,
203
+ default: 'pending',
204
+ description: "Current transaction status: pending, completed, failed"
205
+
206
+ property :metadata,
207
+ default: {},
208
+ description: "Additional transaction metadata as key-value pairs"
209
+ end
210
+
211
+ # Access descriptions programmatically
212
+ DocumentedMessage.property_description(:amount)
213
+ # => "Transaction amount in the smallest currency unit"
214
+
215
+ DocumentedMessage.property_descriptions
216
+ # => {
217
+ # transaction_id: "Unique identifier for the transaction",
218
+ # amount: "Transaction amount in the smallest currency unit",
219
+ # currency: "ISO 4217 currency code",
220
+ # status: "Current transaction status: pending, completed, failed",
221
+ # metadata: "Additional transaction metadata as key-value pairs"
222
+ # }
223
+
224
+ DocumentedMessage.described_properties
225
+ # => [:transaction_id, :amount, :currency, :status, :metadata]
226
+ ```
227
+
228
+ ## Accessing Property Information
229
+
230
+ SmartMessage provides several methods to introspect properties:
231
+
232
+ ```ruby
233
+ class IntrospectionExample < SmartMessage::Base
234
+ property :id, required: true, description: "Unique identifier"
235
+ property :name, description: "Display name"
236
+ property :created_at, default: -> { Time.now }
237
+ property :tags
238
+ end
239
+
240
+ # Instance methods
241
+ instance = IntrospectionExample.new(id: 1, name: "Test")
242
+ instance.fields # => Set[:id, :name, :created_at, :tags]
243
+ instance.to_h # => Hash of all properties and values
244
+
245
+ # Class methods
246
+ IntrospectionExample.fields # => Set[:id, :name, :created_at, :tags]
247
+ IntrospectionExample.property_descriptions # => Hash of descriptions
248
+ IntrospectionExample.described_properties # => [:id, :name]
249
+ ```
250
+
251
+ ## Hashie Extensions
252
+
253
+ SmartMessage::Base automatically includes these Hashie extensions:
254
+
255
+ ### 1. DeepMerge
256
+ Allows deep merging of nested hash properties:
257
+
258
+ ```ruby
259
+ msg = MyMessage.new(config: { a: 1, b: { c: 2 } })
260
+ msg.deep_merge(config: { b: { d: 3 } })
261
+ # => config: { a: 1, b: { c: 2, d: 3 } }
262
+ ```
263
+
264
+ ### 2. IgnoreUndeclared
265
+ Silently ignores properties that haven't been declared:
266
+
267
+ ```ruby
268
+ # Won't raise an error for unknown properties
269
+ msg = MyMessage.new(known: 'value', unknown: 'ignored')
270
+ ```
271
+
272
+ ### 3. IndifferentAccess
273
+ Access properties with strings or symbols:
274
+
275
+ ```ruby
276
+ msg = MyMessage.new('name' => 'John')
277
+ msg[:name] # => 'John'
278
+ msg['name'] # => 'John'
279
+ msg.name # => 'John'
280
+ ```
281
+
282
+ ### 4. MethodAccess
283
+ Access properties as methods:
284
+
285
+ ```ruby
286
+ msg = MyMessage.new(name: 'John')
287
+ msg.name # => 'John'
288
+ msg.name = 'Jane'
289
+ msg.name # => 'Jane'
290
+ ```
291
+
292
+ ### 5. MergeInitializer
293
+ Allows initializing with merged hash values:
294
+
295
+ ```ruby
296
+ defaults = { status: 'active', retries: 3 }
297
+ msg = MyMessage.new(defaults.merge(status: 'pending'))
298
+ # => status: 'pending', retries: 3
299
+ ```
300
+
301
+ ## Examples
302
+
303
+ ### Complete Example: Order Processing Message
304
+
305
+ ```ruby
306
+ class OrderProcessingMessage < SmartMessage::Base
307
+ description "Manages the complete order lifecycle from placement to delivery"
308
+
309
+ # Required fields with descriptions
310
+ property :order_id,
311
+ required: true,
312
+ description: "Unique order identifier from the ordering system"
313
+
314
+ property :customer_id,
315
+ required: true,
316
+ description: "Customer who placed the order"
317
+
318
+ # Amount with transformation and description
319
+ property :total_amount,
320
+ transform_with: ->(v) { BigDecimal(v.to_s) },
321
+ description: "Total order amount including tax and shipping"
322
+
323
+ # Status with default and validation description
324
+ property :status,
325
+ default: 'pending',
326
+ description: "Order status: pending, processing, shipped, delivered, cancelled"
327
+
328
+ # Items with coercion
329
+ property :items,
330
+ default: [],
331
+ description: "Array of order line items"
332
+
333
+ # Timestamps with dynamic defaults
334
+ property :created_at,
335
+ default: -> { Time.now },
336
+ description: "When the order was created"
337
+
338
+ property :updated_at,
339
+ default: -> { Time.now },
340
+ description: "Last modification timestamp"
341
+
342
+ # Optional fields
343
+ property :notes,
344
+ description: "Optional order notes or special instructions"
345
+
346
+ property :shipping_address,
347
+ description: "Shipping address as a nested hash"
348
+
349
+ # Field translation for external APIs
350
+ property :external_ref,
351
+ from: [:externalReference, :ext_ref],
352
+ description: "Reference ID from external system"
353
+ end
354
+
355
+ # Usage
356
+ order = OrderProcessingMessage.new(
357
+ order_id: 'ORD-2024-001',
358
+ customer_id: 'CUST-123',
359
+ total_amount: '149.99',
360
+ items: [
361
+ { sku: 'WIDGET-A', quantity: 2, price: 49.99 },
362
+ { sku: 'WIDGET-B', quantity: 1, price: 50.01 }
363
+ ],
364
+ shipping_address: {
365
+ street: '123 Main St',
366
+ city: 'Springfield',
367
+ state: 'IL',
368
+ zip: '62701'
369
+ },
370
+ externalReference: 'EXT-789' # Note: uses translated field name
371
+ )
372
+
373
+ # Access properties
374
+ order.order_id # => 'ORD-2024-001'
375
+ order.total_amount # => BigDecimal('149.99')
376
+ order.status # => 'pending' (default)
377
+ order.external_ref # => 'EXT-789' (translated)
378
+ order.created_at # => Time object
379
+
380
+ # Get class and property information
381
+ OrderProcessingMessage.description
382
+ # => "Manages the complete order lifecycle from placement to delivery"
383
+
384
+ OrderProcessingMessage.property_description(:total_amount)
385
+ # => "Total order amount including tax and shipping"
386
+
387
+ OrderProcessingMessage.property_descriptions.keys
388
+ # => [:order_id, :customer_id, :total_amount, :status, :items, ...]
389
+ ```
390
+
391
+ ### Example: API Integration Message
392
+
393
+ ```ruby
394
+ class ApiWebhookMessage < SmartMessage::Base
395
+ # Handle different API naming conventions
396
+ property :event_type,
397
+ from: [:eventType, :event, :type],
398
+ required: true,
399
+ description: "Type of webhook event"
400
+
401
+ property :payload,
402
+ required: true,
403
+ description: "Event payload data"
404
+
405
+ property :timestamp,
406
+ from: [:timestamp, :created_at, :occurredAt],
407
+ transform_with: ->(v) { Time.parse(v.to_s) },
408
+ description: "When the event occurred"
409
+
410
+ property :retry_count,
411
+ from: :retryCount,
412
+ default: 0,
413
+ transform_with: ->(v) { v.to_i },
414
+ description: "Number of delivery attempts"
415
+
416
+ property :signature,
417
+ description: "HMAC signature for webhook validation"
418
+ end
419
+
420
+ # Can initialize with various field names
421
+ webhook1 = ApiWebhookMessage.new(
422
+ eventType: 'order.completed',
423
+ payload: { order_id: 123 },
424
+ occurredAt: '2024-01-01T10:00:00Z',
425
+ retryCount: '2'
426
+ )
427
+
428
+ webhook2 = ApiWebhookMessage.new(
429
+ type: 'order.completed', # Alternative field name
430
+ payload: { order_id: 123 },
431
+ timestamp: Time.now, # Alternative field name
432
+ retry_count: 2 # Internal field name
433
+ )
434
+ ```
435
+
436
+ ## Best Practices
437
+
438
+ 1. **Always add descriptions** to document the purpose and format of each property
439
+ 2. **Use required properties** for fields that must be present for valid messages
440
+ 3. **Provide sensible defaults** for optional fields to reduce boilerplate
441
+ 4. **Use transformations** to ensure data consistency and type safety
442
+ 5. **Leverage field translation** when integrating with external APIs that use different naming conventions
443
+ 6. **Document valid values** in descriptions for enum-like fields (e.g., status fields)
444
+ 7. **Use type coercion** for fields that may come from untrusted sources (like HTTP parameters)
445
+
446
+ ## Property Option Compatibility
447
+
448
+ Multiple options can be combined on a single property:
449
+
450
+ ```ruby
451
+ property :amount,
452
+ required: true,
453
+ from: [:amount, :total, :value],
454
+ transform_with: ->(v) { BigDecimal(v.to_s) },
455
+ description: "Transaction amount in cents"
456
+ ```
457
+
458
+ The processing order is:
459
+ 1. Field translation (from)
460
+ 2. Default value (if not provided)
461
+ 3. Required validation
462
+ 4. Type coercion
463
+ 5. Transformation
464
+ 6. Value assignment
465
+
466
+ ## Limitations
467
+
468
+ - Property names must be valid Ruby method names
469
+ - The `_sm_` prefix is reserved for internal SmartMessage properties
470
+ - Descriptions are metadata only and don't affect runtime behavior
471
+ - Some Hashie options may conflict if used incorrectly (e.g., required with default)
data/docs/transports.md CHANGED
@@ -125,6 +125,194 @@ messages.each do |msg|
125
125
  end
126
126
  ```
127
127
 
128
+ ### Redis Transport
129
+
130
+ Production-ready Redis pub/sub transport for distributed messaging.
131
+
132
+ **Features:**
133
+ - Redis pub/sub messaging
134
+ - Automatic channel management using message class names
135
+ - Thread-safe subscriber management
136
+ - Connection resilience with automatic reconnection
137
+ - Configurable connection parameters
138
+ - Background message subscription threads
139
+
140
+ **Usage:**
141
+
142
+ ```ruby
143
+ # Basic Redis configuration
144
+ transport = SmartMessage::Transport.create(:redis,
145
+ url: 'redis://localhost:6379',
146
+ db: 0
147
+ )
148
+
149
+ # Production configuration with custom options
150
+ transport = SmartMessage::Transport.create(:redis,
151
+ url: 'redis://prod-redis:6379',
152
+ db: 1,
153
+ auto_subscribe: true,
154
+ reconnect_attempts: 5,
155
+ reconnect_delay: 2
156
+ )
157
+
158
+ # Configure in message class
159
+ class OrderMessage < SmartMessage::Base
160
+ property :order_id
161
+ property :customer_id
162
+ property :amount
163
+
164
+ config do
165
+ transport SmartMessage::Transport.create(:redis,
166
+ url: 'redis://localhost:6379',
167
+ db: 1
168
+ )
169
+ serializer SmartMessage::Serializer::JSON.new
170
+ end
171
+
172
+ def self.process(message_header, message_payload)
173
+ order_data = JSON.parse(message_payload)
174
+ order = new(order_data)
175
+ puts "Processing order #{order.order_id} for $#{order.amount}"
176
+ # Your business logic here
177
+ end
178
+ end
179
+
180
+ # Subscribe to messages (creates Redis subscription to "OrderMessage" channel)
181
+ OrderMessage.subscribe
182
+
183
+ # Publish messages (publishes to "OrderMessage" Redis channel)
184
+ order = OrderMessage.new(
185
+ order_id: "ORD-123",
186
+ customer_id: "CUST-456",
187
+ amount: 99.99
188
+ )
189
+ order.publish
190
+ ```
191
+
192
+ **Options:**
193
+ - `url` (String): Redis connection URL (default: 'redis://localhost:6379')
194
+ - `db` (Integer): Redis database number (default: 0)
195
+ - `auto_subscribe` (Boolean): Automatically start subscriber thread (default: true)
196
+ - `reconnect_attempts` (Integer): Number of reconnection attempts (default: 5)
197
+ - `reconnect_delay` (Integer): Delay between reconnection attempts in seconds (default: 1)
198
+ - `debug` (Boolean): Enable debug output (default: false)
199
+
200
+ **Channel Naming:**
201
+
202
+ The Redis transport uses the message class name as the Redis channel name. This provides automatic routing:
203
+
204
+ ```ruby
205
+ class UserMessage < SmartMessage::Base
206
+ # Messages published to/from Redis channel "UserMessage"
207
+ end
208
+
209
+ class AdminMessage < SmartMessage::Base
210
+ # Messages published to/from Redis channel "AdminMessage"
211
+ end
212
+
213
+ class OrderProcessing::PaymentMessage < SmartMessage::Base
214
+ # Messages published to/from Redis channel "OrderProcessing::PaymentMessage"
215
+ end
216
+ ```
217
+
218
+ **Connection Management:**
219
+
220
+ ```ruby
221
+ transport = SmartMessage::Transport.create(:redis, url: 'redis://localhost:6379')
222
+
223
+ # Check connection status
224
+ puts transport.connected? # => true/false
225
+
226
+ # Manual connection management
227
+ transport.connect
228
+ transport.disconnect
229
+
230
+ # The transport automatically reconnects on connection failures
231
+ ```
232
+
233
+ **Multi-Message Type Support:**
234
+
235
+ ```ruby
236
+ # Different message types can share the same Redis transport
237
+ redis_transport = SmartMessage::Transport.create(:redis,
238
+ url: 'redis://localhost:6379',
239
+ auto_subscribe: true
240
+ )
241
+
242
+ # Configure multiple message classes to use the same transport
243
+ [OrderMessage, PaymentMessage, ShippingMessage].each do |msg_class|
244
+ msg_class.config do
245
+ transport redis_transport
246
+ serializer SmartMessage::Serializer::JSON.new
247
+ end
248
+
249
+ # Subscribe to each message type (creates separate Redis subscriptions)
250
+ msg_class.subscribe
251
+ end
252
+
253
+ # Publishing to any message type routes to its specific Redis channel
254
+ OrderMessage.new(order_id: "123").publish # -> "OrderMessage" channel
255
+ PaymentMessage.new(amount: 50.0).publish # -> "PaymentMessage" channel
256
+ ShippingMessage.new(tracking: "ABC").publish # -> "ShippingMessage" channel
257
+ ```
258
+
259
+ **Error Handling and Resilience:**
260
+
261
+ The Redis transport includes built-in error handling:
262
+
263
+ ```ruby
264
+ # Automatic reconnection on connection failures
265
+ transport = SmartMessage::Transport.create(:redis,
266
+ url: 'redis://localhost:6379',
267
+ reconnect_attempts: 5, # Try 5 times to reconnect
268
+ reconnect_delay: 2 # Wait 2 seconds between attempts
269
+ )
270
+
271
+ # Connection failures during publishing will trigger automatic retry
272
+ # If all reconnection attempts fail, the original error is raised
273
+ ```
274
+
275
+ **Production Deployment:**
276
+
277
+ ```ruby
278
+ # Production Redis configuration
279
+ class ProductionMessage < SmartMessage::Base
280
+ config do
281
+ transport SmartMessage::Transport.create(:redis,
282
+ url: ENV['REDIS_URL'] || 'redis://localhost:6379',
283
+ db: ENV['REDIS_DB']&.to_i || 0,
284
+ auto_subscribe: true,
285
+ reconnect_attempts: 10,
286
+ reconnect_delay: 5
287
+ )
288
+ serializer SmartMessage::Serializer::JSON.new
289
+ logger Logger.new(STDOUT)
290
+ end
291
+ end
292
+ ```
293
+
294
+ **Testing with Redis:**
295
+
296
+ ```ruby
297
+ # Test configuration (using separate Redis database)
298
+ class TestMessage < SmartMessage::Base
299
+ config do
300
+ transport SmartMessage::Transport.create(:redis,
301
+ url: 'redis://localhost:6379',
302
+ db: 15, # Use separate database for tests
303
+ auto_subscribe: true
304
+ )
305
+ serializer SmartMessage::Serializer::JSON.new
306
+ end
307
+ end
308
+
309
+ # In your test setup
310
+ def setup
311
+ # Clear test database
312
+ Redis.new(url: 'redis://localhost:6379', db: 15).flushdb
313
+ end
314
+ ```
315
+
128
316
  ## Transport Interface
129
317
 
130
318
  All transports must implement the `SmartMessage::Transport::Base` interface:
@@ -188,19 +376,24 @@ transport.receive(message_header, message_payload) # protected method
188
376
  Register custom transports for easy creation:
189
377
 
190
378
  ```ruby
191
- # Register a transport class
192
- SmartMessage::Transport.register(:redis, RedisTransport)
379
+ # Register custom transport classes
193
380
  SmartMessage::Transport.register(:kafka, KafkaTransport)
381
+ SmartMessage::Transport.register(:webhook, WebhookTransport)
194
382
 
195
- # List all registered transports
383
+ # List all registered transports (includes built-ins)
196
384
  puts SmartMessage::Transport.available
197
- # => [:stdout, :memory, :redis, :kafka]
385
+ # => [:stdout, :memory, :redis, :kafka, :webhook]
198
386
 
199
- # Create instances
387
+ # Create instances of built-in transports
200
388
  redis_transport = SmartMessage::Transport.create(:redis,
201
389
  url: "redis://localhost:6379"
202
390
  )
203
391
 
392
+ memory_transport = SmartMessage::Transport.create(:memory,
393
+ auto_process: true
394
+ )
395
+
396
+ # Create instances of custom transports
204
397
  kafka_transport = SmartMessage::Transport.create(:kafka,
205
398
  servers: ["localhost:9092"]
206
399
  )
@@ -311,12 +504,13 @@ SmartMessage::Transport.create(:memory,
311
504
  max_messages: 1000
312
505
  )
313
506
 
314
- # Hypothetical Redis specific
507
+ # Redis specific
315
508
  SmartMessage::Transport.create(:redis,
316
509
  url: "redis://localhost:6379",
317
510
  db: 1,
318
- namespace: "messages",
319
- ttl: 3600
511
+ auto_subscribe: true,
512
+ reconnect_attempts: 5,
513
+ reconnect_delay: 2
320
514
  )
321
515
  ```
322
516