package main import ( "encoding/json" "fmt" "os" "time" badger "github.com/dgraph-io/badger/v4" "github.com/google/uuid" ) // StoredValue matches the structure in main.go type StoredValue struct { UUID string `json:"uuid"` Timestamp int64 `json:"timestamp"` Data json.RawMessage `json:"data"` } // Test utility to create conflicting data directly in BadgerDB func createConflictingData(dataDir1, dataDir2 string) error { // Same timestamp, different UUIDs timestamp := time.Now().UnixMilli() path := "test/conflict/data" // Data for node1 data1 := json.RawMessage(`{"message": "from node1", "value": 100}`) uuid1 := uuid.New().String() // Data for node2 (same timestamp, different UUID and content) data2 := json.RawMessage(`{"message": "from node2", "value": 200}`) uuid2 := uuid.New().String() // Store in node1's database err := storeConflictData(dataDir1, path, timestamp, uuid1, data1) if err != nil { return fmt.Errorf("failed to store in node1: %v", err) } // Store in node2's database err = storeConflictData(dataDir2, path, timestamp, uuid2, data2) if err != nil { return fmt.Errorf("failed to store in node2: %v", err) } fmt.Printf("Created conflict scenario:\n") fmt.Printf("Path: %s\n", path) fmt.Printf("Timestamp: %d\n", timestamp) fmt.Printf("Node1 UUID: %s, Data: %s\n", uuid1, string(data1)) fmt.Printf("Node2 UUID: %s, Data: %s\n", uuid2, string(data2)) return nil } func storeConflictData(dataDir, path string, timestamp int64, uuid string, data json.RawMessage) error { opts := badger.DefaultOptions(dataDir + "/badger") opts.Logger = nil db, err := badger.Open(opts) if err != nil { return err } defer db.Close() storedValue := StoredValue{ UUID: uuid, Timestamp: timestamp, Data: data, } valueBytes, err := json.Marshal(storedValue) if err != nil { return err } return db.Update(func(txn *badger.Txn) error { // Store main data if err := txn.Set([]byte(path), valueBytes); err != nil { return err } // Store timestamp index indexKey := fmt.Sprintf("_ts:%020d:%s", timestamp, path) return txn.Set([]byte(indexKey), []byte(uuid)) }) } func main() { if len(os.Args) < 3 { fmt.Println("Usage: go run test_conflict.go ") os.Exit(1) } err := createConflictingData(os.Args[1], os.Args[2]) if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } fmt.Println("Conflict data created successfully!") fmt.Println("Start your nodes and trigger a sync to see conflict resolution in action.") }