v1.3.0 "Ōtō" - Response Acknowledgment
Release Date: July 25, 2025
Code Name: "Ōtō" (応答 - Response/Acknowledgment)
Type: Minor Release
🎯 Overview
Version 1.3.0 introduces comprehensive response acknowledgment across all WebSocket operations, replacing empty Task returns with ActionResult responses. This release also modernizes streaming operations by adopting ChannelReader
🛠️ Technical Details
ActionResult Response Pattern
All WebSocket event handlers now return ActionResult instead of empty Task, providing:
- Acknowledgment Feedback: Clients can confirm successful operation completion
- Error Reporting: Detailed error information when operations fail
- Operation Status: Clear success/failure indication with descriptive messages
Channel-Based Streaming
Streaming operations have been upgraded from IAsyncEnumerable
- Better Performance: More efficient memory usage and throughput
- Improved Backpressure: Built-in flow control mechanisms
- Resource Management: Better cleanup and disposal patterns
🔄 Changes
Response Acknowledgment
- Event Handlers: All stream-related events updated to expect ActionResult responses
- Interface Updates:
IJiroClient
,IJiroHubServer
, andJiroClientBase
aligned with new pattern
Streaming Infrastructure
- ChannelReader Integration: All streaming methods now use
ChannelReader<T>
instead ofIAsyncEnumerable<T>
- Performance Optimization: Reduced memory allocation and improved throughput
- Enhanced Control: Better flow control and cancellation support
Enhanced Event Coverage
- RemoveSessionRequested: Added event handler with proper RemoveSessionRequest parameter
- UpdateSessionRequested: Added event handler returning ActionResult for acknowledgment
- MachineInfoRequested: New event for machine information retrieval from clients
- Complete Coverage: All hub client methods now have corresponding event implementations
Documentation Enhancements
- XML Documentation: Added comprehensive parameter and return value documentation
- ActionResult Details: Detailed documentation for the new response model
- Usage Examples: Updated examples reflecting the new patterns
💻 Usage Examples
ActionResult Response Pattern implementation
// Event handler now returns ActionResult
LogsStreamRequested += async (request) =>
{
try
{
await ProcessLogsStream(request);
return new ActionResult
{
IsSuccess = true,
Message = "Logs stream processed successfully"
};
}
catch (Exception ex)
{
return new ActionResult
{
IsSuccess = false,
Message = "Failed to process logs stream",
Errors = new[] { ex.Message }
};
}
};
Channel-Based Streaming implementation
// Using ChannelReader for streaming (fire-and-forget)
public async Task ReceiveLogsStreamAsync(string requestId, ChannelReader<LogEntry> stream)
{
try
{
await foreach (var logEntry in stream.ReadAllAsync())
{
await ProcessLogEntry(logEntry);
}
logger.LogInformation("Stream {RequestId} processed successfully", requestId);
}
catch (Exception ex)
{
logger.LogError(ex, "Failed to process stream {RequestId}", requestId);
}
}
Enhanced Event Handling
// Session management with proper request objects
RemoveSessionRequested += async (removeRequest) =>
{
var result = await sessionManager.RemoveSessionAsync(removeRequest);
return new ActionResult
{
IsSuccess = result.Success,
Message = result.Message
};
};
UpdateSessionRequested += async (updateRequest) =>
{
var result = await sessionManager.UpdateSessionAsync(updateRequest);
return new ActionResult
{
IsSuccess = result.Success,
Message = result.Message
};
};
// New machine information event
MachineInfoRequested += async (infoRequest) =>
{
var machineInfo = await systemService.GetMachineInfoAsync(infoRequest);
return new MachineInfoResponse
{
RequestId = infoRequest.RequestId,
Data = machineInfo
};
};
🚀 Deployment
Breaking Changes
- Stream Parameters: Streaming methods now expect
ChannelReader<T>
instead ofIAsyncEnumerable<T>
- Event Returns: Stream request events now return
Task<ActionResult>
for acknowledgment - Session Events:
RemoveSessionRequested
now takesRemoveSessionRequest
instead ofstring
- New Events: Implementations must handle the new
MachineInfoRequested
event
Migration Guide
// Before v1.3.0
public event Func<GetLogsRequest, Task> LogsStreamRequested;
public event Func<string, Task<ActionResult>> RemoveSessionRequested;
public async Task ReceiveLogsStreamAsync(string requestId, IAsyncEnumerable<LogEntry> stream) { }
// After v1.3.0
public event Func<GetLogsRequest, Task<ActionResult>> LogsStreamRequested;
public event Func<RemoveSessionRequest, Task<ActionResult>> RemoveSessionRequested;
public event Func<MachineInfoRequest, Task<MachineInfoResponse>> MachineInfoRequested;
public async Task ReceiveLogsStreamAsync(string requestId, ChannelReader<LogEntry> stream)
{
// Process stream (fire-and-forget)
await ProcessStream(requestId, stream);
}
🔮 Future Considerations
- Distributed Tracing: ActionResult foundation enables future distributed tracing integration
- Performance Monitoring: Response patterns facilitate operation performance tracking
- Error Analytics: Structured error reporting enables better failure analysis
- Flow Control: Channel-based streaming prepares for advanced flow control features
Note: This release introduces breaking changes to streaming interfaces. Please review the migration guide and update your event handlers to return ActionResult responses. The new channel-based streaming provides significant performance improvements and better resource management.