feat: add protobuf message compression and decompression for Redis; refactor product fetching logic
This commit is contained in:
		@@ -1,9 +1,17 @@
 | 
			
		||||
package redis
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"compress/flate"
 | 
			
		||||
	"compress/zlib"
 | 
			
		||||
	"context"
 | 
			
		||||
	"github.com/redis/rueidis"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/golang/protobuf/proto"
 | 
			
		||||
	"github.com/redis/rueidis"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var Client *rueidis.Client
 | 
			
		||||
@@ -35,3 +43,90 @@ func CloseClient() {
 | 
			
		||||
		(*Client).Close()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteProtoMessage compresses and writes a protobuf message to Redis
 | 
			
		||||
func WriteProtoMessage(ctx context.Context, key string, message proto.Message, ttl ...time.Duration) error {
 | 
			
		||||
	if Client == nil {
 | 
			
		||||
		return fmt.Errorf("redis client not initialized")
 | 
			
		||||
	}
 | 
			
		||||
	if message == nil {
 | 
			
		||||
		return fmt.Errorf("message is nil")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Marshal protobuf message
 | 
			
		||||
	bytesMessage, err := proto.Marshal(message)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to marshal proto message: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Compress with zlib
 | 
			
		||||
	var buf bytes.Buffer
 | 
			
		||||
	w, err := zlib.NewWriterLevel(&buf, flate.BestCompression)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to create zlib writer: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer w.Close() // гарантированное закрытие
 | 
			
		||||
 | 
			
		||||
	if _, err := w.Write(bytesMessage); err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to write to zlib writer: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	if err := w.Close(); err != nil { // финализируем сжатие
 | 
			
		||||
		return fmt.Errorf("failed to close zlib writer: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var ttlDuration time.Duration
 | 
			
		||||
	if len(ttl) > 0 {
 | 
			
		||||
		ttlDuration = ttl[0]
 | 
			
		||||
	} else {
 | 
			
		||||
		ttlDuration = 3 * time.Hour // Default TTL of 24 hours
 | 
			
		||||
	}
 | 
			
		||||
	// Write to Redis
 | 
			
		||||
	if err := (*Client).Do(ctx, (*Client).B().
 | 
			
		||||
		Set().
 | 
			
		||||
		Key(key).
 | 
			
		||||
		Value(rueidis.BinaryString(buf.Bytes())).
 | 
			
		||||
		Ex(ttlDuration).
 | 
			
		||||
		Build()).
 | 
			
		||||
		Error(); err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to write compressed data to Redis: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReadProtoMessage reads and decompresses a protobuf message from Redis
 | 
			
		||||
func ReadProtoMessage(ctx context.Context, key string, message proto.Message) error {
 | 
			
		||||
	if Client == nil {
 | 
			
		||||
		return fmt.Errorf("redis client not initialized")
 | 
			
		||||
	}
 | 
			
		||||
	if message == nil {
 | 
			
		||||
		return fmt.Errorf("message is nil")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get bytes from Redis
 | 
			
		||||
	resp, err := (*Client).Do(ctx, (*Client).B().Get().Key(key).Build()).AsBytes()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to read data from Redis: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	if resp == nil {
 | 
			
		||||
		return fmt.Errorf("no data found for key: %s", key)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Decompress
 | 
			
		||||
	reader, err := zlib.NewReader(bytes.NewReader(resp))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to create zlib reader: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer reader.Close()
 | 
			
		||||
 | 
			
		||||
	decompressed, err := io.ReadAll(reader)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to decompress data: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Unmarshal protobuf
 | 
			
		||||
	if err := proto.Unmarshal(decompressed, message); err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to unmarshal proto message: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,10 @@
 | 
			
		||||
package redis
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"github.com/redis/rueidis"
 | 
			
		||||
	"github.com/redis/rueidis/rueidislock"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var Locker *rueidislock.Locker
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user