This commit is contained in:
Oarkflow
2025-08-02 16:17:20 +05:45
parent ffbf9f99df
commit 271beed429
5 changed files with 212 additions and 113 deletions

View File

@@ -52,14 +52,14 @@ type Config struct {
BufferPoolSize int
}
// DefaultConfig returns default configuration
// DefaultConfig returns default configuration with NO timeouts for persistent connections
func DefaultConfig() *Config {
return &Config{
MaxMessageSize: MaxMessageSize,
MaxHeaderSize: MaxHeaderSize,
MaxQueueLength: MaxQueueLength,
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
ReadTimeout: 0, // NO read timeout for persistent broker-consumer connections
WriteTimeout: 0, // NO write timeout for persistent broker-consumer connections
EnableCompression: false,
BufferPoolSize: 1000,
}
@@ -252,7 +252,7 @@ func (c *Codec) SendMessage(ctx context.Context, conn net.Conn, msg *Message) er
return c.sendRawMessage(ctx, conn, msg)
}
// sendRawMessage handles the actual sending of a message or fragment
// sendRawMessage handles the actual sending of a message or fragment WITHOUT timeouts
func (c *Codec) sendRawMessage(ctx context.Context, conn net.Conn, msg *Message) error {
// Serialize message
data, err := msg.Serialize()
@@ -283,17 +283,21 @@ func (c *Codec) sendRawMessage(ctx context.Context, conn net.Conn, msg *Message)
binary.BigEndian.PutUint32(buffer.B[:4], uint32(len(data)))
copy(buffer.B[4:], data)
// Set timeout
deadline := time.Now().Add(c.config.WriteTimeout)
if ctxDeadline, ok := ctx.Deadline(); ok && ctxDeadline.Before(deadline) {
deadline = ctxDeadline
}
// CRITICAL: DO NOT set any write deadlines for broker-consumer connections
// These connections must remain open indefinitely for persistent communication
// Only set timeout if explicitly configured AND not zero (for backward compatibility)
if c.config.WriteTimeout > 0 {
deadline := time.Now().Add(c.config.WriteTimeout)
if ctxDeadline, ok := ctx.Deadline(); ok && ctxDeadline.Before(deadline) {
deadline = ctxDeadline
}
if err := conn.SetWriteDeadline(deadline); err != nil {
c.incrementErrors()
return fmt.Errorf("failed to set write deadline: %w", err)
if err := conn.SetWriteDeadline(deadline); err != nil {
c.incrementErrors()
return fmt.Errorf("failed to set write deadline: %w", err)
}
defer conn.SetWriteDeadline(time.Time{})
}
defer conn.SetWriteDeadline(time.Time{})
// Write with buffering
writer := bufio.NewWriter(conn)
@@ -318,7 +322,7 @@ func (c *Codec) sendRawMessage(ctx context.Context, conn net.Conn, msg *Message)
return nil
}
// ReadMessage reads a message with proper error handling and timeouts
// ReadMessage reads a message WITHOUT timeouts for persistent broker-consumer connections
func (c *Codec) ReadMessage(ctx context.Context, conn net.Conn) (*Message, error) {
// Check context cancellation before proceeding
if err := ctx.Err(); err != nil {
@@ -326,24 +330,22 @@ func (c *Codec) ReadMessage(ctx context.Context, conn net.Conn) (*Message, error
return nil, fmt.Errorf("context ended before read: %w", err)
}
// Check context cancellation before proceeding
if err := ctx.Err(); err != nil {
c.incrementErrors()
return nil, fmt.Errorf("context ended before read: %w", err)
}
// CRITICAL: DO NOT set any read deadlines for broker-consumer connections
// These connections must remain open indefinitely for persistent communication
// Only set timeout if explicitly configured AND not zero (for backward compatibility)
if c.config.ReadTimeout > 0 {
deadline := time.Now().Add(c.config.ReadTimeout)
if ctxDeadline, ok := ctx.Deadline(); ok && ctxDeadline.Before(deadline) {
deadline = ctxDeadline
}
// Set timeout
deadline := time.Now().Add(c.config.ReadTimeout)
if ctxDeadline, ok := ctx.Deadline(); ok && ctxDeadline.Before(deadline) {
deadline = ctxDeadline
if err := conn.SetReadDeadline(deadline); err != nil {
c.incrementErrors()
return nil, fmt.Errorf("failed to set read deadline: %w", err)
}
defer conn.SetReadDeadline(time.Time{})
}
if err := conn.SetReadDeadline(deadline); err != nil {
c.incrementErrors()
return nil, fmt.Errorf("failed to set read deadline: %w", err)
}
defer conn.SetReadDeadline(time.Time{})
// Read length prefix
lengthBytes := make([]byte, 4)
if _, err := io.ReadFull(conn, lengthBytes); err != nil {