You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							516 lines
						
					
					
						
							13 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							516 lines
						
					
					
						
							13 KiB
						
					
					
				
								package offset
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"database/sql"
							 | 
						|
									"os"
							 | 
						|
									"testing"
							 | 
						|
									"time"
							 | 
						|
								
							 | 
						|
									_ "github.com/mattn/go-sqlite3" // SQLite driver
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/pb/schema_pb"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								func createTestDB(t *testing.T) *sql.DB {
							 | 
						|
									// Create temporary database file
							 | 
						|
									tmpFile, err := os.CreateTemp("", "offset_test_*.db")
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to create temp database file: %v", err)
							 | 
						|
									}
							 | 
						|
									tmpFile.Close()
							 | 
						|
								
							 | 
						|
									// Clean up the file when test completes
							 | 
						|
									t.Cleanup(func() {
							 | 
						|
										os.Remove(tmpFile.Name())
							 | 
						|
									})
							 | 
						|
								
							 | 
						|
									db, err := sql.Open("sqlite3", tmpFile.Name())
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to open database: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									t.Cleanup(func() {
							 | 
						|
										db.Close()
							 | 
						|
									})
							 | 
						|
								
							 | 
						|
									return db
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func createTestPartitionForSQL() *schema_pb.Partition {
							 | 
						|
									return &schema_pb.Partition{
							 | 
						|
										RingSize:   1024,
							 | 
						|
										RangeStart: 0,
							 | 
						|
										RangeStop:  31,
							 | 
						|
										UnixTimeNs: time.Now().UnixNano(),
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func TestSQLOffsetStorage_InitializeSchema(t *testing.T) {
							 | 
						|
									db := createTestDB(t)
							 | 
						|
								
							 | 
						|
									storage, err := NewSQLOffsetStorage(db)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to create SQL storage: %v", err)
							 | 
						|
									}
							 | 
						|
									defer storage.Close()
							 | 
						|
								
							 | 
						|
									// Verify tables were created
							 | 
						|
									tables := []string{
							 | 
						|
										"partition_offset_checkpoints",
							 | 
						|
										"offset_mappings",
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									for _, table := range tables {
							 | 
						|
										var count int
							 | 
						|
										err := db.QueryRow("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=?", table).Scan(&count)
							 | 
						|
										if err != nil {
							 | 
						|
											t.Fatalf("Failed to check table %s: %v", table, err)
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										if count != 1 {
							 | 
						|
											t.Errorf("Table %s was not created", table)
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func TestSQLOffsetStorage_SaveLoadCheckpoint(t *testing.T) {
							 | 
						|
									db := createTestDB(t)
							 | 
						|
									storage, err := NewSQLOffsetStorage(db)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to create SQL storage: %v", err)
							 | 
						|
									}
							 | 
						|
									defer storage.Close()
							 | 
						|
								
							 | 
						|
									partition := createTestPartitionForSQL()
							 | 
						|
								
							 | 
						|
									// Test saving checkpoint
							 | 
						|
									err = storage.SaveCheckpoint("test-namespace", "test-topic", partition, 100)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to save checkpoint: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Test loading checkpoint
							 | 
						|
									checkpoint, err := storage.LoadCheckpoint("test-namespace", "test-topic", partition)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to load checkpoint: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if checkpoint != 100 {
							 | 
						|
										t.Errorf("Expected checkpoint 100, got %d", checkpoint)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Test updating checkpoint
							 | 
						|
									err = storage.SaveCheckpoint("test-namespace", "test-topic", partition, 200)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to update checkpoint: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									checkpoint, err = storage.LoadCheckpoint("test-namespace", "test-topic", partition)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to load updated checkpoint: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if checkpoint != 200 {
							 | 
						|
										t.Errorf("Expected updated checkpoint 200, got %d", checkpoint)
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func TestSQLOffsetStorage_LoadCheckpointNotFound(t *testing.T) {
							 | 
						|
									db := createTestDB(t)
							 | 
						|
									storage, err := NewSQLOffsetStorage(db)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to create SQL storage: %v", err)
							 | 
						|
									}
							 | 
						|
									defer storage.Close()
							 | 
						|
								
							 | 
						|
									partition := createTestPartitionForSQL()
							 | 
						|
								
							 | 
						|
									// Test loading non-existent checkpoint
							 | 
						|
									_, err = storage.LoadCheckpoint("test-namespace", "test-topic", partition)
							 | 
						|
									if err == nil {
							 | 
						|
										t.Error("Expected error for non-existent checkpoint")
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func TestSQLOffsetStorage_SaveLoadOffsetMappings(t *testing.T) {
							 | 
						|
									db := createTestDB(t)
							 | 
						|
									storage, err := NewSQLOffsetStorage(db)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to create SQL storage: %v", err)
							 | 
						|
									}
							 | 
						|
									defer storage.Close()
							 | 
						|
								
							 | 
						|
									partition := createTestPartitionForSQL()
							 | 
						|
									partitionKey := partitionKey(partition)
							 | 
						|
								
							 | 
						|
									// Save multiple offset mappings
							 | 
						|
									mappings := []struct {
							 | 
						|
										offset    int64
							 | 
						|
										timestamp int64
							 | 
						|
										size      int32
							 | 
						|
									}{
							 | 
						|
										{0, 1000, 100},
							 | 
						|
										{1, 2000, 150},
							 | 
						|
										{2, 3000, 200},
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									for _, mapping := range mappings {
							 | 
						|
										err := storage.SaveOffsetMapping(partitionKey, mapping.offset, mapping.timestamp, mapping.size)
							 | 
						|
										if err != nil {
							 | 
						|
											t.Fatalf("Failed to save offset mapping: %v", err)
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Load offset mappings
							 | 
						|
									entries, err := storage.LoadOffsetMappings(partitionKey)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to load offset mappings: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if len(entries) != len(mappings) {
							 | 
						|
										t.Errorf("Expected %d entries, got %d", len(mappings), len(entries))
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Verify entries are sorted by offset
							 | 
						|
									for i, entry := range entries {
							 | 
						|
										expected := mappings[i]
							 | 
						|
										if entry.KafkaOffset != expected.offset {
							 | 
						|
											t.Errorf("Entry %d: expected offset %d, got %d", i, expected.offset, entry.KafkaOffset)
							 | 
						|
										}
							 | 
						|
										if entry.SMQTimestamp != expected.timestamp {
							 | 
						|
											t.Errorf("Entry %d: expected timestamp %d, got %d", i, expected.timestamp, entry.SMQTimestamp)
							 | 
						|
										}
							 | 
						|
										if entry.MessageSize != expected.size {
							 | 
						|
											t.Errorf("Entry %d: expected size %d, got %d", i, expected.size, entry.MessageSize)
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func TestSQLOffsetStorage_GetHighestOffset(t *testing.T) {
							 | 
						|
									db := createTestDB(t)
							 | 
						|
									storage, err := NewSQLOffsetStorage(db)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to create SQL storage: %v", err)
							 | 
						|
									}
							 | 
						|
									defer storage.Close()
							 | 
						|
								
							 | 
						|
									partition := createTestPartitionForSQL()
							 | 
						|
									partitionKey := TopicPartitionKey("test-namespace", "test-topic", partition)
							 | 
						|
								
							 | 
						|
									// Test empty partition
							 | 
						|
									_, err = storage.GetHighestOffset("test-namespace", "test-topic", partition)
							 | 
						|
									if err == nil {
							 | 
						|
										t.Error("Expected error for empty partition")
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Add some offset mappings
							 | 
						|
									offsets := []int64{5, 1, 3, 2, 4}
							 | 
						|
									for _, offset := range offsets {
							 | 
						|
										err := storage.SaveOffsetMapping(partitionKey, offset, offset*1000, 100)
							 | 
						|
										if err != nil {
							 | 
						|
											t.Fatalf("Failed to save offset mapping: %v", err)
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Get highest offset
							 | 
						|
									highest, err := storage.GetHighestOffset("test-namespace", "test-topic", partition)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to get highest offset: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if highest != 5 {
							 | 
						|
										t.Errorf("Expected highest offset 5, got %d", highest)
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func TestSQLOffsetStorage_GetOffsetMappingsByRange(t *testing.T) {
							 | 
						|
									db := createTestDB(t)
							 | 
						|
									storage, err := NewSQLOffsetStorage(db)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to create SQL storage: %v", err)
							 | 
						|
									}
							 | 
						|
									defer storage.Close()
							 | 
						|
								
							 | 
						|
									partition := createTestPartitionForSQL()
							 | 
						|
									partitionKey := partitionKey(partition)
							 | 
						|
								
							 | 
						|
									// Add offset mappings
							 | 
						|
									for i := int64(0); i < 10; i++ {
							 | 
						|
										err := storage.SaveOffsetMapping(partitionKey, i, i*1000, 100)
							 | 
						|
										if err != nil {
							 | 
						|
											t.Fatalf("Failed to save offset mapping: %v", err)
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Get range of offsets
							 | 
						|
									entries, err := storage.GetOffsetMappingsByRange(partitionKey, 3, 7)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to get offset range: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									expectedCount := 5 // offsets 3, 4, 5, 6, 7
							 | 
						|
									if len(entries) != expectedCount {
							 | 
						|
										t.Errorf("Expected %d entries, got %d", expectedCount, len(entries))
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Verify range
							 | 
						|
									for i, entry := range entries {
							 | 
						|
										expectedOffset := int64(3 + i)
							 | 
						|
										if entry.KafkaOffset != expectedOffset {
							 | 
						|
											t.Errorf("Entry %d: expected offset %d, got %d", i, expectedOffset, entry.KafkaOffset)
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func TestSQLOffsetStorage_GetPartitionStats(t *testing.T) {
							 | 
						|
									db := createTestDB(t)
							 | 
						|
									storage, err := NewSQLOffsetStorage(db)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to create SQL storage: %v", err)
							 | 
						|
									}
							 | 
						|
									defer storage.Close()
							 | 
						|
								
							 | 
						|
									partition := createTestPartitionForSQL()
							 | 
						|
									partitionKey := partitionKey(partition)
							 | 
						|
								
							 | 
						|
									// Test empty partition stats
							 | 
						|
									stats, err := storage.GetPartitionStats(partitionKey)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to get empty partition stats: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if stats.RecordCount != 0 {
							 | 
						|
										t.Errorf("Expected record count 0, got %d", stats.RecordCount)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if stats.EarliestOffset != -1 {
							 | 
						|
										t.Errorf("Expected earliest offset -1, got %d", stats.EarliestOffset)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Add some data
							 | 
						|
									sizes := []int32{100, 150, 200}
							 | 
						|
									for i, size := range sizes {
							 | 
						|
										err := storage.SaveOffsetMapping(partitionKey, int64(i), int64(i*1000), size)
							 | 
						|
										if err != nil {
							 | 
						|
											t.Fatalf("Failed to save offset mapping: %v", err)
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Get stats with data
							 | 
						|
									stats, err = storage.GetPartitionStats(partitionKey)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to get partition stats: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if stats.RecordCount != 3 {
							 | 
						|
										t.Errorf("Expected record count 3, got %d", stats.RecordCount)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if stats.EarliestOffset != 0 {
							 | 
						|
										t.Errorf("Expected earliest offset 0, got %d", stats.EarliestOffset)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if stats.LatestOffset != 2 {
							 | 
						|
										t.Errorf("Expected latest offset 2, got %d", stats.LatestOffset)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if stats.HighWaterMark != 3 {
							 | 
						|
										t.Errorf("Expected high water mark 3, got %d", stats.HighWaterMark)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									expectedTotalSize := int64(100 + 150 + 200)
							 | 
						|
									if stats.TotalSize != expectedTotalSize {
							 | 
						|
										t.Errorf("Expected total size %d, got %d", expectedTotalSize, stats.TotalSize)
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func TestSQLOffsetStorage_GetAllPartitions(t *testing.T) {
							 | 
						|
									db := createTestDB(t)
							 | 
						|
									storage, err := NewSQLOffsetStorage(db)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to create SQL storage: %v", err)
							 | 
						|
									}
							 | 
						|
									defer storage.Close()
							 | 
						|
								
							 | 
						|
									// Test empty database
							 | 
						|
									partitions, err := storage.GetAllPartitions()
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to get all partitions: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if len(partitions) != 0 {
							 | 
						|
										t.Errorf("Expected 0 partitions, got %d", len(partitions))
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Add data for multiple partitions
							 | 
						|
									partition1 := createTestPartitionForSQL()
							 | 
						|
									partition2 := &schema_pb.Partition{
							 | 
						|
										RingSize:   1024,
							 | 
						|
										RangeStart: 32,
							 | 
						|
										RangeStop:  63,
							 | 
						|
										UnixTimeNs: time.Now().UnixNano(),
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									partitionKey1 := partitionKey(partition1)
							 | 
						|
									partitionKey2 := partitionKey(partition2)
							 | 
						|
								
							 | 
						|
									storage.SaveOffsetMapping(partitionKey1, 0, 1000, 100)
							 | 
						|
									storage.SaveOffsetMapping(partitionKey2, 0, 2000, 150)
							 | 
						|
								
							 | 
						|
									// Get all partitions
							 | 
						|
									partitions, err = storage.GetAllPartitions()
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to get all partitions: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if len(partitions) != 2 {
							 | 
						|
										t.Errorf("Expected 2 partitions, got %d", len(partitions))
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Verify partition keys are present
							 | 
						|
									partitionMap := make(map[string]bool)
							 | 
						|
									for _, p := range partitions {
							 | 
						|
										partitionMap[p] = true
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if !partitionMap[partitionKey1] {
							 | 
						|
										t.Errorf("Partition key %s not found", partitionKey1)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if !partitionMap[partitionKey2] {
							 | 
						|
										t.Errorf("Partition key %s not found", partitionKey2)
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func TestSQLOffsetStorage_CleanupOldMappings(t *testing.T) {
							 | 
						|
									db := createTestDB(t)
							 | 
						|
									storage, err := NewSQLOffsetStorage(db)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to create SQL storage: %v", err)
							 | 
						|
									}
							 | 
						|
									defer storage.Close()
							 | 
						|
								
							 | 
						|
									partition := createTestPartitionForSQL()
							 | 
						|
									partitionKey := partitionKey(partition)
							 | 
						|
								
							 | 
						|
									// Add mappings with different timestamps
							 | 
						|
									now := time.Now().UnixNano()
							 | 
						|
								
							 | 
						|
									// Add old mapping by directly inserting with old timestamp
							 | 
						|
									oldTime := now - (24 * time.Hour).Nanoseconds() // 24 hours ago
							 | 
						|
									_, err = db.Exec(`
							 | 
						|
										INSERT INTO offset_mappings 
							 | 
						|
										(partition_key, kafka_offset, smq_timestamp, message_size, created_at)
							 | 
						|
										VALUES (?, ?, ?, ?, ?)
							 | 
						|
									`, partitionKey, 0, oldTime, 100, oldTime)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to insert old mapping: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Add recent mapping
							 | 
						|
									storage.SaveOffsetMapping(partitionKey, 1, now, 150)
							 | 
						|
								
							 | 
						|
									// Verify both mappings exist
							 | 
						|
									entries, err := storage.LoadOffsetMappings(partitionKey)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to load mappings: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if len(entries) != 2 {
							 | 
						|
										t.Errorf("Expected 2 mappings before cleanup, got %d", len(entries))
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Cleanup old mappings (older than 12 hours)
							 | 
						|
									cutoffTime := now - (12 * time.Hour).Nanoseconds()
							 | 
						|
									err = storage.CleanupOldMappings(cutoffTime)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to cleanup old mappings: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Verify only recent mapping remains
							 | 
						|
									entries, err = storage.LoadOffsetMappings(partitionKey)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to load mappings after cleanup: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if len(entries) != 1 {
							 | 
						|
										t.Errorf("Expected 1 mapping after cleanup, got %d", len(entries))
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if entries[0].KafkaOffset != 1 {
							 | 
						|
										t.Errorf("Expected remaining mapping offset 1, got %d", entries[0].KafkaOffset)
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func TestSQLOffsetStorage_Vacuum(t *testing.T) {
							 | 
						|
									db := createTestDB(t)
							 | 
						|
									storage, err := NewSQLOffsetStorage(db)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to create SQL storage: %v", err)
							 | 
						|
									}
							 | 
						|
									defer storage.Close()
							 | 
						|
								
							 | 
						|
									// Vacuum should not fail on empty database
							 | 
						|
									err = storage.Vacuum()
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to vacuum database: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Add some data and vacuum again
							 | 
						|
									partition := createTestPartitionForSQL()
							 | 
						|
									partitionKey := partitionKey(partition)
							 | 
						|
									storage.SaveOffsetMapping(partitionKey, 0, 1000, 100)
							 | 
						|
								
							 | 
						|
									err = storage.Vacuum()
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to vacuum database with data: %v", err)
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func TestSQLOffsetStorage_ConcurrentAccess(t *testing.T) {
							 | 
						|
									db := createTestDB(t)
							 | 
						|
									storage, err := NewSQLOffsetStorage(db)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to create SQL storage: %v", err)
							 | 
						|
									}
							 | 
						|
									defer storage.Close()
							 | 
						|
								
							 | 
						|
									partition := createTestPartitionForSQL()
							 | 
						|
									partitionKey := partitionKey(partition)
							 | 
						|
								
							 | 
						|
									// Test concurrent writes
							 | 
						|
									const numGoroutines = 10
							 | 
						|
									const offsetsPerGoroutine = 10
							 | 
						|
								
							 | 
						|
									done := make(chan bool, numGoroutines)
							 | 
						|
								
							 | 
						|
									for i := 0; i < numGoroutines; i++ {
							 | 
						|
										go func(goroutineID int) {
							 | 
						|
											defer func() { done <- true }()
							 | 
						|
								
							 | 
						|
											for j := 0; j < offsetsPerGoroutine; j++ {
							 | 
						|
												offset := int64(goroutineID*offsetsPerGoroutine + j)
							 | 
						|
												err := storage.SaveOffsetMapping(partitionKey, offset, offset*1000, 100)
							 | 
						|
												if err != nil {
							 | 
						|
													t.Errorf("Failed to save offset mapping %d: %v", offset, err)
							 | 
						|
													return
							 | 
						|
												}
							 | 
						|
											}
							 | 
						|
										}(i)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Wait for all goroutines to complete
							 | 
						|
									for i := 0; i < numGoroutines; i++ {
							 | 
						|
										<-done
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Verify all mappings were saved
							 | 
						|
									entries, err := storage.LoadOffsetMappings(partitionKey)
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Failed to load mappings: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									expectedCount := numGoroutines * offsetsPerGoroutine
							 | 
						|
									if len(entries) != expectedCount {
							 | 
						|
										t.Errorf("Expected %d mappings, got %d", expectedCount, len(entries))
							 | 
						|
									}
							 | 
						|
								}
							 |