Skip to content

v2.0.0

Choose a tag to compare

@Cartisim Cartisim released this 21 Jul 00:37
· 58 commits to main since this release

ConnectionManagerKit v2.0.0 Release Notes

🎉 Major Release - Generic Type Support

ConnectionManagerKit 2.0.0 introduces generic type support for enhanced type safety and flexibility. This is a breaking change that improves the API's robustness and enables custom data types.

Release Date: July 21, 2025
Minimum Requirements: Swift 6.0+, iOS 17.0+, macOS 14.0+, tvOS 17.0+, watchOS 10.0+, Linux


🚀 What's New

✨ Generic Type Support

  • Type-Safe Connections: ConnectionManager and ConnectionListener now support custom inbound and outbound types
  • Associated Types: Delegate protocols use associated types for compile-time type safety
  • Flexible Data Handling: Support for custom data types beyond ByteBuffer
  • End-to-End Type Safety: Complete generic type system from client to server

🔒 Enhanced Type Safety

  • Compile-Time Validation: Type mismatches are caught at compile time
  • Type-Safe Delegates: Delegate methods enforce correct generic types
  • Explicit Type Parameters: Clear indication of data types being used
  • Generic Context Objects: All context structs support custom types

🛠️ Improved API Design

  • Type-Safe Delegate Setting: setDelegate() method ensures type compatibility
  • Better Error Handling: More specific error messages for type mismatches
  • Enhanced Documentation: Comprehensive examples and migration guides
  • Convenience Methods: Easy-to-use factory methods for common cases

⚠️ Breaking Changes

1. ConnectionManager Initialization

Before (v1.x):

let manager = ConnectionManager()

After (v2.0.0):

// For ByteBuffer (most common case)
let manager = ConnectionManager<ByteBuffer, ByteBuffer>()

// For custom types
let customManager = ConnectionManager<MyInboundType, MyOutboundType>()

2. ConnectionListener Initialization

Before (v1.x):

let listener = ConnectionListener()

After (v2.0.0):

// For ByteBuffer (most common case)
let listener = ConnectionListener<ByteBuffer, ByteBuffer>()

// Using convenience method
let listener = ConnectionListener.byteBuffer()

// For custom types
let customListener = ConnectionListener<MyInboundType, MyOutboundType>()

3. Delegate Protocol Updates

Before (v1.x):

class MyDelegate: ConnectionManagerDelegate {
    func deliverChannel(_ channel: NIOAsyncChannel<ByteBuffer, ByteBuffer>, 
                       manager: ConnectionManager, 
                       cacheKey: String) async {
        // ...
    }
}

After (v2.0.0):

class MyDelegate: ConnectionManagerDelegate {
    // Define associated types
    typealias Inbound = ByteBuffer
    typealias Outbound = ByteBuffer
    
    func deliverChannel(_ channel: NIOAsyncChannel<ByteBuffer, ByteBuffer>, 
                       manager: ConnectionManager<ByteBuffer, ByteBuffer>, 
                       cacheKey: String) async {
        // ...
    }
}

4. Delegate Assignment

Before (v1.x):

manager.delegate = myDelegate

After (v2.0.0):

// Type-safe delegate setting
manager.setDelegate(myDelegate)

🔧 Migration Guide

Quick Migration Steps

  1. Update ConnectionManager Instantiations

    // Replace all instances of:
    ConnectionManager()
    
    // With:
    ConnectionManager<ByteBuffer, ByteBuffer>()
  2. Update ConnectionListener Instantiations

    // Replace all instances of:
    ConnectionListener()
    
    // With:
    ConnectionListener<ByteBuffer, ByteBuffer>()
    
    // Or use the convenience method:
    ConnectionListener.byteBuffer()
  3. Add Associated Types to Delegates

    class MyDelegate: ConnectionManagerDelegate {
        typealias Inbound = ByteBuffer
        typealias Outbound = ByteBuffer
        // ... rest of implementation
    }
  4. Update Delegate Method Signatures

    // Update manager parameter type:
    func deliverChannel(_ channel: NIOAsyncChannel<ByteBuffer, ByteBuffer>, 
                       manager: ConnectionManager<ByteBuffer, ByteBuffer>, 
                       cacheKey: String) async
  5. Use Type-Safe Delegate Setting

    // Replace:
    manager.delegate = myDelegate
    
    // With:
    manager.setDelegate(myDelegate)

Migration Checklist

  • Update all ConnectionManager() instantiations to ConnectionManager<ByteBuffer, ByteBuffer>()
  • Update all ConnectionListener() instantiations to ConnectionListener<ByteBuffer, ByteBuffer>()
  • Add associated types to delegate classes
  • Update delegate method signatures with proper generic types
  • Replace direct delegate assignment with setDelegate() method
  • Test all connection scenarios

🎯 New Features

Custom Data Type Support

// Define custom types
struct MyMessage: Sendable {
    let id: String
    let data: Data
}

// Use with ConnectionManager
let manager = ConnectionManager<MyMessage, MyMessage>()

// Use with ConnectionListener
let listener = ConnectionListener<MyMessage, MyMessage>()

Type-Safe Delegate Pattern

class MyCustomDelegate: ConnectionManagerDelegate {
    typealias Inbound = MyMessage
    typealias Outbound = MyMessage
    
    func deliverChannel(_ channel: NIOAsyncChannel<MyMessage, MyMessage>, 
                       manager: ConnectionManager<MyMessage, MyMessage>, 
                       cacheKey: String) async {
        // Type-safe implementation
    }
}

Convenience Methods

// Easy ByteBuffer initialization
let manager = ConnectionManager.byteBuffer()
let listener = ConnectionListener.byteBuffer()

