smart_message 0.0.16 → 0.0.17

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b0f06621d7e381b6069aba0fad1c329b941349e95488bdf5d8d39fd66e1d0fd2
4
- data.tar.gz: d1ef64216d07f3e6005db87194590984004bf68f923c09bec93aadb889909cb1
3
+ metadata.gz: 31da3cbbad04e7c1c5c6c4957e9cbe19fd2b5ef3b4eb13079f6daa5056cf5f93
4
+ data.tar.gz: f418df55d5e4e40b8ad942eec2c553ae6f6275a85a1a1fe8063addcee8ddc2f7
5
5
  SHA512:
6
- metadata.gz: f06e42c967e586521659b24e132001a64e51d64541214b06c7d5fa7bf6bfc48782a13bec11ace183ae50ff93b3840a5344ea2c59f3b44f0227fe8162b5452c44
7
- data.tar.gz: bd2b874f6574600002a5b1cf845ca37076aef74f53fde34b7bae183af5c8978c5dd7c7fdb4d9f442014d7fb146371655e4f3092216e285fc7b0f5fba65dd254f
6
+ metadata.gz: 72876daadfbf2d4bc817ceaa0e41d5564e537a4baf71b36fb4042ed217c63802bf1500ff51bdcce9b19c8765ad9be2a7d8e6fbc288e937ec30a64334fa5e3d1f
7
+ data.tar.gz: e663de462e0221c88ca90352ef11861b99b7ed43b43a941899e67b9dfc584c68a1af9c2b86a5f09188fd2ee528308869eb92a267920bdf8fc52e197e30c1eb91
data/CHANGELOG.md CHANGED
@@ -7,6 +7,70 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.0.17] 2025-09-11
11
+
12
+ ### Enhanced
13
+ - **FileTransport Message Handling**: Simplified FileTransport publish method to only handle message objects
14
+ - **Architecture Clarification**: FileTransport now exclusively accepts SmartMessage objects with `_sm_header`
15
+ - **Message Processing**: Proper extraction of message class from `message._sm_header.message_class`
16
+ - **Serialization Flow**: Clean serialization pipeline using `encode_message(message)` before file operations
17
+ - **Code Quality**: Eliminated unnecessary backward compatibility code for raw string payloads
18
+ - **Demo Program Simplification**: Streamlined 06 demo with minimal message properties
19
+ - **Property Reduction**: DemoMessage now uses only `first_name` and `last_name` properties for clarity
20
+ - **Format Examples**: Three clear format demonstrations (Alice Johnson in :pretty, Bob Smith & Carol Williams in :jsonl, David Brown, Emma Davis & Frank Miller in :json)
21
+ - **Educational Value**: Simplified output makes format differences more apparent and easier to understand
22
+ - **Documentation Updates**: Updated usage examples and JQ query patterns to reflect simple property structure
23
+
24
+ ### Fixed
25
+ - **FileTransport Test Compatibility**: Removed invalid compatibility test for raw string publishing
26
+ - **Issue**: Test `test_publish_compatibility_method` was passing raw strings to FileTransport.publish
27
+ - **Architecture Decision**: FileTransport should only handle SmartMessage objects, not raw strings
28
+ - **Solution**: Removed the invalid test that conflicted with proper message object architecture
29
+ - **Impact**: Test suite now properly validates FileTransport's message-only publishing contract
30
+ - **StdoutTransport Architecture**: Simplified StdoutTransport to minimal subclass of FileTransport
31
+ - **Inheritance**: StdoutTransport now inherits all functionality from FileTransport with minimal 6-line implementation
32
+ - **Option Merging**: Fixed critical bug where `file_path: $stdout` always overwrote user-provided options
33
+ - **Solution**: Changed from `options.merge(defaults)` to `defaults.merge(options)` for proper option precedence
34
+ - **Flexibility**: StdoutTransport can now write to files when `file_path` option is provided, while defaulting to STDOUT
35
+ - **FileTransport Format Support**: Added comprehensive output formatting capabilities to FileTransport
36
+ - **Format Options**: Implemented `:json` (raw), `:jsonl` (JSON with newline), and `:pretty` (amazing_print formatting)
37
+ - **Pretty Printing**: Added amazing_print integration for `:pretty` format using serializer's `decode` method
38
+ - **Serializer Integration**: Pretty format uses transport's serializer to deserialize messages back to Ruby objects
39
+ - **Fallback Handling**: Graceful fallback to raw output when amazing_print is unavailable or deserialization fails
40
+ - **FileTransport IO Object Support**: Enhanced FileTransport to handle IO objects properly
41
+ - **IO Detection**: Added `respond_to?(:write)` checks to distinguish IO objects from file paths
42
+ - **Directory Operations**: Skip directory creation for IO objects in `ensure_directory_exists`
43
+ - **File Operations**: Return IO objects directly in `open_file_handle` instead of trying to open them
44
+ - **Compatibility**: Maintains full backward compatibility with string file paths
45
+
46
+ ### Fixed
47
+ - **StdoutTransport Option Precedence**: Fixed critical configuration bug preventing file output
48
+ - **Issue**: `super(options.merge(file_path: $stdout))` caused defaults to always override user options
49
+ - **Impact**: StdoutTransport could not write to files when `file_path` was provided
50
+ - **Fix**: Reversed merge order to `defaults.merge(options)` for proper option precedence
51
+ - **Result**: StdoutTransport now correctly respects user-provided file paths while defaulting to STDOUT
52
+ - **FileOperations Type Safety**: Enhanced type checking for file vs IO operations
53
+ - **Issue**: `File.dirname` called on IO objects caused "no implicit conversion" errors
54
+ - **Solution**: Added `respond_to?(:write)` checks throughout FileOperations module
55
+ - **Methods Fixed**: `ensure_directory_exists`, `open_file_handle`, and related file operations
56
+ - **Robustness**: FileTransport now handles both file paths and IO objects seamlessly
57
+
58
+ ### Added
59
+ - **Pretty Format Demo**: Enhanced STDOUT transport demo with comprehensive format examples
60
+ - **Demo Update**: `examples/memory/06_stdout_publish_only.rb` now demonstrates all three formats
61
+ - **Format Examples**: LogMessage (jsonl), MetricsMessage (json), and DebugMessage (pretty)
62
+ - **Complex Data**: DebugMessage showcases pretty formatting with nested data structures
63
+ - **Educational Value**: Clear documentation of format differences and use cases
64
+
65
+ ### Tests
66
+ - **Complete Test Suite**: All transport tests now pass without errors
67
+ - **Test Results**: 313 runs, 930 assertions, 0 failures, 0 errors, 27 skips
68
+ - **StdoutTransport Tests**: Fixed all TypeError issues related to IO object handling
69
+ - **FileTransport Integration**: Verified format support and IO object compatibility
70
+ - **Test Cleanup**: Removed invalid test that attempted to publish raw strings to FileTransport
71
+ - **Architecture Validation**: Test suite now properly validates message-only publishing contract
72
+ - **Regression Prevention**: Test coverage ensures option merging bug cannot reoccur
73
+
10
74
  ## [0.0.16] 2025-09-10
