snapshot of https://github.com/seaweedfs/seaweedfs.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
This commit is contained in:
412
test/kafka/internal/testutil/clients.go
Normal file
412
test/kafka/internal/testutil/clients.go
Normal file
@@ -0,0 +1,412 @@
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/IBM/sarama"
|
||||
"github.com/segmentio/kafka-go"
|
||||
)
|
||||
|
||||
const (
|
||||
consumerGroupHeartbeatInterval = 2 * time.Second
|
||||
consumerGroupSessionTimeout = 6 * time.Second
|
||||
consumerGroupRebalanceTimeout = 6 * time.Second
|
||||
consumerGroupJoinBackoff = 250 * time.Millisecond
|
||||
consumerGroupAttemptTimeout = 15 * time.Second
|
||||
)
|
||||
|
||||
// KafkaGoClient wraps kafka-go client with test utilities
|
||||
type KafkaGoClient struct {
|
||||
brokerAddr string
|
||||
t *testing.T
|
||||
}
|
||||
|
||||
// SaramaClient wraps Sarama client with test utilities
|
||||
type SaramaClient struct {
|
||||
brokerAddr string
|
||||
config *sarama.Config
|
||||
t *testing.T
|
||||
}
|
||||
|
||||
type ConsumeGroupRetryDebug struct {
|
||||
Attempt int
|
||||
MaxAttempts int
|
||||
Topic string
|
||||
GroupID string
|
||||
ExpectedCount int
|
||||
Err error
|
||||
}
|
||||
|
||||
// NewKafkaGoClient creates a new kafka-go test client
|
||||
func NewKafkaGoClient(t *testing.T, brokerAddr string) *KafkaGoClient {
|
||||
return &KafkaGoClient{
|
||||
brokerAddr: brokerAddr,
|
||||
t: t,
|
||||
}
|
||||
}
|
||||
|
||||
// NewSaramaClient creates a new Sarama test client with default config
|
||||
func NewSaramaClient(t *testing.T, brokerAddr string) *SaramaClient {
|
||||
config := sarama.NewConfig()
|
||||
config.Version = sarama.V2_8_0_0
|
||||
config.Producer.Return.Successes = true
|
||||
config.Consumer.Return.Errors = true
|
||||
config.Consumer.Offsets.Initial = sarama.OffsetOldest // Start from earliest when no committed offset
|
||||
|
||||
return &SaramaClient{
|
||||
brokerAddr: brokerAddr,
|
||||
config: config,
|
||||
t: t,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateTopic creates a topic using kafka-go
|
||||
func (k *KafkaGoClient) CreateTopic(topicName string, partitions int, replicationFactor int) error {
|
||||
k.t.Helper()
|
||||
|
||||
conn, err := kafka.Dial("tcp", k.brokerAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dial broker: %w", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
topicConfig := kafka.TopicConfig{
|
||||
Topic: topicName,
|
||||
NumPartitions: partitions,
|
||||
ReplicationFactor: replicationFactor,
|
||||
}
|
||||
|
||||
err = conn.CreateTopics(topicConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create topic: %w", err)
|
||||
}
|
||||
|
||||
k.t.Logf("Created topic %s with %d partitions", topicName, partitions)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ProduceMessages produces messages using kafka-go
|
||||
func (k *KafkaGoClient) ProduceMessages(topicName string, messages []kafka.Message) error {
|
||||
k.t.Helper()
|
||||
|
||||
writer := &kafka.Writer{
|
||||
Addr: kafka.TCP(k.brokerAddr),
|
||||
Topic: topicName,
|
||||
Balancer: &kafka.LeastBytes{},
|
||||
BatchTimeout: 50 * time.Millisecond,
|
||||
RequiredAcks: kafka.RequireOne,
|
||||
}
|
||||
defer writer.Close()
|
||||
|
||||
// Increased timeout to handle slow CI environments, especially when consumer groups
|
||||
// are active and holding locks or requiring offset commits
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
err := writer.WriteMessages(ctx, messages...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("write messages: %w", err)
|
||||
}
|
||||
|
||||
k.t.Logf("Produced %d messages to topic %s", len(messages), topicName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConsumeMessages consumes messages using kafka-go
|
||||
func (k *KafkaGoClient) ConsumeMessages(topicName string, expectedCount int) ([]kafka.Message, error) {
|
||||
k.t.Helper()
|
||||
|
||||
reader := kafka.NewReader(kafka.ReaderConfig{
|
||||
Brokers: []string{k.brokerAddr},
|
||||
Topic: topicName,
|
||||
Partition: 0, // Explicitly set partition 0 for simple consumption
|
||||
StartOffset: kafka.FirstOffset,
|
||||
MinBytes: 1,
|
||||
MaxBytes: 10e6,
|
||||
})
|
||||
defer reader.Close()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var messages []kafka.Message
|
||||
for i := 0; i < expectedCount; i++ {
|
||||
msg, err := reader.ReadMessage(ctx)
|
||||
if err != nil {
|
||||
return messages, fmt.Errorf("read message %d: %w", i, err)
|
||||
}
|
||||
messages = append(messages, msg)
|
||||
}
|
||||
|
||||
k.t.Logf("Consumed %d messages from topic %s", len(messages), topicName)
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
// ConsumeWithGroup consumes messages using consumer group.
|
||||
// Retries the initial join+fetch with a fresh reader if it fails before any
|
||||
// message is received — re-joining an existing group races with the previous
|
||||
// member's LeaveGroup / session cleanup and can surface as an i/o timeout on
|
||||
// the first FetchMessage.
|
||||
func (k *KafkaGoClient) ConsumeWithGroup(topicName, groupID string, expectedCount int) ([]kafka.Message, error) {
|
||||
return k.consumeWithGroup(topicName, groupID, expectedCount, nil, nil)
|
||||
}
|
||||
|
||||
// ConsumeWithGroupDebug runs ConsumeWithGroup with diagnostic hooks.
|
||||
// - onRetry fires after each failed attempt; the snapshot is post-LeaveGroup
|
||||
// because reader.Close() has already run by then (group will look Empty).
|
||||
// - onTick fires every ~1.5s while an attempt is in flight, so the caller
|
||||
// can observe live group state during the join/sync/fetch cycle — the
|
||||
// only place we get to see PreparingRebalance / CompletingRebalance churn.
|
||||
func (k *KafkaGoClient) ConsumeWithGroupDebug(topicName, groupID string, expectedCount int, onRetry func(ConsumeGroupRetryDebug), onTick func()) ([]kafka.Message, error) {
|
||||
return k.consumeWithGroup(topicName, groupID, expectedCount, onRetry, onTick)
|
||||
}
|
||||
|
||||
func (k *KafkaGoClient) consumeWithGroup(topicName, groupID string, expectedCount int, onRetry func(ConsumeGroupRetryDebug), onTick func()) ([]kafka.Message, error) {
|
||||
k.t.Helper()
|
||||
|
||||
const maxJoinAttempts = 5
|
||||
var lastErr error
|
||||
for attempt := 1; attempt <= maxJoinAttempts; attempt++ {
|
||||
messages, err, progressed := k.consumeWithGroupOnce(topicName, groupID, expectedCount, onTick)
|
||||
if err == nil {
|
||||
return messages, nil
|
||||
}
|
||||
lastErr = err
|
||||
// Only retry if we failed before any message was received. Once we've
|
||||
// fetched at least one message, a partial result is more useful than a
|
||||
// full retry (which would start over from the last committed offset).
|
||||
if progressed {
|
||||
return messages, err
|
||||
}
|
||||
if onRetry != nil {
|
||||
onRetry(ConsumeGroupRetryDebug{
|
||||
Attempt: attempt,
|
||||
MaxAttempts: maxJoinAttempts,
|
||||
Topic: topicName,
|
||||
GroupID: groupID,
|
||||
ExpectedCount: expectedCount,
|
||||
Err: err,
|
||||
})
|
||||
}
|
||||
if attempt == maxJoinAttempts {
|
||||
break
|
||||
}
|
||||
backoff := time.Duration(500*(1<<(attempt-1))) * time.Millisecond
|
||||
k.t.Logf("ConsumeWithGroup join attempt %d/%d failed (%v) — retrying after %v", attempt, maxJoinAttempts, err, backoff)
|
||||
time.Sleep(backoff)
|
||||
}
|
||||
return nil, lastErr
|
||||
}
|
||||
|
||||
// consumeWithGroupOnce runs a single consume attempt. Returns the messages
|
||||
// fetched, any error, and whether any message was received (used to decide
|
||||
// whether a retry is safe).
|
||||
func (k *KafkaGoClient) consumeWithGroupOnce(topicName, groupID string, expectedCount int, onTick func()) ([]kafka.Message, error, bool) {
|
||||
// Give each reader its own ClientID so restarts do not get mistaken for the
|
||||
// still-shutting-down reader they are replacing.
|
||||
dialer := &kafka.Dialer{
|
||||
ClientID: fmt.Sprintf("seaweedfs-e2e-%s-%d", groupID, time.Now().UnixNano()),
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
reader := kafka.NewReader(kafka.ReaderConfig{
|
||||
Brokers: []string{k.brokerAddr},
|
||||
Dialer: dialer,
|
||||
Topic: topicName,
|
||||
GroupID: groupID,
|
||||
MinBytes: 1,
|
||||
MaxBytes: 10e6,
|
||||
CommitInterval: 500 * time.Millisecond,
|
||||
HeartbeatInterval: consumerGroupHeartbeatInterval,
|
||||
SessionTimeout: consumerGroupSessionTimeout,
|
||||
RebalanceTimeout: consumerGroupRebalanceTimeout,
|
||||
JoinGroupBackoff: consumerGroupJoinBackoff,
|
||||
})
|
||||
defer reader.Close()
|
||||
|
||||
offset := reader.Offset()
|
||||
k.t.Logf("Consumer group reader created for group %s, initial offset: %d", groupID, offset)
|
||||
|
||||
// Keep each attempt short enough that a retry can outlive a stale group
|
||||
// member instead of burning most of the overall test timeout on one try.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), consumerGroupAttemptTimeout)
|
||||
defer cancel()
|
||||
|
||||
// While the reader is still alive (i.e. before defer reader.Close() runs),
|
||||
// periodically invoke onTick so the caller can snapshot the gateway's view
|
||||
// of the group during the join/sync/fetch cycle. Stop it before reader.Close
|
||||
// fires — defers run LIFO, so this defer comes after the reader.Close defer.
|
||||
if onTick != nil {
|
||||
tickStop := make(chan struct{})
|
||||
tickDone := make(chan struct{})
|
||||
go func() {
|
||||
defer close(tickDone)
|
||||
ticker := time.NewTicker(1500 * time.Millisecond)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-tickStop:
|
||||
return
|
||||
case <-ticker.C:
|
||||
onTick()
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
close(tickStop)
|
||||
<-tickDone
|
||||
}()
|
||||
}
|
||||
|
||||
var messages []kafka.Message
|
||||
for i := 0; i < expectedCount; i++ {
|
||||
msg, err := reader.FetchMessage(ctx)
|
||||
if err != nil {
|
||||
return messages, fmt.Errorf("read message %d: %w", i, err), len(messages) > 0
|
||||
}
|
||||
messages = append(messages, msg)
|
||||
k.t.Logf(" Fetched message %d: offset=%d, partition=%d", i, msg.Offset, msg.Partition)
|
||||
|
||||
var commitErr error
|
||||
for attempt := 0; attempt < 3; attempt++ {
|
||||
commitErr = reader.CommitMessages(ctx, msg)
|
||||
if commitErr == nil {
|
||||
k.t.Logf(" Committed offset %d (attempt %d)", msg.Offset, attempt+1)
|
||||
break
|
||||
}
|
||||
k.t.Logf(" Commit attempt %d failed for offset %d: %v", attempt+1, msg.Offset, commitErr)
|
||||
time.Sleep(time.Duration(50*(1<<attempt)) * time.Millisecond)
|
||||
}
|
||||
if commitErr != nil {
|
||||
return messages, fmt.Errorf("committing message %d: %w", i, commitErr), true
|
||||
}
|
||||
}
|
||||
|
||||
k.t.Logf("Consumed %d messages from topic %s with group %s", len(messages), topicName, groupID)
|
||||
return messages, nil, true
|
||||
}
|
||||
|
||||
// CreateTopic creates a topic using Sarama
|
||||
func (s *SaramaClient) CreateTopic(topicName string, partitions int32, replicationFactor int16) error {
|
||||
s.t.Helper()
|
||||
|
||||
admin, err := sarama.NewClusterAdmin([]string{s.brokerAddr}, s.config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create admin client: %w", err)
|
||||
}
|
||||
defer admin.Close()
|
||||
|
||||
topicDetail := &sarama.TopicDetail{
|
||||
NumPartitions: partitions,
|
||||
ReplicationFactor: replicationFactor,
|
||||
}
|
||||
|
||||
err = admin.CreateTopic(topicName, topicDetail, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create topic: %w", err)
|
||||
}
|
||||
|
||||
s.t.Logf("Created topic %s with %d partitions", topicName, partitions)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ProduceMessages produces messages using Sarama
|
||||
func (s *SaramaClient) ProduceMessages(topicName string, messages []string) error {
|
||||
s.t.Helper()
|
||||
|
||||
producer, err := sarama.NewSyncProducer([]string{s.brokerAddr}, s.config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create producer: %w", err)
|
||||
}
|
||||
defer producer.Close()
|
||||
|
||||
for i, msgText := range messages {
|
||||
msg := &sarama.ProducerMessage{
|
||||
Topic: topicName,
|
||||
Key: sarama.StringEncoder(fmt.Sprintf("Test message %d", i)),
|
||||
Value: sarama.StringEncoder(msgText),
|
||||
}
|
||||
|
||||
partition, offset, err := producer.SendMessage(msg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("send message %d: %w", i, err)
|
||||
}
|
||||
|
||||
s.t.Logf("Produced message %d: partition=%d, offset=%d", i, partition, offset)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ProduceMessageToPartition produces a single message to a specific partition using Sarama
|
||||
func (s *SaramaClient) ProduceMessageToPartition(topicName string, partition int32, message string) error {
|
||||
s.t.Helper()
|
||||
|
||||
producer, err := sarama.NewSyncProducer([]string{s.brokerAddr}, s.config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create producer: %w", err)
|
||||
}
|
||||
defer producer.Close()
|
||||
|
||||
msg := &sarama.ProducerMessage{
|
||||
Topic: topicName,
|
||||
Partition: partition,
|
||||
Key: sarama.StringEncoder(fmt.Sprintf("key-p%d", partition)),
|
||||
Value: sarama.StringEncoder(message),
|
||||
}
|
||||
|
||||
actualPartition, offset, err := producer.SendMessage(msg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("send message to partition %d: %w", partition, err)
|
||||
}
|
||||
|
||||
s.t.Logf("Produced message to partition %d: actualPartition=%d, offset=%d", partition, actualPartition, offset)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConsumeMessages consumes messages using Sarama
|
||||
func (s *SaramaClient) ConsumeMessages(topicName string, partition int32, expectedCount int) ([]string, error) {
|
||||
s.t.Helper()
|
||||
|
||||
consumer, err := sarama.NewConsumer([]string{s.brokerAddr}, s.config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create consumer: %w", err)
|
||||
}
|
||||
defer consumer.Close()
|
||||
|
||||
partitionConsumer, err := consumer.ConsumePartition(topicName, partition, sarama.OffsetOldest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create partition consumer: %w", err)
|
||||
}
|
||||
defer partitionConsumer.Close()
|
||||
|
||||
var messages []string
|
||||
timeout := time.After(30 * time.Second)
|
||||
|
||||
for len(messages) < expectedCount {
|
||||
select {
|
||||
case msg := <-partitionConsumer.Messages():
|
||||
messages = append(messages, string(msg.Value))
|
||||
case err := <-partitionConsumer.Errors():
|
||||
return messages, fmt.Errorf("consumer error: %w", err)
|
||||
case <-timeout:
|
||||
return messages, fmt.Errorf("timeout waiting for messages, got %d/%d", len(messages), expectedCount)
|
||||
}
|
||||
}
|
||||
|
||||
s.t.Logf("Consumed %d messages from topic %s", len(messages), topicName)
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
// GetConfig returns the Sarama configuration
|
||||
func (s *SaramaClient) GetConfig() *sarama.Config {
|
||||
return s.config
|
||||
}
|
||||
|
||||
// SetConfig sets a custom Sarama configuration
|
||||
func (s *SaramaClient) SetConfig(config *sarama.Config) {
|
||||
s.config = config
|
||||
}
|
||||
Reference in New Issue
Block a user