Enhanced Error Handling

  • Better error messages for type mismatches
  • Compile-time validation of delegate types
  • Clear guidance for migration issues

🔧 Technical Improvements

Internal Changes

  • Generic Parameter Support: Full generic type system integration
  • Type Erasure Handling: Proper handling of existential types
  • Delegate Type Safety: Compile-time validation of delegate compatibility
  • Memory Management: Improved weak reference handling with generics

Performance Enhancements

  • Type-Safe Caching: Generic connection cache with type safety
  • Optimized Delegates: Reduced runtime type checking
  • Better Compilation: More efficient generic code generation

Test Improvements

  • Faster Test Execution: Tests complete in ~10 seconds instead of 127+ seconds
  • Better Error Handling: Tests properly handle expected connection failures
  • Type Safety: All tests use proper generic types

📚 Documentation Updates

New Documentation

  • Migration Guide: Step-by-step migration instructions
  • Generic API Examples: Comprehensive examples with custom types
  • Type Safety Guide: Best practices for type-safe networking
  • Breaking Changes: Detailed explanation of all changes

Updated Documentation

  • Getting Started: Updated with generic API examples
  • Basic Usage: All examples use new generic syntax
  • API Reference: Complete documentation of new generic types
  • README: Migration guide and updated installation instructions

🧪 Testing

Test Coverage

  • 16 tests passing with new generic API
  • Type safety tests for generic parameters
  • Migration tests for backward compatibility scenarios
  • Performance tests for generic implementations

Test Improvements

  • Generic Test Utilities: Type-safe test helpers
  • Mock Objects: Updated mocks for generic types
  • Integration Tests: End-to-end testing with generics
  • Faster Execution: Reduced test timeouts and improved performance

🚀 Getting Started with v2.0.0

Basic Setup

import ConnectionManagerKit

// Create manager with explicit types
let manager = ConnectionManager<ByteBuffer, ByteBuffer>()

// Or use convenience method
let manager = ConnectionManager.byteBuffer()

// Set up type-safe delegate
class MyDelegate: ConnectionManagerDelegate {
    typealias Inbound = ByteBuffer
    typealias Outbound = ByteBuffer
    
    func retrieveChannelHandlers() -> [ChannelHandler] { [] }
    
    func deliverChannel(_ channel: NIOAsyncChannel<ByteBuffer, ByteBuffer>, 
                       manager: ConnectionManager<ByteBuffer, ByteBuffer>, 
                       cacheKey: String) async {
        // Implementation
    }
}

// Use type-safe delegate setting
manager.setDelegate(MyDelegate())

Server Setup

// Create listener with explicit types
let listener = ConnectionListener<ByteBuffer, ByteBuffer>()

// Or use convenience method
let listener = ConnectionListener.byteBuffer()

// Set up server
let config = try await listener.resolveAddress(
    .init(group: MultiThreadedEventLoopGroup.singleton, host: "0.0.0.0", port: 8080)
)

try await listener.listen(
    address: config.address!,
    configuration: config,
    delegate: connectionDelegate,
    listenerDelegate: listenerDelegate
)

Custom Types Example

// Define custom message types
struct ChatMessage: Sendable {
    let sender: String
    let content: String
    let timestamp: Date
}

// Create manager for custom types
let chatManager = ConnectionManager<ChatMessage, ChatMessage>()

// Create listener for custom types
let chatListener = ConnectionListener<ChatMessage, ChatMessage>()

// Implement type-safe delegate
class ChatDelegate: ConnectionManagerDelegate {
    typealias Inbound = ChatMessage
    typealias Outbound = ChatMessage
    
    func deliverChannel(_ channel: NIOAsyncChannel<ChatMessage, ChatMessage>, 
                       manager: ConnectionManager<ChatMessage, ChatMessage>, 
                       cacheKey: String) async {
        // Handle chat messages
    }
}

🔮 Future Roadmap

Planned Features

  • Protocol Buffers Support: Native protobuf integration
  • GraphQL Support: GraphQL over WebSocket
  • Advanced Caching: Redis-backed connection caching
  • Metrics Integration: Prometheus metrics support

Performance Goals

  • Zero-Copy Operations: Optimized data transfer
  • Connection Pooling: Advanced connection management
  • Load Balancing: Built-in load balancing support

🤝 Community

Contributing

We welcome contributions! Please see our Contributing Guidelines for details.

Support

Related Projects


📋 Changelog

Added

  • Generic type support for ConnectionManager
  • Generic type support for ConnectionListener
  • Associated types in delegate protocols
  • Type-safe setDelegate() method
  • Convenience methods byteBuffer() for common use cases
  • Comprehensive migration guide
  • Enhanced error handling for type mismatches
  • Generic connection cache implementation
  • Generic context structs (ChannelContext, WriterContext, StreamContext)

Changed

  • ConnectionManager now requires explicit generic parameters
  • ConnectionListener now requires explicit generic parameters
  • Delegate protocols use associated types
  • Delegate assignment requires type-safe method
  • All examples updated to use generic syntax
  • Test performance improved (10 seconds vs 127+ seconds)
  • Better handling of expected connection failures in tests

Removed

  • Non-generic ConnectionManager constructor
  • Non-generic ConnectionListener constructor
  • Direct delegate property assignment
  • Legacy delegate method signatures

Fixed

  • Type safety issues with delegate patterns
  • Memory management with generic types
  • Compilation errors with existential types
  • Documentation inconsistencies
  • Test timeouts and performance issues
  • Generic parameter shadowing in protocol extensions

🎊 Thank You

Thank you to all contributors, users, and the Swift community for making this release possible. The generic type support in v2.0.0 represents a significant step forward in type safety and API design.

Built with ❤️ by the NeedleTails Team


For detailed migration assistance, please refer to the Migration Guide in our README.