11
75
 
12
76
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- smart_message (0.0.16)
4
+ smart_message (0.0.17)
5
5
  activesupport
6
6
  async
7
7
  async-redis
@@ -30,7 +30,7 @@ GEM
30
30
  tzinfo (~> 2.0, >= 2.0.5)
31
31
  uri (>= 0.13.1)
32
32
  amazing_print (1.8.1)
33
- async (2.31.0)
33
+ async (2.32.0)
34
34
  console (~> 1.29)
35
35
  fiber-annotation
36
36
  io-event (~> 1.11)
@@ -47,10 +47,10 @@ GEM
47
47
  base64 (0.3.0)
48
48
  benchmark (0.4.1)
49
49
  bigdecimal (3.2.3)
50
- breaker_machines (0.4.0)
50
+ breaker_machines (0.5.0)
51
51
  activesupport (>= 7.2)
52
52
  concurrent-ruby (~> 1.3)
53
- state_machines (>= 0.50.0)
53
+ state_machines (>= 0.100.0)
54
54
  zeitwerk (~> 2.7)
55
55
  colorize (1.1.0)
56
56
  concurrent-ruby (1.3.5)
data/README.md CHANGED
@@ -667,28 +667,32 @@ OrderMessage.new(
667
667
 
668
668
  ### STDOUT Transport (Publish-Only)
669
669
 
670
- The STDOUT transport is designed for publish-only scenarios - perfect for debugging, logging, or integration with external systems.
670
+ The STDOUT transport is designed for publish-only scenarios - perfect for debugging, logging, or integration with external systems. Built as a minimal subclass of FileTransport, it inherits comprehensive formatting capabilities.
671
671
 
672
672
  ```ruby
673
673
  # Basic STDOUT output (publish-only)
674
674
  transport = SmartMessage::Transport::StdoutTransport.new
675
675
 
676
- # Pretty-printed format for human reading (default)
676
+ # JSON Lines format - one message per line (default)
677
+ transport = SmartMessage::Transport::StdoutTransport.new(format: :jsonl)
678
+
679
+ # Pretty-printed format with amazing_print for human reading
677
680
  transport = SmartMessage::Transport::StdoutTransport.new(format: :pretty)
678
681
 
679
- # JSON format for machine processing
682
+ # Compact JSON format without newlines
680
683
  transport = SmartMessage::Transport::StdoutTransport.new(format: :json)
681
684
 
682
685
  # Output to file instead of STDOUT
683
- transport = SmartMessage::Transport::StdoutTransport.new(output: "messages.log")
686
+ transport = SmartMessage::Transport::StdoutTransport.new(file_path: "messages.log")
684
687
  ```
685
688
 
686
689
  **Key Features:**
687
690
  - **Publish-only**: No message processing or loopback
688
691
  - **Subscription attempts are ignored** with warning logs
689
- - **Two formats**: `:pretty` for debugging, `:json` for integration
692
+ - **Three formats**: `:jsonl` (default), `:pretty` for debugging, `:json` for compact output
693
+ - **Flexible Output**: Defaults to STDOUT but can write to files when `file_path` specified
690
694
  - **Perfect for**: debugging, logging, piping to external tools
691
- - **Use cases**: `./app | jq`, `./app | fluentd`, development monitoring
695
+ - **Use cases**: `./app | jq '.first_name'`, `./app | fluentd`, development monitoring
692
696
 
693
697
  **For local message processing, use MemoryTransport instead:**
694
698
  ```ruby
@@ -0,0 +1,361 @@
1
+ # Transport Selection Guide
2
+
3
+ Choosing the right transport for your SmartMessage application is crucial for performance, reliability, and maintainability. This guide provides comprehensive information about each available transport and decision matrices to help you select the optimal transport configuration.
4
+
5
+ ## Available Transports
6
+
7
+ ### Memory Transport
8
+ **In-memory message storage for development and testing**
9
+
10
+ - **Type**: In-memory queue with optional auto-processing
11
+ - **Best For**: Unit testing, development, rapid prototyping, message inspection
12
+ - **Key Features**:
13
+ - No external dependencies
14
+ - Thread-safe operations
15
+ - Message inspection capabilities
16
+ - Configurable memory limits
17
+ - Fastest performance (~0.01ms latency)
18
+ - **Limitations**: Single-process only, no persistence, memory usage grows with volume
19
+ - **Use Cases**: Unit tests, development debugging, in-memory message queuing
20
+
21
+ ### Redis Transport
22
+ **Production-ready Redis pub/sub for distributed messaging**
23
+
24
+ - **Type**: Redis pub/sub with broadcast delivery
25
+ - **Best For**: Production messaging, microservices communication, real-time applications
26
+ - **Key Features**:
27
+ - Distributed messaging support
28
+ - Automatic reconnection handling
29
+ - High throughput (80K+ messages/second)
30
+ - Low latency (~1ms)
31
+ - Thread-based subscriber model
32
+ - **Limitations**: No message persistence, no pattern matching, all subscribers receive all messages
33
+ - **Use Cases**: Production systems, scalable architectures, service-to-service messaging
34
+
35
+ ### STDOUT Transport
36
+ **Console and file output with multiple formatting options**
37
+
38
+ - **Type**: Output-only transport with formatting capabilities
39
+ - **Best For**: Development debugging, application logging, message tracing, integration testing
40
+ - **Key Features**:
41
+ - Three output formats (`:pretty`, `:jsonl`, `:json`)
42
+ - Console or file output
43
+ - Optional loopback processing
44
+ - Human-readable pretty printing
45
+ - Thread-safe file operations
46
+ - **Limitations**: Not suitable for production messaging, single output destination
47
+ - **Use Cases**: Development debugging, structured logging, message flow tracing
48
+
49
+ ### File Transport
50
+ **Base class for file-based messaging**
51
+
52
+ - **Type**: Abstract base class for file-based transports
53
+ - **Best For**: Custom file-based transport implementations, message archiving
54
+ - **Key Features**:
55
+ - Automatic directory creation
56
+ - Thread-safe file operations
57
+ - Message serialization handling
58
+ - Extensible architecture for custom transports
59
+ - **Limitations**: Rarely used directly, requires custom implementation
60
+ - **Use Cases**: Custom transport development, message persistence, audit trails
61
+
62
+ ### Multi-Transport Publishing
63
+ **Simultaneous publishing to multiple transports**
64
+
65
+ - **Type**: Configuration pattern for publishing to multiple destinations
66
+ - **Best For**: High availability, migration scenarios, monitoring integration, redundancy
67
+ - **Key Features**:
68
+ - Publish to multiple transports with single `publish()` call
69
+ - Resilient to partial failures
70
+ - Sequential processing with error isolation
71
+ - Transport introspection methods
72
+ - **Limitations**: Sequential processing can impact performance, memory usage scales with transport count
73
+ - **Use Cases**: Critical message redundancy, gradual migration, operational monitoring
74
+
75
+ ## Transport Selection Matrix
76
+
77
+ ### By Development Phase
78
+
79
+ | Phase | Primary Transport | Secondary Transport | Use Case |
80
+ |-------|------------------|-------------------|----------|
81
+ | **Unit Testing** | Memory | - | Fast, isolated, inspectable |
82
+ | **Development** | STDOUT (pretty) | Memory (loopback) | Human-readable debugging |
83
+ | **Integration Testing** | STDOUT (jsonl) | Memory | Structured output, verification |
84
+ | **Staging** | Redis | STDOUT (file) | Production-like with logging |
85
+ | **Production** | Redis | Multi-transport | Scalable with redundancy |
86
+
87
+ ### By Use Case
88
+
89
+ | Use Case | Recommended Transport | Configuration | Rationale |
90
+ |----------|----------------------|---------------|-----------|
91
+ | **Unit Tests** | Memory | `auto_process: true` | No dependencies, fast, inspectable |
92
+ | **Development Debugging** | STDOUT | `format: :pretty, loopback: true` | Human-readable with local processing |
93
+ | **Application Logging** | STDOUT | `format: :jsonl, file_path: 'app.log'` | Structured logs for analysis |
94
+ | **Message Tracing** | STDOUT | `format: :json, file_path: '/tmp/trace.log'` | Compact format for debugging |
95
+ | **Production Messaging** | Redis | `url: ENV['REDIS_URL']` | Distributed, reliable, scalable |
96
+ | **Critical Messages** | Multi-transport | `[Redis, STDOUT(file), Redis(backup)]` | Redundancy and audit trail |
97
+ | **Migration Scenarios** | Multi-transport | `[OldTransport, NewTransport]` | Gradual transition |
98
+ | **Development→Production** | Environment-based | Switch based on `Rails.env` | Appropriate for each environment |
99
+
100
+ ### By Architecture Pattern
101
+
102
+ #### Single Application (Monolith)
103
+ ```ruby
104
+ # Development
105
+ transport: SmartMessage::Transport::StdoutTransport.new(format: :pretty)
106
+
107
+ # Production
108
+ transport: SmartMessage::Transport::RedisTransport.new(url: ENV['REDIS_URL'])
109
+ ```
110
+
111
+ #### Microservices Architecture
112
+ ```ruby
113
+ # High-availability critical messages
114
+ transport: [
115
+ SmartMessage::Transport::RedisTransport.new(url: primary_redis),
116
+ SmartMessage::Transport::RedisTransport.new(url: backup_redis),
117
+ SmartMessage::Transport::StdoutTransport.new(file_path: '/var/log/audit.log')
118
+ ]
119
+ ```
120
+
121
+ #### Event-Driven System
122
+ ```ruby
123
+ # Events with monitoring
124
+ transport: [
125
+ SmartMessage::Transport::RedisTransport.new(url: event_redis),
126
+ SmartMessage::Transport::StdoutTransport.new(
127
+ format: :jsonl,
128
+ file_path: '/var/log/events.log'
129
+ )
130
+ ]
131
+ ```
132
+
133
+ ## Decision Tree
134
+
135
+ ### Step 1: Environment Classification
136
+ ```
137
+ Are you in...?
138
+ ├── Unit Testing → Memory Transport
139
+ ├── Development → STDOUT Transport (pretty format)
140
+ ├── Integration Testing → STDOUT Transport (jsonl format)
141
+ └── Production → Continue to Step 2
142
+ ```
143
+
144
+ ### Step 2: Message Criticality (Production)
145
+ ```
146
+ How critical are your messages?
147
+ ├── Low criticality → Redis Transport (single)
148
+ ├── Medium criticality → Redis + STDOUT file logging
149
+ └── High criticality → Multi-transport (Redis primary + backup + audit)
150
+ ```
151
+
152
+ ### Step 3: Scale Requirements
153
+ ```
154
+ Expected message volume?
155
+ ├── Low (<1K/day) → Any transport suitable
156
+ ├── Medium (1K-100K/day) → Redis Transport recommended
157
+ └── High (>100K/day) → Redis Transport + performance tuning
158
+ ```
159
+
160
+ ### Step 4: Integration Requirements
161
+ ```
162
+ Need external integration?
163
+ ├── Log aggregation → STDOUT Transport (jsonl to file)
164
+ ├── Monitoring systems → Multi-transport (Redis + STDOUT)
165
+ ├── Audit requirements → Multi-transport with file logging
166
+ └── None → Single transport sufficient
167
+ ```
168
+
169
+ ## Configuration Examples
170
+
171
+ ### Environment-Based Configuration
172
+ ```ruby
173
+ class ApplicationMessage < SmartMessage::Base
174
+ transport case Rails.env
175
+ when 'test'
176
+ SmartMessage::Transport::MemoryTransport.new(auto_process: true)
177
+ when 'development'
178
+ SmartMessage::Transport::StdoutTransport.new(
179
+ format: :pretty,
180
+ loopback: true
181
+ )
182
+ when 'staging'
183
+ [
184
+ SmartMessage::Transport::RedisTransport.new(url: ENV['REDIS_URL']),
185
+ SmartMessage::Transport::StdoutTransport.new(
186
+ format: :jsonl,
187
+ file_path: '/var/log/staging.log'
188
+ )
189
+ ]
190
+ when 'production'
191
+ [
192
+ SmartMessage::Transport::RedisTransport.new(url: ENV['PRIMARY_REDIS_URL']),
193
+ SmartMessage::Transport::RedisTransport.new(url: ENV['BACKUP_REDIS_URL']),
194
+ SmartMessage::Transport::StdoutTransport.new(
195
+ format: :jsonl,
196
+ file_path: '/var/log/production.log'
197
+ )
198
+ ]
199
+ end
200
+ end
201
+ ```
202
+
203
+ ### Message-Type Based Selection
204
+ ```ruby
205
+ # High-volume, low-criticality events
206
+ class UserActivityMessage < SmartMessage::Base
207
+ transport SmartMessage::Transport::RedisTransport.new(url: ENV['REDIS_URL'])
208
+ end
209
+
210
+ # Critical business events
211
+ class PaymentProcessedMessage < SmartMessage::Base
212
+ transport [
213
+ SmartMessage::Transport::RedisTransport.new(url: ENV['PRIMARY_REDIS_URL']),
214
+ SmartMessage::Transport::RedisTransport.new(url: ENV['BACKUP_REDIS_URL']),
215
+ SmartMessage::Transport::StdoutTransport.new(
216
+ format: :jsonl,
217
+ file_path: '/var/log/payments.log'
218
+ )
219
+ ]
220
+ end
221
+
222
+ # Development/debugging messages
223
+ class DebugMessage < SmartMessage::Base
224
+ transport SmartMessage::Transport::StdoutTransport.new(
225
+ format: :pretty,
226
+ loopback: true
227
+ )
228
+ end
229
+ ```
230
+
231
+ ## Performance Considerations
232
+
233
+ ### Latency Comparison
234
+ | Transport | Typical Latency | Best Use |
235
+ |-----------|----------------|----------|
236
+ | Memory | ~0.01ms | Unit tests, development |
237
+ | STDOUT | ~1ms | Logging, debugging |
238
+ | Redis | ~1ms | Production messaging |
239
+ | Multi-transport | Sum of individual transports | Critical messages |
240
+
241
+ ### Throughput Comparison
242
+ | Transport | Throughput | Limiting Factor |
243
+ |-----------|------------|----------------|
244
+ | Memory | Highest | CPU and memory |
245
+ | STDOUT | Medium | I/O operations |
246
+ | Redis | High | Network and Redis performance |
247
+ | Multi-transport | Lowest individual transport | Sequential processing |
248
+
249
+ ### Resource Usage
250
+ | Transport | Memory Usage | External Dependencies | Setup Complexity |
251
+ |-----------|--------------|----------------------|------------------|
252
+ | Memory | Grows with volume | None | Minimal |
253
+ | STDOUT | Minimal | None | Minimal |
254
+ | Redis | Low | Redis server | Medium |
255
+ | File | Minimal | None | Minimal |
256
+
257
+ ## Migration Strategies
258
+
259
+ ### Development to Production
260
+ ```ruby
261
+ # Phase 1: Development (Memory/STDOUT)
262
+ transport: SmartMessage::Transport::MemoryTransport.new
263
+
264
+ # Phase 2: Integration Testing (STDOUT with file)
265
+ transport: SmartMessage::Transport::StdoutTransport.new(
266
+ format: :jsonl,
267
+ file_path: '/tmp/integration.log'
268
+ )
269
+
270
+ # Phase 3: Staging (Redis + logging)
271
+ transport: [
272
+ SmartMessage::Transport::RedisTransport.new(url: staging_redis),
273
+ SmartMessage::Transport::StdoutTransport.new(file_path: '/var/log/staging.log')
274
+ ]
275
+
276
+ # Phase 4: Production (Multi-transport)
277
+ transport: [
278
+ SmartMessage::Transport::RedisTransport.new(url: primary_redis),
279
+ SmartMessage::Transport::RedisTransport.new(url: backup_redis)
280
+ ]
281
+ ```
282
+
283
+ ### Transport Evolution
284
+ ```ruby
285
+ # Start simple
286
+ class MyMessage < SmartMessage::Base
287
+ transport SmartMessage::Transport::MemoryTransport.new
288
+ end
289
+
290
+ # Add logging
291
+ class MyMessage < SmartMessage::Base
292
+ transport SmartMessage::Transport::StdoutTransport.new(format: :jsonl)
293
+ end
294
+
295
+ # Scale to production
296
+ class MyMessage < SmartMessage::Base
297
+ transport SmartMessage::Transport::RedisTransport.new(url: ENV['REDIS_URL'])
298
+ end
299
+
300
+ # Add redundancy
301
+ class MyMessage < SmartMessage::Base
302
+ transport [
303
+ SmartMessage::Transport::RedisTransport.new(url: ENV['PRIMARY_REDIS']),
304
+ SmartMessage::Transport::RedisTransport.new(url: ENV['BACKUP_REDIS'])
305
+ ]
306
+ end
307
+ ```
308
+
309
+ ## Best Practices
310
+
311
+ ### General Guidelines
312
+ 1. **Start Simple**: Begin with Memory/STDOUT transports in development
313
+ 2. **Match Environment**: Use appropriate transports for each environment
314
+ 3. **Consider Criticality**: More critical messages need more redundant transports
315
+ 4. **Monitor Performance**: Track latency and throughput in production
316
+ 5. **Plan Migration**: Design transport evolution from development to production
317
+
318
+ ### Transport-Specific
319
+ - **Memory**: Use in tests and development only, set reasonable message limits
320
+ - **STDOUT**: Use `:pretty` for development, `:jsonl` for structured logging
321
+ - **Redis**: Configure proper connection pooling and reconnection settings
322
+ - **Multi-transport**: Limit to 2-4 transports, order by speed/criticality
323
+
324
+ ### Environment Configuration
325
+ - **Development**: Readable formats, loopback enabled for testing
326
+ - **Testing**: Fast, isolated transports with deterministic behavior
327
+ - **Staging**: Production-like configuration with additional logging
328
+ - **Production**: Redundant, monitored, with proper error handling
329
+
330
+ ## Troubleshooting
331
+
332
+ ### Common Issues
333
+
334
+ **Slow message publishing**
335
+ - Check multi-transport ordering (put fastest first)
336
+ - Verify Redis connection health
337
+ - Monitor file I/O performance
338
+
339
+ **Messages not appearing**
340
+ - Verify transport configuration matches environment
341
+ - Check Redis connectivity and permissions
342
+ - Ensure file paths are writable
343
+
344
+ **Memory issues**
345
+ - Set limits on Memory transport
346
+ - Monitor multi-transport memory usage
347
+ - Check for message accumulation in development
348
+
349
+ **Test failures**
350
+ - Use Memory transport for predictable test behavior
351
+ - Clear messages between tests
352
+ - Mock external transport dependencies
353
+
354
+ ## Related Documentation
355
+
356
+ - [Multi-Transport Publishing](../transports/multi-transport.md) - Detailed multi-transport patterns
357
+ - [Memory Transport](../transports/memory-transport.md) - Development and testing transport
358
+ - [Redis Transport](../transports/redis-transport.md) - Production messaging transport
359
+ - [STDOUT Transport](../transports/stdout-transport.md) - Output and logging transport
360
+ - [File Transport](../transports/file-transport.md) - Base class for file-based transports
361
+ - [Transport Overview](../reference/transports.md) - Technical transport reference
@@ -33,29 +33,36 @@ message.publish # ✅ Publishes to all three transports
33
33
 
34
34
  ### STDOUT Transport
35
35
 
36
- **Publish-only transport** perfect for debugging, logging, and integration with external systems.
36
+ **Publish-only transport** perfect for debugging, logging, and integration with external systems. Built as a minimal subclass of FileTransport, inheriting comprehensive formatting and IO handling capabilities.
37
37
 
38
38
  **Features:**
39
39
  - **Publish-only**: No message processing or loopback capability
40
- - Outputs messages to console or file in pretty-print or JSON formats
40
+ - **Three output formats**: `:jsonl` (default), `:pretty` (amazing_print), `:json` (compact)
41
+ - **Flexible output**: Defaults to STDOUT but can write to files
42
+ - **Smart IO handling**: Automatically handles both IO objects and file paths
41
43
  - Subscription attempts are ignored with warning logs
42
44
  - Perfect for piping to external tools and log aggregators
43
45
  - No external dependencies
44
46
 
47
+ **📚 See [STDOUT Transport Documentation](../transports/stdout-transport.md) for comprehensive usage examples.**
48
+
45
49
  **Usage:**
46
50
 
47
51
  ```ruby
48
- # Basic STDOUT output (publish-only)
52
+ # Basic STDOUT output with default JSONL format
49
53
  transport = SmartMessage::Transport::StdoutTransport.new
50
54
 
51
- # Pretty-printed format for human reading (default)
55
+ # JSON Lines format - one message per line (default)
56
+ transport = SmartMessage::Transport::StdoutTransport.new(format: :jsonl)
57
+
58
+ # Pretty-printed format with amazing_print for debugging
52
59
  transport = SmartMessage::Transport::StdoutTransport.new(format: :pretty)
53
60
 
54
- # JSON format for machine processing
61
+ # Compact JSON format without newlines
55
62
  transport = SmartMessage::Transport::StdoutTransport.new(format: :json)
56
63
 
57
- # Output to file instead of console
58
- transport = SmartMessage::Transport::StdoutTransport.new(output: "messages.log")
64
+ # Output to file instead of STDOUT
65
+ transport = SmartMessage::Transport::StdoutTransport.new(file_path: "messages.log")
59
66
 
60
67
  # Configure in message class
61
68
  class LogMessage < SmartMessage::Base
@@ -65,25 +72,42 @@ class LogMessage < SmartMessage::Base
65
72
  config do
66
73
  transport SmartMessage::Transport::StdoutTransport.new(
67
74
  format: :json,
68
- output: "app.log"
75
+ file_path: "app.log"
69
76
  )
70
77
  end
71
78
  end
72
79
  ```
73
80
 
74
81
  **Options:**
75
- - `format` (Symbol): Output format - `:pretty` for debugging, `:json` for integration (default: `:pretty`)
76
- - `output` (String|IO): Output destination - filename string or IO object (default: `$stdout`)
82
+ - `format` (Symbol): Output format - `:jsonl` (default), `:pretty`, `:json`
83
+ - `file_path` (String|IO): Output destination - filename string or IO object (default: `$stdout`)
84
+ - All FileTransport options are inherited and available
77
85
 
78
86
  **Important:** For local message processing during development, use **MemoryTransport** instead.
79
87
 
80
- **Example Output:**
88
+ **Format Examples:**
89
+
90
+ **JSONL Format (default):**
91
+ ```json
92
+ {"_sm_header":{"uuid":"abc-123","message_class":"DemoMessage"},"first_name":"Alice","last_name":"Johnson"}
93
+ {"_sm_header":{"uuid":"def-456","message_class":"DemoMessage"},"first_name":"Bob","last_name":"Smith"}
81
94
  ```
82
- ===================================================
83
- == SmartMessage Published via STDOUT Transport
84
- == Header: #<SmartMessage::Header:0x... @uuid="abc-123", @message_class="MyMessage", ...>
85
- == Payload: {"user_id":123,"action":"login","timestamp":"2025-08-17T10:30:00Z"}
86
- ===================================================
95
+
96
+ **Pretty Format:**
97
+ ```ruby
98
+ {
99
+ "_sm_header" => {
100
+ "uuid" => "abc-123",
101
+ "message_class" => "DemoMessage"
102
+ },
103
+ "first_name" => "Alice",
104
+ "last_name" => "Johnson"
105
+ }
106
+ ```
107
+
108
+ **JSON Format:**
109
+ ```json
110
+ {"_sm_header":{"uuid":"abc-123"},"first_name":"Alice"}{"_sm_header":{"uuid":"def-456"},"first_name":"Bob"}
87
111
  ```
88
112
 
89
113
  ### Memory Transport
@@ -517,8 +541,8 @@ Each transport may have specific options:
517
541
  ```ruby
518
542
  # STDOUT specific (publish-only)
519
543
  SmartMessage::Transport::StdoutTransport.new(
520
- format: :json,
521
- output: "/var/log/messages.log"
544
+ format: :jsonl, # :jsonl (default), :pretty, :json
545
+ file_path: "/var/log/messages.log"
522
546
  )
523
547
 
524
548
  # Memory specific